Files
enkly-ai/services/agent/internal/infrastructure/toolexec/workflow_test.go
enkly 79ce8dc4c0
Some checks failed
Go CI Pipeline / build_and_test (push) Failing after 22m0s
Init Project
2026-10-30 18:06:55 +01:00

119 lines
3.4 KiB
Go

package toolexec
import "testing"
func mustParseSteps(t *testing.T, raw []any) []workflowStep {
t.Helper()
steps, err := parseWorkflowSteps(raw)
if err != nil {
t.Fatalf("parseWorkflowSteps: unexpected error: %v", err)
}
return steps
}
func TestParseWorkflowSteps_Basic(t *testing.T) {
raw := []any{
map[string]any{"id": "a", "task": "do a"},
map[string]any{"id": "b", "task": "do b", "depends_on": []any{"a"}},
}
steps := mustParseSteps(t, raw)
if len(steps) != 2 {
t.Fatalf("got %d steps, want 2", len(steps))
}
if steps[1].DependsOn[0] != "a" {
t.Errorf("steps[1].DependsOn = %v, want [a]", steps[1].DependsOn)
}
}
func TestParseWorkflowSteps_Errors(t *testing.T) {
cases := []struct {
name string
raw []any
}{
{"empty", nil},
{"missing id", []any{map[string]any{"task": "x"}}},
{"missing task", []any{map[string]any{"id": "a"}}},
{"duplicate id", []any{
map[string]any{"id": "a", "task": "x"},
map[string]any{"id": "a", "task": "y"},
}},
{"not an object", []any{"not-an-object"}},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if _, err := parseWorkflowSteps(tc.raw); err == nil {
t.Errorf("parseWorkflowSteps(%s): expected an error, got nil", tc.name)
}
})
}
}
func TestParseWorkflowSteps_TooMany(t *testing.T) {
raw := make([]any, maxWorkflowSteps+1)
for i := range raw {
raw[i] = map[string]any{"id": string(rune('a' + i%26)), "task": "x"}
}
if _, err := parseWorkflowSteps(raw); err == nil {
t.Error("expected an error for exceeding maxWorkflowSteps")
}
}
func TestValidateDependencies_OK(t *testing.T) {
steps := mustParseSteps(t, []any{
map[string]any{"id": "a", "task": "x"},
map[string]any{"id": "b", "task": "x", "depends_on": []any{"a"}},
map[string]any{"id": "c", "task": "x", "depends_on": []any{"a", "b"}},
})
if err := validateDependencies(steps); err != nil {
t.Errorf("validateDependencies: unexpected error: %v", err)
}
}
func TestValidateDependencies_UnknownDep(t *testing.T) {
steps := mustParseSteps(t, []any{
map[string]any{"id": "a", "task": "x", "depends_on": []any{"nope"}},
})
if err := validateDependencies(steps); err == nil {
t.Error("expected an error for an unknown dependency")
}
}
func TestValidateDependencies_SelfDependency(t *testing.T) {
steps := mustParseSteps(t, []any{
map[string]any{"id": "a", "task": "x", "depends_on": []any{"a"}},
})
if err := validateDependencies(steps); err == nil {
t.Error("expected an error for a step depending on itself")
}
}
func TestValidateDependencies_Cycle(t *testing.T) {
steps := mustParseSteps(t, []any{
map[string]any{"id": "a", "task": "x", "depends_on": []any{"b"}},
map[string]any{"id": "b", "task": "x", "depends_on": []any{"a"}},
})
if err := validateDependencies(steps); err == nil {
t.Error("expected an error for a two-step cycle")
}
}
func TestDefaultWorkflowVerifier(t *testing.T) {
cases := []struct {
report string
wantOK bool
}{
{"", false},
{" ", false},
{"short", false},
{"(the sub-agent finished without writing a report — try a more specific task description)", false},
{"[step failed to run: context deadline exceeded]", false},
{"This is a plausible, substantial report with real findings in it about the codebase.", true},
}
for _, tc := range cases {
ok, reason := defaultWorkflowVerifier("some task", tc.report)
if ok != tc.wantOK {
t.Errorf("defaultWorkflowVerifier(%q) ok = %v (reason %q), want %v", tc.report, ok, reason, tc.wantOK)
}
}
}