Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/app/app_jobs_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func TestE2E_SpawnAgentToolViaSlashCommand(t *testing.T) {
if err != nil {
t.Fatalf("jobs.NewManager: %v", err)
}
defer func() { _ = mgr.Shutdown(2 * time.Second) }()
defer func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) }()

// Build a minimal App by hand so we don't have to stand up every
// Deps field. The fields we need for this test are: deps.Jobs,
Expand Down
7 changes: 4 additions & 3 deletions internal/app/app_lifecycle_parity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
tea "github.com/charmbracelet/bubbletea"

"github.com/packetcode/packetcode/internal/agent"
"github.com/packetcode/packetcode/internal/testwait"
"github.com/packetcode/packetcode/internal/ui/components/agentview"
)

Expand All @@ -28,7 +29,7 @@ func TestFirstVisibleProgressStopsThinkingSpinner(t *testing.T) {
func TestLeftArrowOpensAgentsOnlyFromEmptyIdleInput(t *testing.T) {
r := newTestApp(t)
mgr := wireJobsManagerForSlashTest(t, r)
t.Cleanup(func() { _ = mgr.Shutdown(2 * time.Second) })
t.Cleanup(func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) })
r.app.input.Reset()
r.app.handleKey(tea.KeyMsg{Type: tea.KeyLeft})
if !r.app.agentView.Visible() {
Expand All @@ -46,7 +47,7 @@ func TestLeftArrowOpensAgentsOnlyFromEmptyIdleInput(t *testing.T) {
func TestAgentWorkspaceTaskPromptCanClearReturnAndSpawn(t *testing.T) {
r := newTestApp(t)
mgr := wireJobsManagerForSlashTest(t, r)
t.Cleanup(func() { _ = mgr.Shutdown(2 * time.Second) })
t.Cleanup(func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) })

r.app.showAgentView()
r.app.handleKey(tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune("n")})
Expand Down Expand Up @@ -84,7 +85,7 @@ func TestAgentWorkspaceTaskPromptCanClearReturnAndSpawn(t *testing.T) {
func TestAgentWorkspaceListActionsAreNotSwallowedByTaskInput(t *testing.T) {
r := newTestApp(t)
mgr := wireJobsManagerForSlashTest(t, r)
t.Cleanup(func() { _ = mgr.Shutdown(2 * time.Second) })
t.Cleanup(func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) })

_, _ = r.app.handleSpawnCommand([]string{"inspect the renderer"})
r.app.showAgentView()
Expand Down
11 changes: 6 additions & 5 deletions internal/app/app_slashcmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/packetcode/packetcode/internal/provider"
"github.com/packetcode/packetcode/internal/session"
"github.com/packetcode/packetcode/internal/statusline"
"github.com/packetcode/packetcode/internal/testwait"
"github.com/packetcode/packetcode/internal/tools"
"github.com/packetcode/packetcode/internal/ui/components/agentview"
"github.com/packetcode/packetcode/internal/ui/components/approval"
Expand Down Expand Up @@ -1459,7 +1460,7 @@ func TestApp_Queue_ListDropAndClear(t *testing.T) {
func TestApp_Agents_ListUsesBackgroundJobs(t *testing.T) {
r := newTestApp(t)
mgr := wireJobsManagerForSlashTest(t, r)
defer func() { _ = mgr.Shutdown(2 * time.Second) }()
defer func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) }()

