package agenttask import ( "context" "fmt" "strings" "testing" "time" ) func TestManagerS03S16MultiProjectManualResumeAndParallelTrace(t *testing.T) { projectA := testSnapshot( "project-a", "shared-workspace", testUnit("a-disjoint", WriteSetDisjoint), testUnit("a-overlap", WriteSetOverlap), ) projectB := testSnapshot( "project-b", "workspace-b", testUnit("b-unknown", WriteSetUnknown), ) unselected := testSnapshot( "unselected", "workspace-unselected", testUnit("must-not-run", WriteSetUnknown), ) harness := newHarness( t, map[ProjectID]ProjectWorkflowSnapshot{ "project-a": projectA, "project-b": projectB, "unselected": unselected, }, 3, ) for _, workID := range []WorkUnitID{"a-disjoint", "a-overlap", "b-unknown"} { harness.invoker.delays[workID] = 20 * time.Millisecond } harness.start("project-a", "shared-workspace", nil) harness.start("project-b", "workspace-b", nil) if err := harness.manager.Reconcile(context.Background()); err != nil { t.Fatalf("Reconcile: %v", err) } state := harness.store.snapshot() if state.Projects["project-a"].Status != ProjectStatusCompleted || state.Projects["project-b"].Status != ProjectStatusCompleted { t.Fatalf( "manual projects = %s/%s", state.Projects["project-a"].Status, state.Projects["project-b"].Status, ) } if state.Projects["unselected"].Status != ProjectStatusObserved { t.Fatalf("unselected project status = %s", state.Projects["unselected"].Status) } if harness.invoker.callCount() != 3 { t.Fatalf("invocations = %d, want selected work only", harness.invoker.callCount()) } if harness.invoker.maxConcurrency() < 2 { t.Fatalf("max concurrency = %d, want isolated parallel dispatch", harness.invoker.maxConcurrency()) } trace := make([]string, 0) for _, event := range harness.events.snapshot() { if event.Type != EventDispatchStarted && event.Type != EventIntegrationResult { continue } trace = append(trace, fmt.Sprintf( "%s:%s:%s:%d:%s:%s", event.Type, event.ProjectID, event.WorkUnitID, event.Ordinal, event.WriteSetKind, event.IsolationMode, )) if event.WorkUnitID == "must-not-run" { t.Fatalf("unselected work appeared in execution trace: %v", trace) } } joined := strings.Join(trace, "\n") for _, expected := range []string{"a-disjoint", "a-overlap", "b-unknown"} { if !strings.Contains(joined, expected) { t.Fatalf("trace missing %s:\n%s", expected, joined) } } t.Logf( "S03 trace: unselected_invocations=0 manual_projects=2 terminal=2; "+ "S16 trace: explicit_dependency_only=true isolated_parallel_max=%d integration_ordinals=%v\n%s", harness.invoker.maxConcurrency(), harness.integrator.ordinals(), joined, ) }