Files
runner_v/src/runner_test.v
Timur Gordon 010ecc7c71 initial commit
2025-08-26 14:47:52 +02:00

244 lines
6.1 KiB
V

module runner
import freeflowuniverse.herolib.core.redisclient
import freeflowuniverse.herolib.core.playbook {PlayBook}
import freeflowuniverse.herolib.baobab.engine { Engine, Context }
__global (
entries shared map[string]string
)
// Mock actor implementation for testing
struct TestActor implements Actor {
pub:
name string = 'test_actor'
pub mut:
redis_conn redisclient.Redis
}
// Implement the Actor interface
pub fn (mut actor TestActor) process_job(j job.Job) ! {
mut redis_conn := actor.redis_conn()!
// Update job status to started
job.update_status(mut redis_conn, j.id, .started) or {
return error('Failed to update job status to started: ${err}')
}
// Run the job using the engine
result := actor.engine.run_in_context(j.script,
db_path: actor.db_path
caller_id: j.caller_id
context_id: j.context_id
) or {
// Handle execution error
job.update_status(mut redis_conn, j.id, .error)!
job.set_error(mut redis_conn, j.id, '${err}')!
return err
}
// Update job status to finished and set result
job.update_status(mut redis_conn, j.id, .finished) or {
return error('Failed to update job status to finished: ${err}')
}
job.set_result(mut redis_conn, j.id, result) or {
return error('Failed to set job result: ${err}')
}
}
fn test_actor_interface_defaults() {
actor := TestActor{
name: 'test_actor'
}
// Test default values from interface
assert actor.name == 'test_actor'
}
fn test_actor_queue_key() {
actor := TestActor{
name: 'test_actor'
}
assert actor.queue_key()! == 'runner:test_actor'
}
// Mock player function for testing
fn mock_player(mut plbook PlayBook) ! {
// Simple test player that adds some content
action := plbook.get(filter:'entry.define')!
entries['entry'] = action.params.get!('entry')!
}
fn test_actor_run_job() {
mut e := Engine{
players: []
}
// Register a simple test player
e.register_player(mock_player) or { panic('Failed to register player: ${err}') }
actor := TestActor{
id: 'test_runner'
db_path: '/tmp/test_run.db'
engine: e
}
// Create a test job
test_job := job.new(
caller_id: 'test_caller',
context_id: 'test_context',
script: 'test script',
script_type: .v
)
// Run the job
result := actor.run_job(test_job) or { panic('Failed to run job: ${err}') }
assert result.len > 0
}
fn test_actor_run_job_with_context() {
mut engine := Engine{
players: []
}
// Register a player that uses context
engine.register_player(fn (mut plbook playbook.PlayBook) ! {
// This player might access context variables
plbook.add_result('Context-aware execution')
}) or { panic('Failed to register context player: ${err}') }
actor := TestActor{
id: 'context_actor'
db_path: '/tmp/context_test.db'
engine: engine
}
// Create a job with specific context
test_job := job.Job{
id: 'context_job_1'
caller_id: 'context_caller'
context_id: 'context_123'
script: 'context_script'
script_type: .osis
status: .dispatched
// ... other fields with defaults
}
result := actor.run_job(test_job) or { panic('Failed to run context job: ${err}') }
assert result.len > 0
}
fn test_actor_process_job_success() {
mut e := Engine{
players: []
}
// Register a successful player
e.register_player(fn (mut plbook playbook.PlayBook) ! {
plbook.add_result('Success!')
}) or { panic('Failed to register success player: ${err}') }
actor := TestActor{
id: 'success_actor'
engine: e
}
// Create test job
test_job := job.new_job('success_caller', 'success_context', 'success script', .v)
// Process the job
actor.process_job(test_job) or { panic('Failed to process job: ${err}') }
// Process the job
actor.process_job(test_job, mut mock_redis) or { panic('Failed to process job: ${err}') }
// Verify Redis operations were called
assert mock_redis.operations.len > 0
// Check that status was updated to started and then finished
job_key := 'hero:job:${test_job.id}'
assert mock_redis.job_status[job_key] == 'finished'
assert mock_redis.job_results[job_key].len > 0
}
fn test_actor_process_job_error() {
mut engine := Engine{
players: []
}
// Register a failing player
engine.register_player(fn (mut plbook playbook.PlayBook) ! {
return error('Test error')
}) or { panic('Failed to register failing player: ${err}') }
actor := TestActor{
id: 'error_actor'
engine: engine
}
// Create test job
test_job := job.new_job('error_caller', 'error_context', 'error script', .v)
// Mock Redis connection
mut mock_redis := MockRedisConn{
operations: []
job_status: map[string]string{}
job_results: map[string]string{}
job_errors: map[string]string{}
}
// Process the job (should handle error gracefully)
if result := actor.process_job(test_job, mut mock_redis) {
panic('Expected job processing to fail')
}
// Verify error was recorded
job_key := 'hero:job:${test_job.id}'
assert mock_redis.job_status[job_key] == 'error'
assert mock_redis.job_errors[job_key].len > 0
}
fn test_multiple_actors() {
mut engine1 := Engine{ players: [] }
mut engine2 := Engine{ players: [] }
engine1.register_player(fn (mut plbook playbook.PlayBook) ! {
plbook.add_result('Actor 1 result')
}) or { panic('Failed to register player 1: ${err}') }
engine2.register_player(fn (mut plbook playbook.PlayBook) ! {
plbook.add_result('Actor 2 result')
}) or { panic('Failed to register player 2: ${err}') }
actor1 := TestActor{
id: 'actor_1'
engine: engine1
}
actor2 := TestActor{
id: 'actor_2'
engine: engine2
}
// Test that actors have different queue keys
queue1 := actor1.queue_key() or { panic('Failed to get queue key 1: ${err}') }
queue2 := actor2.queue_key() or { panic('Failed to get queue key 2: ${err}') }
assert queue1 != queue2
assert queue1.contains('actor_1')
assert queue2.contains('actor_2')
// Test that actors can run jobs independently
job1 := job.new_job('caller1', 'context1', 'script1', .v)
job2 := job.new_job('caller2', 'context2', 'script2', .osis)
result1 := actor1.run_job(job1) or { panic('Failed to run job 1: ${err}') }
result2 := actor2.run_job(job2) or { panic('Failed to run job 2: ${err}') }
assert result1.len > 0
assert result2.len > 0
}