snap, spawnErr := mgr.Spawn(jobs.SpawnRequest{
Prompt: "audit fixtures",
Expand All @@ -1483,7 +1484,7 @@ func TestApp_Agents_ListUsesBackgroundJobs(t *testing.T) {
func TestApp_Agents_DetailOpensJobsPanel(t *testing.T) {
r := newTestApp(t)
mgr := wireJobsManagerForSlashTest(t, r)
defer func() { _ = mgr.Shutdown(2 * time.Second) }()
defer func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) }()

snap, spawnErr := mgr.Spawn(jobs.SpawnRequest{
Prompt: "inspect flaky test",
Expand All @@ -1503,7 +1504,7 @@ func TestApp_Agents_DetailOpensJobsPanel(t *testing.T) {
func TestApp_Agents_NotFoundUsesAgentLabel(t *testing.T) {
r := newTestApp(t)
mgr := wireJobsManagerForSlashTest(t, r)
defer func() { _ = mgr.Shutdown(2 * time.Second) }()
defer func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) }()

r.app.handleSlashCommand("agents", []string{"missing"}, "/agents missing")
convContains(t, r.app, "[agent:missing not found]")
Expand All @@ -1512,7 +1513,7 @@ func TestApp_Agents_NotFoundUsesAgentLabel(t *testing.T) {
func TestApp_Agents_ViewDoesNotOverrideJobsPanelOverlay(t *testing.T) {
r := newTestApp(t)
mgr := wireJobsManagerForSlashTest(t, r)
defer func() { _ = mgr.Shutdown(2 * time.Second) }()
defer func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) }()

snap, spawnErr := mgr.Spawn(jobs.SpawnRequest{
Prompt: "inspect overlay",
Expand Down Expand Up @@ -1646,7 +1647,7 @@ func TestApp_ResizeRecomposesBuiltInStatusLine(t *testing.T) {
func TestApp_HandleJobUpdate_IgnoresStaleSeqAndDedupesTerminal(t *testing.T) {
r := newTestApp(t)
mgr := wireJobsManagerForSlashTest(t, r)
defer func() { _ = mgr.Shutdown(2 * time.Second) }()
defer func() { _ = mgr.Shutdown(testwait.Timeout(2 * time.Second)) }()

snap, spawnErr := mgr.Spawn(jobs.SpawnRequest{
Prompt: "finish once",
Expand Down
3 changes: 2 additions & 1 deletion internal/jobs/abandoned_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/packetcode/packetcode/internal/testwait"
"github.com/packetcode/packetcode/internal/tools"
)

Expand Down Expand Up @@ -133,7 +134,7 @@ func TestCancel_RecordsRequestAndStaysCancelled(t *testing.T) {
// loadPersistedJobs reconciles anything still marked running — so reading
// the directory under a live manager would race the flush and rewrite the
// very record under test.
require.NoError(t, mgr.Shutdown(2*time.Second))
require.NoError(t, mgr.Shutdown(testwait.Timeout(2*time.Second)))

reloaded, _, unread, lerr := loadPersistedJobs(jobsDir, "")
require.NoError(t, lerr)
Expand Down
3 changes: 2 additions & 1 deletion internal/jobs/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/packetcode/packetcode/internal/config"
"github.com/packetcode/packetcode/internal/permissions"
"github.com/packetcode/packetcode/internal/provider"
"github.com/packetcode/packetcode/internal/testwait"
"github.com/packetcode/packetcode/internal/tools"
)

Expand Down Expand Up @@ -322,7 +323,7 @@ func TestManager_Shutdown_Persists(t *testing.T) {
return running == N
})

require.NoError(t, mgr.Shutdown(2*time.Second))
require.NoError(t, mgr.Shutdown(testwait.Timeout(2*time.Second)))

for _, id := range ids {
snap, ok := mgr.Get(id)
Expand Down
8 changes: 5 additions & 3 deletions internal/jobs/persistence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/packetcode/packetcode/internal/testwait"
)

// TestSaveSnapshot_AtomicWrite confirms the temp-file-then-rename
Expand Down Expand Up @@ -175,7 +177,7 @@ func TestManagerPersistenceDebouncesNonterminalUpdates(t *testing.T) {
dir := t.TempDir()
mgr, _, err := NewManager(Config{JobsDir: dir})
require.NoError(t, err)
t.Cleanup(func() { _ = mgr.Shutdown(time.Second) })
t.Cleanup(func() { _ = mgr.Shutdown(testwait.Timeout(time.Second)) })
mgr.persistDelay = time.Hour

for seq := int64(1); seq <= 3; seq++ {
Expand All @@ -197,7 +199,7 @@ func TestManagerPersistenceTerminalFlushIsSynchronous(t *testing.T) {
dir := t.TempDir()
mgr, _, err := NewManager(Config{JobsDir: dir})
require.NoError(t, err)
t.Cleanup(func() { _ = mgr.Shutdown(time.Second) })
t.Cleanup(func() { _ = mgr.Shutdown(testwait.Timeout(time.Second)) })
mgr.persistDelay = time.Hour
require.NoError(t, mgr.savePersistedSnapshot(persistedJob{ID: "terminal", State: "running", Seq: 1}))
require.NoError(t, mgr.savePersistedSnapshot(persistedJob{ID: "terminal", State: "completed", Seq: 2, Summary: "done"}))
Expand All @@ -219,7 +221,7 @@ func TestManagerShutdownFlushesPendingSnapshots(t *testing.T) {
mgr.persistDelay = time.Hour
require.NoError(t, mgr.savePersistedSnapshot(persistedJob{ID: "shutdown", State: "running", Seq: 7, LastMessage: "latest"}))

require.NoError(t, mgr.Shutdown(time.Second))
require.NoError(t, mgr.Shutdown(testwait.Timeout(time.Second)))
got, ok := readPersistedJob(filepath.Join(dir, "shutdown.json"))
require.True(t, ok)
assert.Equal(t, int64(7), got.Seq)
Expand Down
19 changes: 18 additions & 1 deletion internal/jobs/testhelpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,25 @@ func newTestManager(t *testing.T, prov provider.Provider, opts ...func(*Config))
}
mgr, _, err := NewManager(cfg)
require.NoError(t, err)
// Scaled, and reported rather than discarded.
//
// Shutdown returns when its timeout expires whether or not the workers
// stopped. Two seconds was ample on an idle machine and not ample under a
// parallel suite, and what happened then was not a slow test but a broken
// one: the workers were still running, still writing job records into the
// t.TempDir() Go was about to remove. On Windows a directory that is
// gaining files cannot be removed, so the test died in cleanup with
// "TempDir RemoveAll cleanup: ... The directory is not empty" -- naming
// neither the worker, nor the timeout, nor even the assertion it never
// reached. TestResubmit_IsOnlyAllowedOnce failed that way.
//
// The error says "N workers still running after ...", which is the one
// sentence that would have identified this immediately. Discarding it was
// how a shutdown that did not shut anything down looked like success.
t.Cleanup(func() {
_ = mgr.Shutdown(2 * time.Second)
if err := mgr.Shutdown(testwait.Timeout(2 * time.Second)); err != nil {
t.Errorf("jobs manager did not shut down cleanly: %v", err)
}
})
return mgr, tr
}
Expand Down