- Marked the Executor Stub Enhancement section in TODO.md as complete, detailing the enhancements made to the executor's functionality. - Improved the Executor to simulate full execution with Job integration, including phase transitions and logging. - Introduced a Config struct for customizable executor behavior, allowing for testing with callbacks and job integration control. - Implemented phase-specific methods for modular execution, preparing for future real phase implementations. - Added comprehensive tests for the executor, including smoke tests and verification of phase progression and job logs. - Updated progress tracking in TODO.md to reflect the current status of the executor and integration testing.
126 lines
3.7 KiB
Go
126 lines
3.7 KiB
Go
package executor
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/yaoapp/yao/agent/robot/types"
|
|
)
|
|
|
|
// Smoke tests to verify basic flow works
|
|
// These tests use SkipJobIntegration=true to avoid DB dependencies
|
|
// Real integration tests are in manager_test.go and job_test.go
|
|
|
|
func TestExecutorSmoke(t *testing.T) {
|
|
exec := NewWithDelay(0)
|
|
robot := &types.Robot{
|
|
MemberID: "test-smoke",
|
|
TeamID: "team-1",
|
|
Config: &types.Config{Quota: &types.Quota{Max: 1}},
|
|
}
|
|
ctx := types.NewContext(context.Background(), nil)
|
|
|
|
result, err := exec.Execute(ctx, robot, types.TriggerClock, nil)
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, types.ExecCompleted, result.Status)
|
|
assert.Equal(t, types.TriggerClock, result.TriggerType)
|
|
|
|
// Clock trigger executes all phases (P0-P5)
|
|
assert.NotNil(t, result.Inspiration, "P0 should be executed for clock trigger")
|
|
assert.NotNil(t, result.Goals, "P1 should be executed")
|
|
assert.NotEmpty(t, result.Tasks, "P2 should generate tasks")
|
|
assert.NotEmpty(t, result.Results, "P3 should generate results")
|
|
assert.NotNil(t, result.Delivery, "P4 should be executed")
|
|
assert.NotEmpty(t, result.Learning, "P5 should be executed")
|
|
}
|
|
|
|
func TestExecutorHumanTriggerSkipsP0(t *testing.T) {
|
|
exec := NewWithDelay(0)
|
|
robot := &types.Robot{
|
|
MemberID: "test-human",
|
|
TeamID: "team-1",
|
|
Config: &types.Config{Quota: &types.Quota{Max: 1}},
|
|
}
|
|
ctx := types.NewContext(context.Background(), nil)
|
|
|
|
result, err := exec.Execute(ctx, robot, types.TriggerHuman, nil)
|
|
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, types.ExecCompleted, result.Status)
|
|
|
|
// Human trigger skips P0 (Inspiration)
|
|
assert.Nil(t, result.Inspiration, "P0 should be skipped for human trigger")
|
|
assert.NotNil(t, result.Goals, "P1 should be executed")
|
|
}
|
|
|
|
func TestExecutorEventTriggerSkipsP0(t *testing.T) {
|
|
exec := NewWithDelay(0)
|
|
robot := &types.Robot{
|
|
MemberID: "test-event",
|
|
TeamID: "team-1",
|
|
Config: &types.Config{Quota: &types.Quota{Max: 1}},
|
|
}
|
|
ctx := types.NewContext(context.Background(), nil)
|
|
|
|
result, err := exec.Execute(ctx, robot, types.TriggerEvent, nil)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Nil(t, result.Inspiration, "P0 should be skipped for event trigger")
|
|
assert.NotNil(t, result.Goals)
|
|
}
|
|
|
|
func TestExecutorNilRobot(t *testing.T) {
|
|
exec := NewWithDelay(0)
|
|
ctx := types.NewContext(context.Background(), nil)
|
|
|
|
result, err := exec.Execute(ctx, nil, types.TriggerClock, nil)
|
|
|
|
assert.Error(t, err)
|
|
assert.Nil(t, result)
|
|
assert.Contains(t, err.Error(), "robot cannot be nil")
|
|
}
|
|
|
|
func TestExecutorSimulatedFailure(t *testing.T) {
|
|
exec := NewWithDelay(0)
|
|
robot := &types.Robot{
|
|
MemberID: "test-fail",
|
|
TeamID: "team-1",
|
|
Config: &types.Config{Quota: &types.Quota{Max: 1}},
|
|
}
|
|
ctx := types.NewContext(context.Background(), nil)
|
|
|
|
// Pass "simulate_failure" to trigger simulated failure
|
|
result, err := exec.Execute(ctx, robot, types.TriggerClock, "simulate_failure")
|
|
|
|
assert.NoError(t, err) // Execute returns nil error, failure is in result
|
|
assert.NotNil(t, result)
|
|
assert.Equal(t, types.ExecFailed, result.Status)
|
|
assert.Equal(t, "simulated failure", result.Error)
|
|
}
|
|
|
|
func TestExecutorCounters(t *testing.T) {
|
|
exec := NewWithDelay(0)
|
|
robot := &types.Robot{
|
|
MemberID: "test-counter",
|
|
TeamID: "team-1",
|
|
Config: &types.Config{Quota: &types.Quota{Max: 10}},
|
|
}
|
|
ctx := types.NewContext(context.Background(), nil)
|
|
|
|
assert.Equal(t, 0, exec.ExecCount())
|
|
assert.Equal(t, 0, exec.CurrentCount())
|
|
|
|
_, _ = exec.Execute(ctx, robot, types.TriggerClock, nil)
|
|
assert.Equal(t, 1, exec.ExecCount())
|
|
assert.Equal(t, 0, exec.CurrentCount()) // Completed, so 0
|
|
|
|
_, _ = exec.Execute(ctx, robot, types.TriggerClock, nil)
|
|
assert.Equal(t, 2, exec.ExecCount())
|
|
|
|
exec.Reset()
|
|
assert.Equal(t, 0, exec.ExecCount())
|
|
}
|