From c49784790f1aece9c4fbc31628d896afd8cca220 Mon Sep 17 00:00:00 2001 From: omartelo Date: Sat, 17 Oct 2026 16:04:01 -0300 Subject: [PATCH] test(relay): run the suite in parallel --- internal/relay/compose_lang_test.go | 4 ++ internal/relay/focus_test.go | 3 + internal/relay/gaps_test.go | 7 ++ internal/relay/handover_race_test.go | 2 + internal/relay/hangup_test.go | 10 +++ internal/relay/insert_test.go | 15 ++++ internal/relay/later_test.go | 11 +++ internal/relay/merged_test.go | 4 ++ internal/relay/notice_lang_test.go | 4 ++ internal/relay/private_test.go | 7 ++ internal/relay/relay_test.go | 100 +++++++++++++++++++++++++++ internal/relay/resume_test.go | 4 ++ internal/relay/rostername_test.go | 4 ++ internal/relay/status_test.go | 8 +++ internal/relay/subagent_test.go | 15 ++++ internal/relay/viamod_test.go | 18 +++++ internal/relay/workeranswer_test.go | 27 ++++++++ internal/relay/workerclosed_test.go | 4 ++ 18 files changed, 247 insertions(+) diff --git a/internal/relay/compose_lang_test.go b/internal/relay/compose_lang_test.go index 3f63771d..1e4c908d 100644 --- a/internal/relay/compose_lang_test.go +++ b/internal/relay/compose_lang_test.go @@ -12,6 +12,7 @@ import ( // SpawnBriefing): a translation that brings a double quote or an angle bracket // in breaks every Windows spawn of a .cmd provider in that language. func TestSpawnBriefingIsCmdSafeInEveryLanguage(t *testing.T) { + t.Parallel() for _, lang := range prompt.Langs { for _, route := range []SubagentRoute{RouteSessions, RouteCards, RouteNative} { for _, hasTools := range []bool{true, false} { @@ -28,6 +29,7 @@ func TestSpawnBriefingIsCmdSafeInEveryLanguage(t *testing.T) { // format that drops or misnumbers one shows as %!, which an agent would read as // part of the instruction. func TestEveryMessageRendersInEveryLanguage(t *testing.T) { + t.Parallel() for _, lang := range prompt.Langs { messages := []string{ compose(lang, "", "t1", "task", false), @@ -56,6 +58,7 @@ func TestEveryMessageRendersInEveryLanguage(t *testing.T) { // The language is read when a message is composed, not when the relay starts, // so a change in Settings reaches the next message. func TestTheRelayTypesInThePromptLanguageReadLive(t *testing.T) { + t.Parallel() term := newFakeTerminal("s2") svc := newRelay(workspace(), term, nil) lang := prompt.English @@ -76,6 +79,7 @@ func TestTheRelayTypesInThePromptLanguageReadLive(t *testing.T) { // Russian's one form also covers 21, so the nudge prints the count in every // form and the noun agrees with it. func TestTheRussianNudgeAgreesWithItsCount(t *testing.T) { + t.Parallel() for count, want := range map[int]string{ 1: "1 отправленная вами задача готова", 2: "2 отправленные вами задачи готовы", 5: "5 отправленных вами задач готовы", 11: "11 отправленных вами задач готовы", diff --git a/internal/relay/focus_test.go b/internal/relay/focus_test.go index 6f860bf7..ff53584e 100644 --- a/internal/relay/focus_test.go +++ b/internal/relay/focus_test.go @@ -6,6 +6,7 @@ import ( ) func TestFocusOpensTheCardAndRaisesTheWindow(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), newFakeTerminal("s1", "s2", "s3"), events) var order []string @@ -36,6 +37,7 @@ func TestFocusOpensTheCardAndRaisesTheWindow(t *testing.T) { } func TestFocusNamesTheLiveSessionsWhenTheTargetIsUnknown(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), newFakeTerminal("s1", "s3"), events) raised := false @@ -51,6 +53,7 @@ func TestFocusNamesTheLiveSessionsWhenTheTargetIsUnknown(t *testing.T) { } func TestFocusWorksWithoutAWindow(t *testing.T) { + t.Parallel() svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), newFakeTerminal("s3"), nil) if got, err := svc.Focus(FocusOptions{Target: "solo", Project: "revu"}); err != nil || got.ID != "s3" { diff --git a/internal/relay/gaps_test.go b/internal/relay/gaps_test.go index 1bd6ac37..b7d32c4f 100644 --- a/internal/relay/gaps_test.go +++ b/internal/relay/gaps_test.go @@ -13,6 +13,7 @@ import ( // comes later, on the same ticket, and has to reach the sender rather than be // refused as an unknown ticket. func TestAnAnswerAfterTheTurnEndedWithoutOneStillReachesTheSender(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -44,6 +45,7 @@ func TestAnAnswerAfterTheTurnEndedWithoutOneStillReachesTheSender(t *testing.T) // A late answer is still one answer: a second one on the same ticket is refused. func TestALateAnswerIsTakenOnce(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) sent, _ := svc.Send(context.Background(), SendOptions{From: "s1", Target: "docs", Prompt: "run the tests", WaitSeconds: 1}) svc.Observe("s2", "busy") @@ -61,6 +63,7 @@ func TestALateAnswerIsTakenOnce(t *testing.T) { // waiter used to be told the errand was still in progress on a ticket the sweep // had already dropped, so the next wait on it answered "unknown ticket". func TestATicketBeingWaitedOnOutlivesItsHour(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plant(svc, "t1", "s1", "s2", "docs") start := time.Now() @@ -101,6 +104,7 @@ func TestATicketBeingWaitedOnOutlivesItsHour(t *testing.T) { // answering then is answering something else, and attributing it to the // message mid-delivery sends the sender a report of work nobody did. func TestATicketlessAnswerSkipsAMessageStillBeingDelivered(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.submitDelay = 5 * time.Millisecond @@ -128,6 +132,7 @@ func TestATicketlessAnswerSkipsAMessageStillBeingDelivered(t *testing.T) { // ticket is unknown: the ticket still takes a late answer for an hour, and a // caller handed "expired" would stop looking for it. func TestAWaitOnALapsedTicketIsToldItWentUnanswered(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) sent, _ := svc.SendPrivate(context.Background(), SendOptions{From: "s1", Target: "docs", Prompt: "run the tests", WaitSeconds: 1}) svc.Observe("s2", "busy") @@ -149,6 +154,7 @@ func TestAWaitOnALapsedTicketIsToldItWentUnanswered(t *testing.T) { // A caller hanging up as the turn ends, with the late answer landing in // between, must not have its leaving overwrite that answer with the stall. func TestALateAnswerSurvivesTheWaiterHangingUp(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) tk := &ticket{ fromID: "s1", targetID: "s2", target: "docs", @@ -176,6 +182,7 @@ func TestALateAnswerSurvivesTheWaiterHangingUp(t *testing.T) { // A ticket that ages out unanswered, open or lapsed, answers a wait on it with // how it ended: "unknown ticket" would read as a ticket the caller mistyped. func TestAWaitOnAnExpiredTicketSaysItExpired(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) plant(svc, "open", "s1", "s2", "docs") plant(svc, "lapsed", "s1", "s3", "api") diff --git a/internal/relay/handover_race_test.go b/internal/relay/handover_race_test.go index 2d995202..1979f505 100644 --- a/internal/relay/handover_race_test.go +++ b/internal/relay/handover_race_test.go @@ -34,6 +34,7 @@ func (g *gatedEvents) Emit(_ string, data any) { // two critical sections apart, and a Wait between them found neither: "unknown // ticket" for an errand that had just been answered. func TestAWaitAsTheAnswerLandsNeverSeesAnUnknownTicket(t *testing.T) { + t.Parallel() events := &gatedEvents{gate: "s2", reached: make(chan struct{}), release: make(chan struct{})} svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), events) plant(svc, "t1", "s1", "s2", "docs") @@ -64,6 +65,7 @@ func TestAWaitAsTheAnswerLandsNeverSeesAnUnknownTicket(t *testing.T) { // ticket's marks are cleared after the lock is let go and before await runs, // and holding that event parks the Wait there while the answer lands. func TestAnAnswerAWaitCarriedOutIsNotAlsoFiled(t *testing.T) { + t.Parallel() events := &gatedEvents{gate: "s3", reached: make(chan struct{}), release: make(chan struct{})} svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), events) plant(svc, "t1", "s1", "s2", "docs") diff --git a/internal/relay/hangup_test.go b/internal/relay/hangup_test.go index 56638d8b..7ebc3e37 100644 --- a/internal/relay/hangup_test.go +++ b/internal/relay/hangup_test.go @@ -63,6 +63,7 @@ func assertStashedAndNudged(t *testing.T, svc *Service, term *fakeTerminal, answ } func TestACollectWhoseCallerHungUpLeavesTheNextResultToTheNudge(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -90,6 +91,7 @@ func TestACollectWhoseCallerHungUpLeavesTheNextResultToTheNudge(t *testing.T) { // nudge, and the collector then finds its caller gone. The result must not be // drained, and something still has to say it is there. func TestAResultTheHungUpCollectorWasWokenForIsStillNudged(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.mu.Lock() @@ -107,6 +109,7 @@ func TestAResultTheHungUpCollectorWasWokenForIsStillNudged(t *testing.T) { } func TestARenudgeLeavesAResultToTheCollectorStillHolding(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.mu.Lock() @@ -124,6 +127,7 @@ func TestARenudgeLeavesAResultToTheCollectorStillHolding(t *testing.T) { } func TestCollectNowReturnsAtOnceWithWhoStillOwes(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -149,6 +153,7 @@ func TestCollectNowReturnsAtOnceWithWhoStillOwes(t *testing.T) { } func TestCollectNowRefusesACallerWithNoSession(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal(), nil) if _, err := svc.CollectNow(CollectNowOptions{}); err == nil { @@ -157,6 +162,7 @@ func TestCollectNowRefusesACallerWithNoSession(t *testing.T) { } func TestAWaitWhoseCallerHungUpLeavesTheAnswerToTheInbox(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -184,6 +190,7 @@ func TestAWaitWhoseCallerHungUpLeavesTheAnswerToTheInbox(t *testing.T) { // frozen clock is the case the timer path has to end on its own: a deadline // read off a clock that never moves would otherwise hold the line forever. func TestACollectWhoseWaitRunsOutReturnsWhoStillOwes(t *testing.T) { + t.Parallel() for _, tt := range []struct { name string clock func() time.Time @@ -219,6 +226,7 @@ func TestACollectWhoseWaitRunsOutReturnsWhoStillOwes(t *testing.T) { // and never read) had that news meant for its caller; with the caller gone it // goes to the inbox. func TestAnAbandonedWaitStashesTheOutcomeItWasHolding(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -246,6 +254,7 @@ func TestAnAbandonedWaitStashesTheOutcomeItWasHolding(t *testing.T) { // Another caller still holding the ticket carries the outcome out itself, so // one hanging up must not also stash it. func TestAnAbandonedWaitLeavesTheOutcomeToAnotherWaiter(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -271,6 +280,7 @@ func TestAnAbandonedWaitLeavesTheOutcomeToAnotherWaiter(t *testing.T) { // not only when one finishes: Esc is how a wait for results is abandoned, and // the next turn end may be a long way off. func TestAnInterruptedSenderIsNudged(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.Observe("s1", stateBusy) diff --git a/internal/relay/insert_test.go b/internal/relay/insert_test.go index 86d8a9b5..5ce1103f 100644 --- a/internal/relay/insert_test.go +++ b/internal/relay/insert_test.go @@ -25,6 +25,7 @@ func editorWorkspace(root, worktree string) fakeSessions { } func TestInsertPastesWithoutSubmitting(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), term, nil) @@ -42,6 +43,7 @@ func TestInsertPastesWithoutSubmitting(t *testing.T) { } func TestInsertStripsWhatWouldBreakOutOfThePaste(t *testing.T) { + t.Parallel() term := newFakeTerminal("s3") svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), term, nil) @@ -54,6 +56,7 @@ func TestInsertStripsWhatWouldBreakOutOfThePaste(t *testing.T) { } func TestInsertRefusesWhatItCannotPaste(t *testing.T) { + t.Parallel() svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), newFakeTerminal("s3"), nil) if _, err := svc.Insert(InsertOptions{Target: "solo", Text: " \n\x1b "}); err == nil { @@ -69,6 +72,7 @@ func TestInsertRefusesWhatItCannotPaste(t *testing.T) { } func TestInsertFindsTheSessionByProjectName(t *testing.T) { + t.Parallel() term := newFakeTerminal("s3") svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), term, nil) @@ -79,6 +83,7 @@ func TestInsertFindsTheSessionByProjectName(t *testing.T) { } func TestInsertByDirectoryPrefersTheSessionRunningThere(t *testing.T) { + t.Parallel() root := t.TempDir() worktree := filepath.Join(root, "wt") if err := os.Mkdir(worktree, 0o755); err != nil { @@ -102,6 +107,7 @@ func TestInsertByDirectoryPrefersTheSessionRunningThere(t *testing.T) { } func TestInsertNamesEveryCandidateWhenTheDirectoryIsAmbiguous(t *testing.T) { + t.Parallel() root := t.TempDir() work := fakeSessions{projects: []store.Project{ {ID: "p1", Name: "lich", Path: root, Sessions: []store.Session{ @@ -117,6 +123,7 @@ func TestInsertNamesEveryCandidateWhenTheDirectoryIsAmbiguous(t *testing.T) { } func TestInsertFallsBackToTheProjectsSessionsWhenNoneRunInTheDirectory(t *testing.T) { + t.Parallel() root := t.TempDir() work := fakeSessions{projects: []store.Project{ {ID: "p1", Name: "lich", Path: root, Sessions: []store.Session{ @@ -132,6 +139,7 @@ func TestInsertFallsBackToTheProjectsSessionsWhenNoneRunInTheDirectory(t *testin } func TestInsertFindsNothingInAnUnknownProject(t *testing.T) { + t.Parallel() svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), newFakeTerminal("s1"), nil) for _, project := range []string{"nope", "/not/a/project"} { @@ -146,6 +154,7 @@ func TestInsertFindsNothingInAnUnknownProject(t *testing.T) { } func TestInsertGoesInBesideTheUsersDraft(t *testing.T) { + t.Parallel() term := newFakeTerminal("s3") term.typeAt("s3", true) svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), term, nil) @@ -156,6 +165,7 @@ func TestInsertGoesInBesideTheUsersDraft(t *testing.T) { } func TestInsertRefusesASessionBlockedOnAPermission(t *testing.T) { + t.Parallel() term := newFakeTerminal("s3") svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), term, nil) svc.reported["s3"] = stateWaiting @@ -170,6 +180,7 @@ func TestInsertRefusesASessionBlockedOnAPermission(t *testing.T) { } func TestInsertGivesUpOnASessionThatNeverReachesItsPrompt(t *testing.T) { + t.Parallel() term := newFakeTerminal("s3") term.setUp("s3", true) svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), term, nil) @@ -184,6 +195,7 @@ func TestInsertGivesUpOnASessionThatNeverReachesItsPrompt(t *testing.T) { } func TestInsertSurfacesAWriteTheTerminalRefuses(t *testing.T) { + t.Parallel() term := newFakeTerminal("s3") term.writeErr = os.ErrClosed svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), term, nil) @@ -194,6 +206,7 @@ func TestInsertSurfacesAWriteTheTerminalRefuses(t *testing.T) { } func TestPeersCarryTheirDirectories(t *testing.T) { + t.Parallel() svc := newRelay(editorWorkspace("/src/lich", "/src/lich-wt"), newFakeTerminal("s1", "s2"), nil) peers, err := svc.Peers(PeersOptions{}) @@ -209,6 +222,7 @@ func TestPeersCarryTheirDirectories(t *testing.T) { } func TestSendNarrowsByProjectDirectory(t *testing.T) { + t.Parallel() root := t.TempDir() work := fakeSessions{projects: []store.Project{ {ID: "p1", Name: "a", Path: root, Sessions: []store.Session{{ID: "s1", Label: "api"}}}, @@ -223,6 +237,7 @@ func TestSendNarrowsByProjectDirectory(t *testing.T) { } func TestSamePath(t *testing.T) { + t.Parallel() dir := t.TempDir() link := filepath.Join(t.TempDir(), "link") linked := os.Symlink(dir, link) == nil diff --git a/internal/relay/later_test.go b/internal/relay/later_test.go index fc6c596e..2acdfc50 100644 --- a/internal/relay/later_test.go +++ b/internal/relay/later_test.go @@ -53,6 +53,7 @@ func at(unix int64) func() time.Time { } func TestDeliverDueTypesThePromptAndClearsTheRow(t *testing.T) { + t.Parallel() writer := &scheduleWriter{} term := newFakeTerminal("s1") events := &fakeEvents{} @@ -79,6 +80,7 @@ func TestDeliverDueTypesThePromptAndClearsTheRow(t *testing.T) { // The prompt is typed as the user wrote it: no sender, no ticket, none of the // envelope a relayed task carries. A scheduled prompt has nobody to report to. func TestDeliverDueTypesNoEnvelope(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1") svc := newRelay(scheduled(1000, "ship it", &scheduleWriter{}), term, nil) svc.now = at(1000) @@ -91,6 +93,7 @@ func TestDeliverDueTypesNoEnvelope(t *testing.T) { } func TestDeliverDueLeavesAPromptThatIsNotDueYet(t *testing.T) { + t.Parallel() writer := &scheduleWriter{} term := newFakeTerminal("s1") svc := newRelay(scheduled(1001, "later", writer), term, nil) @@ -110,6 +113,7 @@ func TestDeliverDueLeavesAPromptThatIsNotDueYet(t *testing.T) { // lich was closed. It arrives announced, because a reminder from three days ago // read as one written now is the trap being closed here. func TestDeliverDueTypesAnOverduePrompt(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1") svc := newRelay(scheduled(1000, "the overdue one", &scheduleWriter{}), term, nil) svc.now = at(1000 + 3*24*60*60) @@ -131,6 +135,7 @@ func TestDeliverDueTypesAnOverduePrompt(t *testing.T) { // A prompt found within one pass of its time is on time by every measure this // package can take, so it arrives as the user wrote it and nothing else. func TestDeliverDueTypesAnOnTimePromptBare(t *testing.T) { + t.Parallel() for name, now := range map[string]int64{ "to the second": 1000, "within a tick": 1000 + int64(scheduleTick/time.Second), @@ -153,6 +158,7 @@ func TestDeliverDueTypesAnOnTimePromptBare(t *testing.T) { // a prompt that just missed its pass, hours for one held over a working day, // days for one that waited out a closed lich. func TestLateNoticeWordsTheDelay(t *testing.T) { + t.Parallel() cases := map[string]struct { late int64 want string @@ -182,6 +188,7 @@ func TestLateNoticeWordsTheDelay(t *testing.T) { // A session with no prompt to type at keeps its schedule: the row is the only // copy of what the user wrote, and the next pass is when it lands. func TestDeliverDueKeepsThePromptWhileTheSessionIsNotReady(t *testing.T) { + t.Parallel() cases := map[string]func(*fakeTerminal){ "no PTY": func(term *fakeTerminal) { term.live["s1"] = false }, "setting up": func(term *fakeTerminal) { term.settingUp["s1"] = true }, @@ -210,6 +217,7 @@ func TestDeliverDueKeepsThePromptWhileTheSessionIsNotReady(t *testing.T) { // The clear is what stops a second pass typing the same prompt again, so a // clear that fails has to stop the delivery with it. func TestDeliverDueSkipsWhenTheRowCannotBeCleared(t *testing.T) { + t.Parallel() writer := &scheduleWriter{err: errors.New("database is locked")} term := newFakeTerminal("s1") svc := newRelay(scheduled(1000, "run it", writer), term, nil) @@ -223,6 +231,7 @@ func TestDeliverDueSkipsWhenTheRowCannotBeCleared(t *testing.T) { } func TestDeliverDueIgnoresSessionsWithNothingScheduled(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3", "s4") svc := newRelay(workspace(), term, nil) svc.now = at(1000) @@ -237,6 +246,7 @@ func TestDeliverDueIgnoresSessionsWithNothingScheduled(t *testing.T) { } func TestDeliverDueSurvivesAnUnreadableWorkspace(t *testing.T) { + t.Parallel() svc := newRelay(fakeSessions{err: errors.New("no database")}, newFakeTerminal("s1"), nil) svc.deliverDue() } @@ -247,6 +257,7 @@ func TestDeliverDueSurvivesAnUnreadableWorkspace(t *testing.T) { // first free prompt, and the row cleared is the resumed one: the id it was // scheduled under is gone. func TestDeliverDueTypesAPromptParkedThroughAResume(t *testing.T) { + t.Parallel() writer := &scheduleWriter{} sessions := fakeSessions{ projects: []store.Project{{ID: "p1", Name: "lich", Sessions: []store.Session{ diff --git a/internal/relay/merged_test.go b/internal/relay/merged_test.go index d7f05e67..a8e599cb 100644 --- a/internal/relay/merged_test.go +++ b/internal/relay/merged_test.go @@ -25,6 +25,7 @@ func merging() fakeSessions { } func TestAnnounceMergeTellsTheAgentsInTheMergedCheckout(t *testing.T) { + t.Parallel() term := newFakeTerminal("root", "agent", "modded", "shell", "other") term.attachMod("modded", ackedOK) svc := newRelay(merging(), term, nil) @@ -56,6 +57,7 @@ func TestAnnounceMergeTellsTheAgentsInTheMergedCheckout(t *testing.T) { } func TestAnnounceMergeReachesSessionsInTheProjectsOwnDirectory(t *testing.T) { + t.Parallel() term := newFakeTerminal("root", "agent") svc := newRelay(merging(), term, nil) @@ -72,6 +74,7 @@ func TestAnnounceMergeReachesSessionsInTheProjectsOwnDirectory(t *testing.T) { } func TestAnnounceMergeReportsAStoreFailure(t *testing.T) { + t.Parallel() svc := newRelay(fakeSessions{err: errors.New("disk gone")}, newFakeTerminal(), nil) if err := svc.AnnounceMerge("/wt/feat", 1, "x", "b", "main"); err == nil { @@ -80,6 +83,7 @@ func TestAnnounceMergeReportsAStoreFailure(t *testing.T) { } func TestMergeNoticeNamesThePullRequestAndAsksForNoWork(t *testing.T) { + t.Parallel() got := mergeNotice(prompt.English, 42, "Title \x1b[201~with escape", "feat/merge", "main") for _, want := range []string{"#42", "feat/merge", "merged into main", "not a task"} { diff --git a/internal/relay/notice_lang_test.go b/internal/relay/notice_lang_test.go index 1a1e3949..bc26ecc6 100644 --- a/internal/relay/notice_lang_test.go +++ b/internal/relay/notice_lang_test.go @@ -21,6 +21,7 @@ func other(lang prompt.Lang) prompt.Lang { // Every notice renders in every language with its arguments in place and the // [lich] token its readers match on. func TestEveryNoticeRendersInEveryLanguage(t *testing.T) { + t.Parallel() for _, lang := range prompt.Langs { entry := &inboxEntry{target: "docs", ticket: "t1", answer: "all done"} notices := map[string]string{ @@ -68,6 +69,7 @@ func TestEveryNoticeRendersInEveryLanguage(t *testing.T) { // A parked continuation is stored as text, so a row written in one language // must still be recognised, and dropped, once the setting is another. func TestAParkedContinuationIsRecognisedInEveryLanguage(t *testing.T) { + t.Parallel() for _, stored := range prompt.Langs { for _, setting := range prompt.Langs { writer := &parkWriter{} @@ -86,6 +88,7 @@ func TestAParkedContinuationIsRecognisedInEveryLanguage(t *testing.T) { } func TestAPersonsPromptIsNotTakenForTheContinuationInAnyLanguage(t *testing.T) { + t.Parallel() for _, setting := range prompt.Langs { writer := &parkWriter{} svc := newRelay(scheduledWith(5000, "ship the release notes", writer.set), newFakeTerminal("s1"), &fakeEvents{}) @@ -100,6 +103,7 @@ func TestAPersonsPromptIsNotTakenForTheContinuationInAnyLanguage(t *testing.T) { } func TestTheContinuationIsParkedInThePromptLanguage(t *testing.T) { + t.Parallel() for _, lang := range prompt.Langs { writer := &parkWriter{} svc := newRelay(scheduledWith(0, "", writer.set), newFakeTerminal("s1"), &fakeEvents{}) diff --git a/internal/relay/private_test.go b/internal/relay/private_test.go index e832c483..1f5fbd49 100644 --- a/internal/relay/private_test.go +++ b/internal/relay/private_test.go @@ -17,6 +17,7 @@ func plantPrivate(svc *Service, id, fromID, targetID, target string) { } func TestSendPrivateMarksItsResult(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) var ( @@ -44,6 +45,7 @@ func TestSendPrivateMarksItsResult(t *testing.T) { // session, which is how a workflow agent's sibling or the session's own agent // drains its inbox, must not take it, and the ticket still finds it after. func TestANoTicketCollectNeverTakesAPrivateResult(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantPrivate(svc, "t1", "s1", "s2", "docs") if err := svc.Reply(ReplyOptions{Ticket: "t1", Answer: "done"}); err != nil { @@ -70,6 +72,7 @@ func TestANoTicketCollectNeverTakesAPrivateResult(t *testing.T) { // The session's prompt does not speak for whoever sent privately, so nothing is // typed there and the card counts nothing it could not collect. func TestAPrivateResultIsNeverAnnounced(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") events := &fakeEvents{} svc := newRelay(workspace(), term, events) @@ -93,6 +96,7 @@ func TestAPrivateResultIsNeverAnnounced(t *testing.T) { } func TestACollectDoesNotHoldTheLineForAPrivateErrand(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantPrivate(svc, "t1", "s1", "s2", "docs") @@ -110,6 +114,7 @@ func TestACollectDoesNotHoldTheLineForAPrivateErrand(t *testing.T) { } func TestAnOrdinaryResultIsStillNudgedBesideAPrivateOne(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, nil) plantPrivate(svc, "t1", "s1", "s2", "docs") @@ -132,6 +137,7 @@ func TestAnOrdinaryResultIsStillNudgedBesideAPrivateOne(t *testing.T) { // Held for its ticket like any result, for as long, and dropped without a word: // nobody was ever told it existed. func TestAPrivateResultAgesOutSilently(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), events) plantPrivate(svc, "t1", "s1", "s2", "docs") @@ -155,6 +161,7 @@ func TestAPrivateResultAgesOutSilently(t *testing.T) { // must: told "unknown ticket", it cannot tell a result it missed from a ticket // it mistyped. func TestAWaitOnAnExpiredPrivateResultSaysItExpired(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantPrivate(svc, "t1", "s1", "s2", "docs") _ = svc.Reply(ReplyOptions{Ticket: "t1", Answer: "done"}) diff --git a/internal/relay/relay_test.go b/internal/relay/relay_test.go index 364b102d..566428f9 100644 --- a/internal/relay/relay_test.go +++ b/internal/relay/relay_test.go @@ -402,6 +402,7 @@ func workspace() fakeSessions { } func TestPeersListsLiveSessionsWithoutTheCaller(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3", "s5"), nil) peers, err := svc.Peers(PeersOptions{From: "s1"}) @@ -434,6 +435,7 @@ func TestPeersListsLiveSessionsWithoutTheCaller(t *testing.T) { // can hand work to. A session that reported nothing carries no state at all — // never "idle", which would read as free. func TestPeersCarryTheStateEachSessionReported(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3", "s5"), nil) svc.Observe("s2", "busy") @@ -469,6 +471,7 @@ func TestPeersCarryTheStateEachSessionReported(t *testing.T) { // still busy and errands keep reading it so, and a /compact at the prompt // leaves a finished turn finished. The report that closes it says the rest. func TestACompactionMovesNoState(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) svc.Observe("s2", "busy") @@ -499,6 +502,7 @@ func TestACompactionMovesNoState(t *testing.T) { // human. Published as waiting it would tell every caller reading the roster to // hold off from the one session most able to take work. func TestPeersDoNotCallAnIdlePromptWaiting(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) svc.Observe("s2", "busy") @@ -521,6 +525,7 @@ func TestPeersDoNotCallAnIdlePromptWaiting(t *testing.T) { } func TestPeersReportsAStoreFailure(t *testing.T) { + t.Parallel() svc := newRelay(fakeSessions{err: errors.New("database is locked")}, newFakeTerminal(), nil) if _, err := svc.Peers(PeersOptions{From: "s1"}); err == nil { @@ -535,6 +540,7 @@ func TestPeersReportsAStoreFailure(t *testing.T) { // when a write here has returned, and an Enter pressed into that burst is read // as a newline inside the paste instead of as "send it". func TestTheEnterWaitsForTheTargetToFinishTakingThePasteIn(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.submitDelay = time.Millisecond @@ -560,6 +566,7 @@ func TestTheEnterWaitsForTheTargetToFinishTakingThePasteIn(t *testing.T) { // (terminal.HoldInput). The window opens before the paste and closes after the // Enter, which is what this reads off the fake. func TestTheTargetsKeyboardIsHeldForTheWholeSubmission(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.submitDelay = time.Millisecond @@ -583,6 +590,7 @@ func TestTheTargetsKeyboardIsHeldForTheWholeSubmission(t *testing.T) { // repaints on a timer of its own would never go quiet, and an errand that hangs // on that is worse than one whose Enter is late. func TestASilentTargetIsSentItsEnterAnyway(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.submitDelay = time.Millisecond @@ -600,6 +608,7 @@ func TestASilentTargetIsSentItsEnterAnyway(t *testing.T) { } func TestSendDeliversAndReplyAnswers(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -660,6 +669,7 @@ func TestSendDeliversAndReplyAnswers(t *testing.T) { } func TestAMessageFromOutsideLichIsAttributedToTheCommandLine(t *testing.T) { + t.Parallel() term := newFakeTerminal("s2") svc := newRelay(workspace(), term, nil) @@ -682,6 +692,7 @@ func TestAMessageFromOutsideLichIsAttributedToTheCommandLine(t *testing.T) { // agent whose shell is locked down could otherwise have no way to answer at // all, and one pointed at a tool it does not have loses the turn to an error. func TestReplyInstructionOffersTheToolOnlyWhereItExists(t *testing.T) { + t.Parallel() tests := []struct { name string tool bool @@ -722,6 +733,7 @@ func TestReplyInstructionOffersTheToolOnlyWhereItExists(t *testing.T) { // session it names rather than on an error — that mismatch is what made an // agent use both channels at once on the first real run. func TestARosterNameReachesTheSameSession(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -745,6 +757,7 @@ func TestARosterNameReachesTheSameSession(t *testing.T) { // no longer to the one lich derived — which is the string an agent reads out of // /list-agents and writes back at a prompt. func TestARenamedSessionAnswersToItsNewName(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.renamed("s2", "reviewer") svc := newRelay(workspace(), term, nil) @@ -767,6 +780,7 @@ func TestARenamedSessionAnswersToItsNewName(t *testing.T) { // rather than reaching it under two names at once. Answering to both would put // the roster back where it was — an address lich mints and nothing keeps true. func TestADerivedNameIsGoneOnceTheSessionRenames(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.renamed("s2", "reviewer") svc := newRelay(workspace(), term, nil) @@ -786,6 +800,7 @@ func TestADerivedNameIsGoneOnceTheSessionRenames(t *testing.T) { // user chose and the one every message quotes, so it outranks a roster name that // happens to read the same. func TestTheLabelWinsARosterCollision(t *testing.T) { + t.Parallel() collide := fakeSessions{projects: []store.Project{{ ID: "p1", Name: "lich", Path: "/src/lich", Sessions: []store.Session{ @@ -813,6 +828,7 @@ func TestTheLabelWinsARosterCollision(t *testing.T) { // TestAnUnknownNameNamesWhatIsReachable proves a miss is one step from a hit: // both names of every live session come back with the error. func TestAnUnknownNameNamesWhatIsReachable(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) _, err := svc.Send(context.Background(), SendOptions{From: "s1", Target: "ghost", Prompt: "hello", WaitSeconds: 30}) @@ -829,6 +845,7 @@ func TestAnUnknownNameNamesWhatIsReachable(t *testing.T) { // TestWithNothingReachableTheErrorSaysSo proves the empty case reads as a fact // about the workspace rather than as a bad name. func TestWithNothingReachableTheErrorSaysSo(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1"), nil) _, err := svc.Send(context.Background(), SendOptions{From: "s1", Target: "docs", Prompt: "hello", WaitSeconds: 30}) @@ -844,6 +861,7 @@ func TestWithNothingReachableTheErrorSaysSo(t *testing.T) { // from one errand: the target learns who asked, the sender learns who it is // waiting on, and both marks come down when the answer lands. func TestBothCardsAreMarkedAndCleared(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), events) @@ -892,6 +910,7 @@ func TestBothCardsAreMarkedAndCleared(t *testing.T) { // mark of its own — there is no session to put one on — while the target still // learns a request arrived. func TestAnExternalSenderMarksOnlyTheTarget(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s2"), events) @@ -923,6 +942,7 @@ func TestAnExternalSenderMarksOnlyTheTarget(t *testing.T) { // TestAnUndeliveredMessageMarksNobody proves the mark follows the bytes: a write // that failed leaves no card claiming a request that never arrived. func TestAnUndeliveredMessageMarksNobody(t *testing.T) { + t.Parallel() events := &fakeEvents{} term := newFakeTerminal("s1", "s2") term.writeErr = errors.New("pty closed") @@ -940,6 +960,7 @@ func TestAnUndeliveredMessageMarksNobody(t *testing.T) { // stops claiming both cards once it is swept, rather than marking them for the // life of the process. func TestAnExpiredTicketTakesItsMarksDown(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), events) svc.tickets["stale"] = &ticket{ @@ -970,6 +991,7 @@ func TestAnExpiredTicketTakesItsMarksDown(t *testing.T) { // has to survive: the target worked and then answered somewhere lich cannot // read. The wait ends there, saying so, instead of running its full clock out. func TestATurnThatEndsWithoutAnAnswerEndsTheWait(t *testing.T) { + t.Parallel() events := &fakeEvents{} term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, events) @@ -1011,6 +1033,7 @@ func TestATurnThatEndsWithoutAnAnswerEndsTheWait(t *testing.T) { // turn that ends with no reply is that news — what arrives is the short nudge, // and the outcome itself is collected, not typed. func TestTheSenderIsToldAtItsPromptWhenTheTargetStallsUnattended(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -1046,6 +1069,7 @@ func TestTheSenderIsToldAtItsPromptWhenTheTargetStallsUnattended(t *testing.T) { // without that it hears "still working" about an errand already closed, on a // ticket already gone from the map. func TestAWaiterGivingUpAsTheErrandStallsHearsSo(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) tk := &ticket{ target: "docs", @@ -1066,6 +1090,7 @@ func TestAWaiterGivingUpAsTheErrandStallsHearsSo(t *testing.T) { // of the turn in progress says nothing — reporting it as unanswered would // accuse a target that had not read the request yet. func TestAQueuedRequestIgnoresTheTurnAlreadyRunning(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) svc.Observe("s2", "busy") @@ -1133,6 +1158,7 @@ func awaitDelivered(t *testing.T, svc *Service, n int) { // them that turn was — so the answer is not put on one of them by delivery // order, and the worker is asked at its own prompt to name the ticket. func TestADoneWithTwoErrandsOpenStallsBothAndAsksForTheTicket(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") events := &fakeEvents{} svc := newRelay(workspace(), term, events) @@ -1197,6 +1223,7 @@ func TestADoneWithTwoErrandsOpenStallsBothAndAsksForTheTicket(t *testing.T) { // A single errand is the case there is nothing to pick between: it is stalled // on its own, and the worker is not asked to name anything. func TestADoneWithOneErrandOpenStallsItWithoutANotice(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, &fakeEvents{}) @@ -1236,6 +1263,7 @@ func openTickets(svc *Service) []string { // the second message arriving while the first errand's turn is already running: // its skipped turn is the same done that closes the first errand. func TestASecondErrandQueuedMidTurnSurvivesTheFirstsEnd(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) first := make(chan Result, 1) @@ -1268,6 +1296,7 @@ func TestASecondErrandQueuedMidTurnSurvivesTheFirstsEnd(t *testing.T) { // at delivery: a ticket still waiting out the target's setup script has no // message in that PTY, so nothing that happens there can close it. func TestAnUndeliveredTicketIgnoresTheTargetsTurns(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) svc.tickets["held"] = &ticket{ fromID: "s1", targetID: "s2", target: "docs", @@ -1301,6 +1330,7 @@ func TestAnUndeliveredTicketIgnoresTheTargetsTurns(t *testing.T) { // queued and working, so the reply the target eventually sends has no ticket // left to land on. func TestABusyReportInsideTheDeliveryWindowCountsForTheTicket(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) svc.submitDelay = 50 * time.Millisecond @@ -1327,6 +1357,7 @@ func TestABusyReportInsideTheDeliveryWindowCountsForTheTicket(t *testing.T) { // arrives inside the window. Losing it spends the skip on the turn that carries // this request instead, and the errand never closes. func TestADoneInsideTheDeliveryWindowSpendsTheSkip(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.submitDelay = 50 * time.Millisecond @@ -1358,6 +1389,7 @@ func TestADoneInsideTheDeliveryWindowSpendsTheSkip(t *testing.T) { // target that replies and ends its turn in the same breath has answered, and a // race between the two must not turn an answer into a shrug. func TestAnAnsweredTicketIsNotAlsoStalled(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) done := make(chan Result, 1) @@ -1382,6 +1414,7 @@ func TestAnAnsweredTicketIsNotAlsoStalled(t *testing.T) { // TestASessionThatEndedStopsTheWaitOutright proves SessionEnd needs no turn: // the CLI has left the PTY, so nothing there will ever answer. func TestASessionThatEndedStopsTheWaitOutright(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), events) @@ -1412,6 +1445,7 @@ func TestASessionThatEndedStopsTheWaitOutright(t *testing.T) { // TestAnotherSessionsTurnLeavesTheTicketAlone proves the ticket only answers to // its own target: a busy neighbour must not close it. func TestAnotherSessionsTurnLeavesTheTicketAlone(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) done := make(chan Result, 1) @@ -1435,6 +1469,7 @@ func TestAnotherSessionsTurnLeavesTheTicketAlone(t *testing.T) { // answer itself. The full text comes back through Collect, inside a turn the // sender chose, instead of restarting its turn as a prompt submission. func TestAnAnswerNobodyWaitedForIsStashedAndNudged(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -1491,6 +1526,7 @@ func TestAnAnswerNobodyWaitedForIsStashedAndNudged(t *testing.T) { // still holding the line carries the answer out itself, and typing it at the // prompt as well would deliver it twice. func TestAnAnswerSomeoneIsWaitingForIsNotAlsoTyped(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -1516,6 +1552,7 @@ func TestAnAnswerSomeoneIsWaitingForIsNotAlsoTyped(t *testing.T) { // return to: the CLI run from a script is not a session, so an answer nobody // waited for is simply not delivered rather than typed at a stranger. func TestAnExternalSenderHasNoPromptToAnswerAt(t *testing.T) { + t.Parallel() term := newFakeTerminal("s2") svc := newRelay(workspace(), term, nil) @@ -1535,6 +1572,7 @@ func TestAnExternalSenderHasNoPromptToAnswerAt(t *testing.T) { } func TestSendRefusesAnAmbiguousLabel(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s3", "s5"), nil) _, err := svc.Send(context.Background(), SendOptions{From: "s1", Target: "api", Prompt: "hello", WaitSeconds: 30}) @@ -1549,6 +1587,7 @@ func TestSendRefusesAnAmbiguousLabel(t *testing.T) { } func TestSendNarrowsAnAmbiguousLabelByProject(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s3", "s5") svc := newRelay(workspace(), term, nil) @@ -1572,6 +1611,7 @@ func TestSendNarrowsAnAmbiguousLabelByProject(t *testing.T) { } func TestSendRejectsUnreachableTargets(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) tests := []struct { @@ -1595,6 +1635,7 @@ func TestSendRejectsUnreachableTargets(t *testing.T) { } func TestSendReportsADeliveryFailure(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.writeErr = errors.New("pty closed") svc := newRelay(workspace(), term, nil) @@ -1611,6 +1652,7 @@ func TestSendReportsADeliveryFailure(t *testing.T) { } func TestSendPendsWhenTheWaitRunsOutAndWaitPicksItUp(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) got, err := svc.Send(context.Background(), SendOptions{From: "s1", Target: "docs", Prompt: "long errand", WaitSeconds: 1}) @@ -1638,6 +1680,7 @@ func TestSendPendsWhenTheWaitRunsOutAndWaitPicksItUp(t *testing.T) { } func TestReplyRefusesUnknownAndRepeatedTickets(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -1672,6 +1715,7 @@ func TestReplyRefusesUnknownAndRepeatedTickets(t *testing.T) { // exists for: an agent whose context was compacted past the message can still // send its answer home, because one open request needs no guessing. func TestReplyWithoutATicketAnswersTheOneOpenErrand(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), events) @@ -1704,6 +1748,7 @@ func TestReplyWithoutATicketAnswersTheOneOpenErrand(t *testing.T) { // work nobody did. The refusal has to name both tickets and what each asked, or // the agent has nothing to retry with. func TestReplyWithoutATicketIsRefusedWithTwoErrandsOpen(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), events) @@ -1764,6 +1809,7 @@ func TestReplyWithoutATicketIsRefusedWithTwoErrandsOpen(t *testing.T) { // boundary — the cut is in bytes, and half a rune is a replacement character in // the middle of the one line that tells two errands apart. func TestAnErrandIsNamedByTheOpeningOfItsPrompt(t *testing.T) { + t.Parallel() if got := askedExcerpt("run the tests\n\nthen report"); got != "run the tests then report" { t.Errorf("excerpt = %q", got) } @@ -1789,6 +1835,7 @@ func TestAnErrandIsNamedByTheOpeningOfItsPrompt(t *testing.T) { // reads to tell them apart, and a list that shuffles between two runs is one it // cannot. func TestErrandOrderSurvivesAClockThatCannotTellThemApart(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), &fakeEvents{}) tick := time.Date(2026, 9, 4, 12, 0, 0, 0, time.UTC) @@ -1812,6 +1859,7 @@ func TestErrandOrderSurvivesAClockThatCannotTellThemApart(t *testing.T) { // still queued for a prompt that never received it is not an errand this // session can be answering. func TestReplyWithoutATicketNeedsAnErrandItCanName(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.deliveryLimit = 50 * time.Millisecond @@ -1836,6 +1884,7 @@ func TestReplyWithoutATicketNeedsAnErrandItCanName(t *testing.T) { } func TestWaitRefusesAnUnknownTicket(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal(), nil) if _, err := svc.Wait(context.Background(), WaitOptions{Ticket: "deadbeef", WaitSeconds: 1}); err == nil { @@ -1844,6 +1893,7 @@ func TestWaitRefusesAnUnknownTicket(t *testing.T) { } func TestExpiredTicketsAreSweptAway(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) svc.tickets["stale"] = &ticket{ target: "docs", @@ -1863,6 +1913,7 @@ func TestExpiredTicketsAreSweptAway(t *testing.T) { } func TestSendBoundsThePrompt(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -1890,6 +1941,7 @@ func TestSendBoundsThePrompt(t *testing.T) { } func TestReplyTruncatesAnOversizedAnswer(t *testing.T) { + t.Parallel() tests := []struct { name string answer string @@ -1929,6 +1981,7 @@ func TestReplyTruncatesAnOversizedAnswer(t *testing.T) { // and idle mean the same "not working" — so it is dropped rather than kept for // the life of the process. func TestAnEndedSessionLeavesNoStateBehind(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) svc.Observe("s2", "busy") @@ -1949,6 +2002,7 @@ func TestAnEndedSessionLeavesNoStateBehind(t *testing.T) { } func TestSanitizeKeepsWhitespaceAndDropsEscapes(t *testing.T) { + t.Parallel() tests := []struct { name string in string @@ -1975,6 +2029,7 @@ func TestSanitizeKeepsWhitespaceAndDropsEscapes(t *testing.T) { // under the 120s an agent's shell tool allows, and a 30 minute ceiling — so the // cap is pinned from both sides of the boundary rather than from far away. func TestWaitForClampsTheRequestedWait(t *testing.T) { + t.Parallel() tests := []struct { name string seconds int @@ -1996,6 +2051,7 @@ func TestWaitForClampsTheRequestedWait(t *testing.T) { } func TestTicketIDsAreDistinct(t *testing.T) { + t.Parallel() seen := map[string]bool{} for range 100 { id, err := newTicketID() @@ -2036,6 +2092,7 @@ func waitForTicket(svc *Service) string { // there to read it. func TestSendDeliversOnceTheSetupScriptFinishes(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.setUp("s2", true) svc := newRelay(workspace(), term, nil) @@ -2065,6 +2122,7 @@ func TestSendDeliversOnceTheSetupScriptFinishes(t *testing.T) { // to happen was a failed Send with the task gone; what has to happen is a // ticket now and a delivery later, on an errand that still answers. func TestSendQueuesForASessionThatIsNotAtAPromptYet(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.setUp("s2", true) svc := newRelay(workspace(), term, nil) @@ -2104,6 +2162,7 @@ func TestSendQueuesForASessionThatIsNotAtAPromptYet(t *testing.T) { // own timeout (internal/cli, waitBudget) and report a failure on an errand that // is running perfectly well. func TestSendDoesNotBlockOnASessionThatIsNotReady(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.setUp("s2", true) svc := newRelay(workspace(), term, nil) @@ -2127,6 +2186,7 @@ func TestSendDoesNotBlockOnASessionThatIsNotReady(t *testing.T) { // inbox, and told that nothing is queued anymore. func TestQueuedTaskGivesUpWhenTheTargetNeverReachesAPrompt(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.setUp("s2", true) svc := newRelay(workspace(), term, nil) @@ -2153,6 +2213,7 @@ func TestQueuedTaskGivesUpWhenTheTargetNeverReachesAPrompt(t *testing.T) { } func TestQueuedTaskReportsTheTargetDyingToTheInbox(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.setUp("s2", true) events := &fakeEvents{} @@ -2217,6 +2278,7 @@ func (f fakePlugins) Installed(string) bool { return f.installed } func (f fakePlugins) HasTools(string) bool { return f.tools } func TestATaskNobodyPicksUpComesBackUnread(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) @@ -2246,6 +2308,7 @@ func TestATaskNobodyPicksUpComesBackUnread(t *testing.T) { // prompt. The second write is the manual resend automated — seen with opencode, // whose startup goes quiet long enough to pass for a prompt. func TestATaskNobodyReadIsTypedInAgain(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) @@ -2278,6 +2341,7 @@ func TestATaskNobodyReadIsTypedInAgain(t *testing.T) { // session ended — gets the unread verdict without a second write into whatever // holds it now. func TestNoRetryIntoATerminalThatIsNotReady(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) term.onWrite = func(id, data string) { @@ -2299,6 +2363,7 @@ func TestNoRetryIntoATerminalThatIsNotReady(t *testing.T) { } func TestATaskTheTargetStartsWorkingOnIsNotUnread(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) @@ -2320,6 +2385,7 @@ func TestATaskTheTargetStartsWorkingOnIsNotUnread(t *testing.T) { // the message for the next turn and is busy the whole time, so there is nothing // here to tell apart. func TestABusyTargetIsNotCheckedForReceipt(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) svc.Observe("s2", stateBusy) @@ -2338,6 +2404,7 @@ func TestABusyTargetIsNotCheckedForReceipt(t *testing.T) { // message queues behind the open turn, so calling it unread would drop a ticket // whose answer is still coming. func TestAWaitingTargetIsTreatedAsMidTurn(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) svc.Observe("s2", stateBusy) @@ -2359,6 +2426,7 @@ func TestAWaitingTargetIsTreatedAsMidTurn(t *testing.T) { // target is at its prompt, so a task typed there is read within seconds and the // receipt check has to stay armed. func TestWaitingAfterDoneStillArmsTheReceiptCheck(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) svc.Observe("s2", stateBusy) @@ -2377,6 +2445,7 @@ func TestWaitingAfterDoneStillArmsTheReceiptCheck(t *testing.T) { // Without the plugin a session reports nothing whatever happens in it, so its // silence says nothing either. func TestSilenceIsOnlyReadWhereTheProviderReports(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.receiptWindow = 40 * time.Millisecond @@ -2395,6 +2464,7 @@ func TestSilenceIsOnlyReadWhereTheProviderReports(t *testing.T) { // moved on, so the news has to reach its prompt — as a nudge, with the unread // outcome itself waiting in the inbox. func TestTheSenderIsToldAtItsPromptWhenNobodyWasWaiting(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := withReceipts(term) // A window the sender's own wait runs out before, which is the ordinary @@ -2426,6 +2496,7 @@ func TestTheSenderIsToldAtItsPromptWhenNobodyWasWaiting(t *testing.T) { // what is left behind — without that it hears "still working" about a task // nothing read, on a ticket already gone from the map. func TestAWaiterGivingUpAsTheTaskGoesUnreadHearsSo(t *testing.T) { + t.Parallel() svc := withReceipts(newFakeTerminal("s1", "s2")) tk := &ticket{ target: "docs", @@ -2446,6 +2517,7 @@ func TestAWaiterGivingUpAsTheTaskGoesUnreadHearsSo(t *testing.T) { // read it. Whoever leaves last owns what is left behind — the answer is // written, accepted and gone otherwise, on a ticket already out of the map. func TestAnAnswerLandingAsItsLastWaiterGivesUpIsStashed(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) tk := &ticket{ fromID: "s1", @@ -2477,6 +2549,7 @@ func TestAnAnswerLandingAsItsLastWaiterGivesUpIsStashed(t *testing.T) { // only if the installed one is new enough. The relay asks rather than assumes. func TestTheMessageNamesTheToolWhenTheTargetHasIt(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.SetPlugins(fakePlugins{installed: true, tools: true}) @@ -2493,6 +2566,7 @@ func TestTheMessageNamesTheToolWhenTheTargetHasIt(t *testing.T) { } func TestTheMessageNamesOnlyTheCommandWithoutTheTool(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.SetPlugins(fakePlugins{installed: true, tools: false}) @@ -2515,6 +2589,7 @@ func TestTheMessageNamesOnlyTheCommandWithoutTheTool(t *testing.T) { // Nothing wired is the state a test — and a lich whose plugin check never ran — // is in. It has to read as "no tools", never as "assume they are there". func TestWithoutAPluginCheckTheMessageNamesTheCommand(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -2551,6 +2626,7 @@ func plant(svc *Service, id, fromID, targetID, target string) { // sender's turn once per worker — the debounce folds the burst into one line // naming everything that is waiting. func TestABurstOfAnswersCoalescesIntoOneNudge(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, nil) svc.nudgeDelay = 20 * time.Millisecond @@ -2584,6 +2660,7 @@ func TestABurstOfAnswersCoalescesIntoOneNudge(t *testing.T) { // A delivery mid-turn queues as its own turn, which is the cost this whole // path exists to avoid — a busy sender hears nothing until its turn ends. func TestABusySenderIsNudgedOnlyWhenItsTurnEnds(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) svc.Observe("s1", stateBusy) @@ -2607,6 +2684,7 @@ func TestABusySenderIsNudgedOnlyWhenItsTurnEnds(t *testing.T) { // must not be nudged again at every turn end — each nudge starts a turn, and // two of them chasing each other is a loop with a token bill. func TestANudgeIsNotRepeatedOnLaterTurnEnds(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -2630,6 +2708,7 @@ func TestANudgeIsNotRepeatedOnLaterTurnEnds(t *testing.T) { // the sender is never told about — the entry has to go back to unnudged and be // tried again at the next turn end. func TestANudgeThatNeverLandedIsSentAgain(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) term.failWrites(errors.New("pty closed")) @@ -2659,6 +2738,7 @@ func TestANudgeThatNeverLandedIsSentAgain(t *testing.T) { // half is gone. The nudge is the path that has no other gate: it is typed at an // idle sender, which is exactly the session somebody is sitting at. func TestNothingIsTypedIntoAPromptItsUserIsHolding(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) term.typeAt("s1", true) @@ -2680,6 +2760,7 @@ func TestNothingIsTypedIntoAPromptItsUserIsHolding(t *testing.T) { } func TestCollectHoldsTheLineForTheNextResult(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -2704,6 +2785,7 @@ func TestCollectHoldsTheLineForTheNextResult(t *testing.T) { } func TestCollectReportsWhoStillOwes(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -2725,6 +2807,7 @@ func TestCollectReportsWhoStillOwes(t *testing.T) { } func TestCollectWithNothingOpenReturnsAtOnce(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1"), nil) start := time.Now() @@ -2741,6 +2824,7 @@ func TestCollectWithNothingOpenReturnsAtOnce(t *testing.T) { } func TestCollectRefusesACallerWithNoSession(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal(), nil) if _, err := svc.Collect(context.Background(), CollectOptions{WaitSeconds: 1}); err == nil { @@ -2749,6 +2833,7 @@ func TestCollectRefusesACallerWithNoSession(t *testing.T) { } func TestWaitPicksAStashedOutcomeUp(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plant(svc, "t1", "s1", "s2", "docs") @@ -2769,6 +2854,7 @@ func TestWaitPicksAStashedOutcomeUp(t *testing.T) { } func TestAnUncollectedResultExpiresWithItsTTL(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1"), nil) svc.mu.Lock() svc.ready["old"] = &inboxEntry{ @@ -2790,6 +2876,7 @@ func TestAnUncollectedResultExpiresWithItsTTL(t *testing.T) { // The window hears the inbox change size, so the card can say results are // waiting: the nudge tells the agent, the event tells the person. func TestTheInboxSizeIsAnnouncedAsItGrowsAndDrains(t *testing.T) { + t.Parallel() events := &fakeEvents{} term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, events) @@ -2816,6 +2903,7 @@ func TestTheInboxSizeIsAnnouncedAsItGrowsAndDrains(t *testing.T) { } func TestASingleTicketPickupAnnouncesTheSmallerInbox(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), events) plant(svc, "t1", "s1", "s2", "docs") @@ -2833,6 +2921,7 @@ func TestASingleTicketPickupAnnouncesTheSmallerInbox(t *testing.T) { } func TestAnExpiredInboxEntryAnnouncesItsAbsence(t *testing.T) { + t.Parallel() events := &fakeEvents{} svc := newRelay(workspace(), newFakeTerminal("s1"), events) svc.mu.Lock() @@ -2852,6 +2941,7 @@ func TestAnExpiredInboxEntryAnnouncesItsAbsence(t *testing.T) { } func TestTheNudgeNamesTheToolOnlyWhereItExists(t *testing.T) { + t.Parallel() tests := []struct { name string tools bool @@ -2889,6 +2979,7 @@ func TestTheNudgeNamesTheToolOnlyWhereItExists(t *testing.T) { // has. Naming tools that are not in the list would leave that session believing // it has no way to open anything. func TestSpawnBriefingNamesTheRouteThisSpawnGave(t *testing.T) { + t.Parallel() withTools, withCommand := SpawnBriefing(prompt.English, true, RouteSessions), SpawnBriefing(prompt.English, false, RouteSessions) if strings.Contains(withTools, "lich open") { @@ -2920,6 +3011,7 @@ func TestSpawnBriefingNamesTheRouteThisSpawnGave(t *testing.T) { // report back on its own), so the briefing points at it instead of drawing a // line against it, and keeps open_session for what a subagent cannot be. func TestSpawnBriefingSendsCardsToTheAgentTool(t *testing.T) { + t.Parallel() cards := SpawnBriefing(prompt.English, true, RouteCards) for _, want := range []string{"Agent tool", "card", "isolation", "tools in your list"} { if !strings.Contains(cards, want) { @@ -2939,6 +3031,7 @@ func TestSpawnBriefingSendsCardsToTheAgentTool(t *testing.T) { // A card as deep as lich nests them is told its Agent tool stays inside it, and // is not sent to open sessions instead, which would nest cards by another door. func TestSpawnBriefingKeepsANativeCardsFanOutUnderIt(t *testing.T) { + t.Parallel() for _, hasTools := range []bool{true, false} { native := SpawnBriefing(prompt.English, hasTools, RouteNative) for _, want := range []string{"Agent tool", "inside this session", "rather than with new lich sessions"} { @@ -2960,6 +3053,7 @@ func TestSpawnBriefingKeepsANativeCardsFanOutUnderIt(t *testing.T) { // the one holding the request, and reporting it unanswered here would tell the // sender the work is over while the target sits at a prompt able to carry on. func TestAnInterruptedTurnDoesNotEndTheErrand(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -2989,6 +3083,7 @@ func TestAnInterruptedTurnDoesNotEndTheErrand(t *testing.T) { // An interrupted session is at its prompt with nothing running, which is // exactly when a delivery held back for a busy target may go in. func TestAnInterruptedTargetIsNotBusy(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) @@ -3007,6 +3102,7 @@ func TestAnInterruptedTargetIsNotBusy(t *testing.T) { // one a plugin already holds (LICH_SESSION_ID, lich whoami), and the one no // rename moves. func TestSendReachesASessionByItsID(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s5") svc := newRelay(workspace(), term, nil) @@ -3023,6 +3119,7 @@ func TestSendReachesASessionByItsID(t *testing.T) { // A caller naming itself by id is refused exactly as by label: the roster never // holds the caller, whichever name it is looked up by. func TestSendRefusesTheCallersOwnIDLikeItsLabel(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) _, byLabel := svc.Send(context.Background(), SendOptions{From: "s1", Target: "sender", Prompt: "hello", WaitSeconds: 30}) @@ -3036,6 +3133,7 @@ func TestSendRefusesTheCallersOwnIDLikeItsLabel(t *testing.T) { } func TestSelfIsTheCallersOwnEntry(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) got, err := svc.Self(SelfOptions{From: "s1"}) @@ -3052,6 +3150,7 @@ func TestSelfIsTheCallersOwnEntry(t *testing.T) { } func TestSelfRefusesACallerWithoutASession(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1"), nil) for id, want := range map[string]string{"": "LICH_SESSION_ID is unset", "gone": `no session with id "gone"`} { @@ -3066,6 +3165,7 @@ func TestSelfRefusesACallerWithoutASession(t *testing.T) { // card was closed, the same id respawned is a new process that has reported // nothing: it must not read busy to deliveries or in the roster. func TestAReapedOrClosedSessionForgetsItsState(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) svc.Observe("s2", "busy") svc.Observe("s3", "busy") diff --git a/internal/relay/resume_test.go b/internal/relay/resume_test.go index 2db8ff6f..58991f0c 100644 --- a/internal/relay/resume_test.go +++ b/internal/relay/resume_test.go @@ -26,6 +26,7 @@ func (w *parkWriter) all() []ScheduleEvent { } func TestParkResumeParksTheContinuationAfterTheReset(t *testing.T) { + t.Parallel() writer := &parkWriter{} events := &fakeEvents{} svc := newRelay(scheduledWith(0, "", writer.set), newFakeTerminal("s1"), events) @@ -43,6 +44,7 @@ func TestParkResumeParksTheContinuationAfterTheReset(t *testing.T) { } func TestParkResumeParksNothingItShouldNotWaitFor(t *testing.T) { + t.Parallel() tests := []struct { name string resetsAt int64 @@ -72,6 +74,7 @@ func TestParkResumeParksNothingItShouldNotWaitFor(t *testing.T) { // than typed behind that turn. Learned from the row too, so a continuation // parked before a restart is dropped all the same. func TestATurnStartingDropsTheParkedContinuation(t *testing.T) { + t.Parallel() writer := &parkWriter{} events := &fakeEvents{} svc := newRelay(scheduledWith(5000, resumePrompt, writer.set), newFakeTerminal("s1"), events) @@ -90,6 +93,7 @@ func TestATurnStartingDropsTheParkedContinuation(t *testing.T) { } func TestATurnStartingLeavesThePersonsPromptAlone(t *testing.T) { + t.Parallel() writer := &parkWriter{} svc := newRelay(scheduledWith(5000, "ship the release notes", writer.set), newFakeTerminal("s1"), &fakeEvents{}) svc.now = at(1000) diff --git a/internal/relay/rostername_test.go b/internal/relay/rostername_test.go index 7542133a..26f12d75 100644 --- a/internal/relay/rostername_test.go +++ b/internal/relay/rostername_test.go @@ -7,6 +7,7 @@ import "testing" // time. The derivation is only ever the answer when there is nothing to read — // and a name that is only whitespace is nothing to read. func TestRosterNameOf(t *testing.T) { + t.Parallel() tests := []struct { name string recorded string @@ -31,6 +32,7 @@ func TestRosterNameOf(t *testing.T) { // has nothing on record yet — the one it is spawned under, and the one the // roster falls back to. func TestRosterNameDerivesTheBirthName(t *testing.T) { + t.Parallel() tests := []struct { name string cwd string @@ -96,6 +98,7 @@ func TestRosterNameDerivesTheBirthName(t *testing.T) { } func TestRosterNameSeparatesSessionsSharingACheckout(t *testing.T) { + t.Parallel() const cwd = "/home/me/code/lich" first := RosterName(cwd, "4f2a1b3c-0000-4000-8000-000000000000") second := RosterName(cwd, "9d8e7f6a-0000-4000-8000-000000000000") @@ -109,6 +112,7 @@ func TestRosterNameSeparatesSessionsSharingACheckout(t *testing.T) { // mints a session under, the name RosterName gives it is recognised as one, and // a name the user typed is not. func TestIsRosterNameRecognisesEveryBirthName(t *testing.T) { + t.Parallel() for _, tc := range []struct{ cwd, id string }{ {"/home/u/try/skipo", "3c5bd823-ad2f"}, {"/home/u/try/skipo/", "a-b-c-d-e"}, diff --git a/internal/relay/status_test.go b/internal/relay/status_test.go index 07fe926c..08702cea 100644 --- a/internal/relay/status_test.go +++ b/internal/relay/status_test.go @@ -18,6 +18,7 @@ func plantOwed(svc *Service, id, fromID, sender, targetID, asked string) { } func TestStatusOfASessionWithNoErrandsIsThreeEmptyLists(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1"), nil) got := svc.Status("s1") @@ -31,6 +32,7 @@ func TestStatusOfASessionWithNoErrandsIsThreeEmptyLists(t *testing.T) { } func TestStatusListsWhatTheSessionOwes(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantOwed(svc, "t1", "s1", "sender", "s2", "write the docs") plantOwed(svc, "t2", "", "", "s2", "run the tests") @@ -66,6 +68,7 @@ func sameOwed(got, want []OwedErrand) bool { } func TestStatusOrdersOwedErrandsByHandOff(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantOwed(svc, "late", "s1", "sender", "s2", "second") plantOwed(svc, "early", "s1", "sender", "s2", "first") @@ -82,6 +85,7 @@ func TestStatusOrdersOwedErrandsByHandOff(t *testing.T) { } func TestStatusListsOpenErrandsWithTheTargetsState(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) base := time.Now() plant(svc, "busy", "s1", "s2", "docs") @@ -106,6 +110,7 @@ func TestStatusListsOpenErrandsWithTheTargetsState(t *testing.T) { } func TestStatusReadsTheTargetsWaitingAsWaiting(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plant(svc, "t1", "s1", "s2", "docs") svc.Observe("s2", stateBusy) @@ -121,6 +126,7 @@ func TestStatusReadsTheTargetsWaitingAsWaiting(t *testing.T) { // Reading is not collecting: an answer listed as ready is still the agent's to // collect afterwards. func TestStatusListsReadyOutcomesWithoutCollectingThem(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plant(svc, "t1", "s1", "s2", "docs") if err := svc.Reply(ReplyOptions{Ticket: "t1", Answer: "all green"}); err != nil { @@ -143,6 +149,7 @@ func TestStatusListsReadyOutcomesWithoutCollectingThem(t *testing.T) { } func TestStatusLeavesAPrivateOutcomeOut(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantPrivate(svc, "t1", "s1", "s2", "docs") if err := svc.Reply(ReplyOptions{Ticket: "t1", Answer: "done"}); err != nil { @@ -155,6 +162,7 @@ func TestStatusLeavesAPrivateOutcomeOut(t *testing.T) { } func TestStatusNeverListsAnExpiredErrand(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plant(svc, "t1", "s1", "s2", "docs") svc.now = func() time.Time { return time.Now().Add(ticketTTL + time.Minute) } diff --git a/internal/relay/subagent_test.go b/internal/relay/subagent_test.go index 1e945302..1476693d 100644 --- a/internal/relay/subagent_test.go +++ b/internal/relay/subagent_test.go @@ -27,6 +27,7 @@ func branched() fakeSessions { } func TestSendSubagentMarksItsErrand(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) got, err := svc.SendSubagent(context.Background(), SendOptions{From: "s1", Target: "docs", Prompt: "write the docs", WaitSeconds: 1}) @@ -41,6 +42,7 @@ func TestSendSubagentMarksItsErrand(t *testing.T) { } func TestSendSubagentNeedsACallingSession(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s2"), nil) _, err := svc.SendSubagent(context.Background(), SendOptions{Target: "docs", Prompt: "write the docs", WaitSeconds: 1}) @@ -52,6 +54,7 @@ func TestSendSubagentNeedsACallingSession(t *testing.T) { // Through the caller's mod the whole report goes, so the model reads it the // way it reads a native subagent's result, with no collect call. func TestASubagentReportReachesItsCallerWholeThroughTheMod(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", ackedOK) svc := viaMod(term, nil) @@ -93,6 +96,7 @@ func TestASubagentReportReachesItsCallerWholeThroughTheMod(t *testing.T) { // With nothing but a prompt to type at, the report is not typed: a long text // typed into a TUI is what the mod route exists to avoid. func TestASubagentReportIsNotTypedAtACallerWithoutAMod(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(branched(), term, nil) plantSubagent(svc, "t1", "s1", "s2", "docs") @@ -115,6 +119,7 @@ func TestASubagentReportIsNotTypedAtACallerWithoutAMod(t *testing.T) { // A mod that never collected the note leaves the report in the inbox, and the // caller hears the short note typed instead. func TestASubagentReportNoPollCollectedStaysCollectable(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", withdrawn) svc := viaMod(term, nil) @@ -137,6 +142,7 @@ func TestASubagentReportNoPollCollectedStaysCollectable(t *testing.T) { // A report the caller collected first is not delivered a second time. func TestASubagentReportCollectedFirstIsNotAlsoDelivered(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", ackedOK) svc := viaMod(term, nil) @@ -159,6 +165,7 @@ func TestASubagentReportCollectedFirstIsNotAlsoDelivered(t *testing.T) { // Results that are not subagent reports ride the same note as a nudge. func TestASubagentReportCarriesTheNudgeForTheRest(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") term.attachMod("s1", ackedOK) svc := viaMod(term, nil) @@ -192,6 +199,7 @@ func TestASubagentReportCarriesTheNudgeForTheRest(t *testing.T) { } func TestASubagentErrandOutlivesTheTTLWhileItsWorkerLives(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plantSubagent(svc, "t1", "s1", "s2", "docs") @@ -227,6 +235,7 @@ func TestASubagentErrandOutlivesTheTTLWhileItsWorkerLives(t *testing.T) { } func TestAWorkerBlockedOnAPermissionTellsItsCallerOncePerBlock(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plantSubagent(svc, "t1", "s1", "s2", "docs") @@ -254,6 +263,7 @@ func TestAWorkerBlockedOnAPermissionTellsItsCallerOncePerBlock(t *testing.T) { } func TestABlockedWorkerReachesACallerWithAModAsANotification(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", ackedOK) svc := viaMod(term, nil) @@ -277,6 +287,7 @@ func TestABlockedWorkerReachesACallerWithAModAsANotification(t *testing.T) { // waiting after a turn ended is a prompt at rest, and an ordinary errand's // worker is the user's to watch: neither is news for the caller. func TestOnlyABlockedSubagentWorkerIsReported(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, nil) plantSubagent(svc, "t1", "s1", "s2", "docs") @@ -331,6 +342,7 @@ func expectNoneFinished(t *testing.T, finished chan string) { // A worker that reported and then ended the turn it reported in is done, as a // native subagent is once its result is back. func TestAWorkerThatReportedAndEndedItsTurnIsFinished(t *testing.T) { + t.Parallel() svc, finished := finishing(t) plantSubagent(svc, "t1", "s1", "s2", "docs") @@ -350,6 +362,7 @@ func TestAWorkerThatReportedAndEndedItsTurnIsFinished(t *testing.T) { // A report that arrives after the errand lapsed (the worker ended a turn // without answering, then answered later) finishes the worker the same way. func TestAWorkerThatReportedLateIsFinished(t *testing.T) { + t.Parallel() svc, finished := finishing(t) plantSubagent(svc, "t1", "s1", "s2", "docs") svc.Observe("s2", stateBusy) @@ -367,6 +380,7 @@ func TestAWorkerThatReportedLateIsFinished(t *testing.T) { // Only a subagent errand ends with its worker: a session answering an ordinary // send is somebody's peer, and one still holding another errand has work left. func TestAWorkerWithMoreToDoIsNotFinished(t *testing.T) { + t.Parallel() t.Run("ordinary errand", func(t *testing.T) { svc, finished := finishing(t) plant(svc, "t1", "s1", "s2", "docs") @@ -398,6 +412,7 @@ func TestAWorkerWithMoreToDoIsNotFinished(t *testing.T) { } func TestReportsOfOneFlushAreSummedUpByEveryWorker(t *testing.T) { + t.Parallel() got := reportNotification(prompt.English, []*inboxEntry{{target: "docs"}, {target: "api"}}) want := Notification{Status: NotifyCompleted, Summary: `lich sessions "docs", "api" finished`} if *got != want { diff --git a/internal/relay/viamod_test.go b/internal/relay/viamod_test.go index 48bb39ca..2e7a30d5 100644 --- a/internal/relay/viamod_test.go +++ b/internal/relay/viamod_test.go @@ -129,6 +129,7 @@ func assertNotTyped(t *testing.T, term *fakeTerminal, id string) { } func TestATaskToASessionWithAModIsHandedToItNotTyped(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", ackedOK) events := &fakeEvents{} @@ -162,6 +163,7 @@ func TestATaskToASessionWithAModIsHandedToItNotTyped(t *testing.T) { // A prompt no poll collected never runs, so typing it keeps delivery at most // once; from there it is a typed task like any other, receipt check included. func TestATaskNoPollCollectedIsTypedInstead(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", withdrawn) svc := viaMod(term, nil) @@ -184,6 +186,7 @@ func TestATaskNoPollCollectedIsTypedInstead(t *testing.T) { // A prompt a poll collected may still run: typing it again could run the task // twice, so it is reported unread instead, and a late answer still lands. func TestATaskTheModCollectedIsNeverTypedAgain(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", collected) svc := viaMod(term, nil) @@ -207,6 +210,7 @@ func TestATaskTheModCollectedIsNeverTypedAgain(t *testing.T) { // A busy target runs the prompt once its turn ends, which can be long after // the window: the errand waits for its turn instead of being written off. func TestATaskTheModCollectedForABusyTargetWaitsForItsTurn(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", collected) svc := viaMod(term, nil) @@ -235,6 +239,7 @@ func TestATaskTheModCollectedForABusyTargetWaitsForItsTurn(t *testing.T) { // A UserPromptSubmit hook that blocks the prompt would block it typed as well, // so it is reported undelivered rather than typed. func TestATaskAHookDroppedComesBackUndelivered(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", PromptReceipt{State: PromptAcked, Reason: "blocked by a hook"}) svc := viaMod(term, nil) @@ -253,6 +258,7 @@ func TestATaskAHookDroppedComesBackUndelivered(t *testing.T) { } func TestAModTaskTheTargetStartedIsNotUnread(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", ackedOK) svc := viaMod(term, nil) @@ -272,6 +278,7 @@ func TestAModTaskTheTargetStartedIsNotUnread(t *testing.T) { } func TestAnEndedSessionsModTaskIsNotTyped(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", PromptReceipt{State: PromptEnded}) svc := viaMod(term, nil) @@ -289,6 +296,7 @@ func TestAnEndedSessionsModTaskIsNotTyped(t *testing.T) { // A fresh session is typed at while its mod has not polled yet; the receipt // check's second attempt goes to the mod once it has. func TestARetryReachesTheModOnceItAttaches(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := viaMod(term, nil) term.onWrite = func(id, data string) { @@ -313,6 +321,7 @@ func TestARetryReachesTheModOnceItAttaches(t *testing.T) { } func TestSubmitPromptErrorIsTheSendsError(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") refused := errors.New("the transport is down") term.failMod("s2", refused) @@ -331,6 +340,7 @@ func TestSubmitPromptErrorIsTheSendsError(t *testing.T) { // The mod never touches the draft, so a sender typing at its prompt is told at // once instead of after its line goes stale. func TestANudgeReachesASenderThroughItsMod(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", ackedOK) term.typeAt("s1", true) @@ -354,6 +364,7 @@ func TestANudgeReachesASenderThroughItsMod(t *testing.T) { // Mirrors TestANudgeThatNeverLandedIsSentAgain for a nudge a hook refused. func TestANudgeTheModRefusedIsSentAgain(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", PromptReceipt{State: PromptAcked, Reason: "blocked"}, ackedOK) svc := viaMod(term, nil) @@ -373,6 +384,7 @@ func TestANudgeTheModRefusedIsSentAgain(t *testing.T) { } func TestANudgeNoPollCollectedIsTyped(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", withdrawn) svc := viaMod(term, nil) @@ -387,6 +399,7 @@ func TestANudgeNoPollCollectedIsTyped(t *testing.T) { } func TestAScheduledPromptGoesThroughTheMod(t *testing.T) { + t.Parallel() writer := &scheduleWriter{} term := newFakeTerminal("s1") term.attachMod("s1", ackedOK) @@ -402,6 +415,7 @@ func TestAScheduledPromptGoesThroughTheMod(t *testing.T) { } func TestTheTicketNoticeGoesThroughTheMod(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") term.attachMod("s2", ackedOK, ackedOK, ackedOK) svc := viaMod(term, nil) @@ -428,6 +442,7 @@ func TestTheTicketNoticeGoesThroughTheMod(t *testing.T) { // there meanwhile is not its turn: the errand stays open, and the task is typed // once it is withdrawn. func TestATurnBeforeAnyPollCollectedTheTaskDoesNotCloseIt(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", withdrawn) svc := viaMod(term, nil) @@ -454,6 +469,7 @@ func TestATurnBeforeAnyPollCollectedTheTaskDoesNotCloseIt(t *testing.T) { // once the report it raised is through: a report that waited on the nudge's // ack would wait on itself. func TestAStateReportDoesNotWaitOnTheNudgesAck(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", collected) svc := viaMod(term, nil) @@ -481,6 +497,7 @@ func TestAStateReportDoesNotWaitOnTheNudgesAck(t *testing.T) { // The mod never touches the user's line, so a task does not wait for it. func TestATaskReachesADraftingSessionThroughItsMod(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", ackedOK) term.typeAt("s2", true) @@ -496,6 +513,7 @@ func TestATaskReachesADraftingSessionThroughItsMod(t *testing.T) { } func TestAScheduledPromptReachesADraftingSessionThroughItsMod(t *testing.T) { + t.Parallel() writer := &scheduleWriter{} term := newFakeTerminal("s1") term.attachMod("s1", ackedOK) diff --git a/internal/relay/workeranswer_test.go b/internal/relay/workeranswer_test.go index 3a67bc3b..fc4a2407 100644 --- a/internal/relay/workeranswer_test.go +++ b/internal/relay/workeranswer_test.go @@ -44,6 +44,7 @@ func sendSubagentTask(t *testing.T, svc *Service) Result { // A worker whose mod answers for it is handed the task the way a native // subagent is: no ticket, no reply command, only who asked. func TestATaskForAWorkerWhoseModAnswersCarriesNoTicket(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.answerByMod("s2", ackedOK) svc := viaMod(term, nil) @@ -66,6 +67,7 @@ func TestATaskForAWorkerWhoseModAnswersCarriesNoTicket(t *testing.T) { // A worker whose mod does not answer (an older plugin, or none) still needs the // ticket: its reply is the only way home. func TestATaskForAWorkerWhoseModDoesNotAnswerKeepsTheTicket(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s2", ackedOK) svc := viaMod(term, nil) @@ -82,6 +84,7 @@ func TestATaskForAWorkerWhoseModDoesNotAnswerKeepsTheTicket(t *testing.T) { // Only a subagent errand is answered by the mod: an ordinary send to the same // session keeps its ticket. func TestAnOrdinaryTaskToAWorkerWhoseModAnswersKeepsTheTicket(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.answerByMod("s2", ackedOK) svc := viaMod(term, nil) @@ -99,6 +102,7 @@ func TestAnOrdinaryTaskToAWorkerWhoseModAnswersKeepsTheTicket(t *testing.T) { } func TestAWorkersModAnswersItsErrand(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -116,6 +120,7 @@ func TestAWorkersModAnswersItsErrand(t *testing.T) { // The caller reads a mod's answer exactly as it reads a reply: whole, through // its own mod, as a finished background agent. func TestAModsAnswerReachesTheCallerAsTheReport(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") term.attachMod("s1", ackedOK) svc := viaMod(term, nil) @@ -137,6 +142,7 @@ func TestAModsAnswerReachesTheCallerAsTheReport(t *testing.T) { // An answer from a session nobody handed a subagent errand is dropped: the mod // cannot tell a worker from a session whose subagents the user kept native. func TestAnAnswerFromASessionWithNoSubagentErrandIsIgnored(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plant(svc, "t1", "s1", "s2", "docs") @@ -152,6 +158,7 @@ func TestAnAnswerFromASessionWithNoSubagentErrandIsIgnored(t *testing.T) { // The worker may still call reply_to_session itself: the first answer wins and // the mod's, landing after it, is dropped. func TestTheFirstAnswerWins(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -172,6 +179,7 @@ func TestTheFirstAnswerWins(t *testing.T) { // With two subagent errands open nothing says which the text answers, so // neither is closed on a guess. func TestAnAnswerBetweenTwoSubagentErrandsIsIgnored(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") plantAnsweredByMod(svc, "t2", "s1", "s2", "docs") @@ -189,6 +197,7 @@ func TestAnAnswerBetweenTwoSubagentErrandsIsIgnored(t *testing.T) { // report yet; its mod answers when it resumes. That turn ending must not tell // the caller the errand went unanswered. func TestATurnEndingWithoutTheModsAnswerKeepsTheErrandOpen(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") svc := newRelay(workspace(), term, nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -218,6 +227,7 @@ func TestATurnEndingWithoutTheModsAnswerKeepsTheErrandOpen(t *testing.T) { // The mod's answer and the turn's done report race: whichever lands last // finishes the worker. func TestAWorkerWhoseAnswerLandsAfterItsTurnEndedIsFinished(t *testing.T) { + t.Parallel() svc, finished := finishing(t) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -229,6 +239,7 @@ func TestAWorkerWhoseAnswerLandsAfterItsTurnEndedIsFinished(t *testing.T) { } func TestAWorkerWhoseAnswerLandsMidTurnIsFinishedWhenItEnds(t *testing.T) { + t.Parallel() svc, finished := finishing(t) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -262,6 +273,7 @@ func expectAnswer(t *testing.T, svc *Service, id, want string) { // Claude Code's tasks. Its mod reports that turn, and the report is only "I // handed it off": the errand must wait for the turn that has the result. func TestAWorkersAnswerWaitsForTheErrandsItSent(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -284,6 +296,7 @@ func TestAWorkersAnswerWaitsForTheErrandsItSent(t *testing.T) { // An ordinary errand the worker sent holds its answer the same way: its // outcome reaches the worker's prompt and starts the turn that answers. func TestAWorkersAnswerWaitsForAnOrdinaryErrandItSent(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") plant(svc, "t2", "s2", "s3", "api") @@ -295,6 +308,7 @@ func TestAWorkersAnswerWaitsForAnOrdinaryErrandItSent(t *testing.T) { // A private errand reaches no prompt, so nothing would ever resume the worker // for it: it does not hold the answer. func TestAPrivateErrandDoesNotHoldAWorkersAnswer(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") plant(svc, "t2", "s2", "s3", "api") @@ -309,6 +323,7 @@ func TestAPrivateErrandDoesNotHoldAWorkersAnswer(t *testing.T) { // A result that lands while the worker is mid-turn is handed to it only when // that turn ends, so the turn's own report was written without it. func TestAWorkersAnswerWaitsForAResultItHasNotRead(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -331,6 +346,7 @@ func TestAWorkersAnswerWaitsForAResultItHasNotRead(t *testing.T) { // A result the worker was told about and chose not to collect does not hold // its answer forever: the turn after the notice is the one that read it. func TestAResultTheWorkerWasToldAboutDoesNotHoldItsAnswer(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -351,6 +367,7 @@ func TestAResultTheWorkerWasToldAboutDoesNotHoldItsAnswer(t *testing.T) { // that ended in silence. Someone is waiting on it, so it hears the errand // stopped, and that is what resumes it. func TestAWorkerHearsItsOwnWorkerStopped(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") plantAnsweredByMod(svc, "t2", "s2", "s3", "api") @@ -373,6 +390,7 @@ func TestAWorkerHearsItsOwnWorkerStopped(t *testing.T) { // its report until something else started a turn there. Someone is waiting on // the worker, so it hears the errand expired, and that is what resumes it. func TestAWorkerHearsItsOwnErrandExpired(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2", "s3") svc := newRelay(workspace(), term, nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -401,6 +419,7 @@ func TestAWorkerHearsItsOwnErrandExpired(t *testing.T) { // A worker that answered by its ticket while its own worker still runs is not // closed under that worker: the report it is owed would reach no one. func TestAWorkerWithAnErrandOfItsOwnOpenIsNotFinished(t *testing.T) { + t.Parallel() svc, finished := finishing(t) plantSubagent(svc, "t1", "s1", "s2", "docs") plantSubagent(svc, "t2", "s2", "s3", "api") @@ -418,6 +437,7 @@ func TestAWorkerWithAnErrandOfItsOwnOpenIsNotFinished(t *testing.T) { // while the worker runs, its errand would never end: the caller hears // unanswered, with why. func TestAWorkersUnansweredTurnEndsItsErrand(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -439,6 +459,7 @@ func TestAWorkersUnansweredTurnEndsItsErrand(t *testing.T) { } func TestACallerHoldingTheLineHearsAWorkerWentUnanswered(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -463,6 +484,7 @@ func TestACallerHoldingTheLineHearsAWorkerWentUnanswered(t *testing.T) { // The worker's card stays open: its user can still steer it to an answer, and // that answer reaches the caller by the ticket. func TestAWorkersAnswerAfterAnUnansweredTurnStillReachesTheCaller(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -475,6 +497,7 @@ func TestAWorkersAnswerAfterAnUnansweredTurnStillReachesTheCaller(t *testing.T) // An errand already ended is not ended twice: a second empty turn files no // second outcome. func TestASecondUnansweredTurnFilesNothingMore(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") @@ -491,6 +514,7 @@ func TestASecondUnansweredTurnFilesNothingMore(t *testing.T) { // An empty turn while an errand of the worker's own is out is the turn that // handed it off: the outcome reaching the worker resumes it. func TestAnUnansweredTurnWaitsForTheErrandsTheWorkerSent(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2", "s3"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") plant(svc, "t2", "s2", "s3", "api") @@ -502,6 +526,7 @@ func TestAnUnansweredTurnWaitsForTheErrandsTheWorkerSent(t *testing.T) { // A usage limit is an API error lich parks the continuation of, and that // continuation is the turn that answers. func TestAnErrorWhileAResumeIsParkedKeepsTheErrandOpen(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantAnsweredByMod(svc, "t1", "s1", "s2", "docs") svc.markResume("s2") @@ -517,6 +542,7 @@ func TestAnErrorWhileAResumeIsParkedKeepsTheErrandOpen(t *testing.T) { // An ordinary errand is not the mod's to end. func TestAnUnansweredTurnLeavesAnOrdinaryErrandAlone(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plant(svc, "t1", "s1", "s2", "docs") @@ -530,6 +556,7 @@ func TestAnUnansweredTurnLeavesAnOrdinaryErrandAlone(t *testing.T) { // without an answer, whether the report is still on its way or already waits // in its inbox for the prompt to free up. func TestATurnEndingWhileTheWorkerAwaitsItsOwnErrandKeepsItsErrandOpen(t *testing.T) { + t.Parallel() for name, reportFirst := range map[string]bool{"report still running": false, "report waiting": true} { t.Run(name, func(t *testing.T) { term := newFakeTerminal("s1", "s2", "s3") diff --git a/internal/relay/workerclosed_test.go b/internal/relay/workerclosed_test.go index 1b012e27..8526402b 100644 --- a/internal/relay/workerclosed_test.go +++ b/internal/relay/workerclosed_test.go @@ -11,6 +11,7 @@ import ( // the errand ends there and the caller is told nothing: the SessionEnd its // dying CLI reports a moment later finds no errand to call unanswered. func TestClosingAWorkerEndsItsErrandSilently(t *testing.T) { + t.Parallel() term := newFakeTerminal("s1", "s2") events := &fakeEvents{} svc := newRelay(workspace(), term, events) @@ -42,6 +43,7 @@ func TestClosingAWorkerEndsItsErrandSilently(t *testing.T) { // or by another session, ends work the caller never stopped, so the caller hears // it stopped the way it hears any other outcome: in its inbox, with a nudge. func TestAWorkerClosedByAnotherHandTellsItsCallerItStopped(t *testing.T) { + t.Parallel() for _, closer := range []string{"", "s3"} { t.Run("closer="+closer, func(t *testing.T) { term := newFakeTerminal("s1", "s2", "s3") @@ -67,6 +69,7 @@ func TestAWorkerClosedByAnotherHandTellsItsCallerItStopped(t *testing.T) { // A caller still holding the line hears how the errand ended: stopped, which no // card has to be opened about. func TestAWaiterOnAClosedWorkerHearsItStopped(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plantSubagent(svc, "t1", "s1", "s2", "docs") @@ -94,6 +97,7 @@ func TestAWaiterOnAClosedWorkerHearsItStopped(t *testing.T) { // Only subagent errands end with their worker's close: an ordinary errand at // a closed session still ends as it always did. func TestClosingASessionLeavesOrdinaryErrandsToTheirEnd(t *testing.T) { + t.Parallel() svc := newRelay(workspace(), newFakeTerminal("s1", "s2"), nil) plant(svc, "t1", "s1", "s2", "docs")