Skip to content

Commit 6463e41

Browse files
committed
chore: add workspace bash background tests
1 parent d10a605 commit 6463e41

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

codersdk/toolsdk/bash_test.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/coder/coder/v2/agent/agenttest"
1010
"github.com/coder/coder/v2/coderd/coderdtest"
1111
"github.com/coder/coder/v2/codersdk/toolsdk"
12+
"github.com/coder/coder/v2/testutil"
1213
)
1314

1415
func TestWorkspaceBash(t *testing.T) {
@@ -338,3 +339,145 @@ func TestWorkspaceBashTimeoutIntegration(t *testing.T) {
338339
require.NotContains(t, result.Output, "Command canceled due to timeout")
339340
})
340341
}
342+
343+
func TestWorkspaceBashBackgroundIntegration(t *testing.T) {
344+
t.Parallel()
345+
346+
t.Run("BackgroundCommandReturnsImmediately", func(t *testing.T) {
347+
t.Parallel()
348+
349+
client, workspace, agentToken := setupWorkspaceForAgent(t)
350+
351+
// Start the agent and wait for it to be fully ready
352+
_ = agenttest.New(t, client.URL, agentToken)
353+
354+
// Wait for workspace agents to be ready
355+
coderdtest.NewWorkspaceAgentWaiter(t, client, workspace.ID).Wait()
356+
357+
deps, err := toolsdk.NewDeps(client)
358+
require.NoError(t, err)
359+
360+
args := toolsdk.WorkspaceBashArgs{
361+
Workspace: workspace.Name,
362+
Command: `echo "started" && sleep 5 && echo "completed"`, // Command that would take 5+ seconds
363+
Background: true, // Run in background
364+
}
365+
366+
result, err := toolsdk.WorkspaceBash.Handler(t.Context(), deps, args)
367+
368+
// Should not error
369+
require.NoError(t, err)
370+
371+
t.Logf("Background result: exitCode=%d, output=%q", result.ExitCode, result.Output)
372+
373+
// Should have exit code 0 (background start successful)
374+
require.Equal(t, 0, result.ExitCode)
375+
376+
// Should contain PID and log path info, not the actual command output
377+
require.Contains(t, result.Output, "Command started with PID:")
378+
require.Contains(t, result.Output, "Log path: /tmp/mcp-bg/")
379+
380+
// Should NOT contain the actual command output since it runs in background
381+
// The command was `echo "started" && sleep 5 && echo "completed"`
382+
// So we check that the quoted strings don't appear in the output
383+
require.NotContains(t, result.Output, `"started"`, "Should not contain command output in background mode")
384+
require.NotContains(t, result.Output, `"completed"`, "Should not contain command output in background mode")
385+
})
386+
387+
t.Run("BackgroundVsNormalExecution", func(t *testing.T) {
388+
t.Parallel()
389+
390+
client, workspace, agentToken := setupWorkspaceForAgent(t)
391+
392+
// Start the agent and wait for it to be fully ready
393+
_ = agenttest.New(t, client.URL, agentToken)
394+
395+
// Wait for workspace agents to be ready
396+
coderdtest.NewWorkspaceAgentWaiter(t, client, workspace.ID).Wait()
397+
398+
deps, err := toolsdk.NewDeps(client)
399+
require.NoError(t, err)
400+
401+
// First run the same command in normal mode
402+
normalArgs := toolsdk.WorkspaceBashArgs{
403+
Workspace: workspace.Name,
404+
Command: `echo "hello world"`,
405+
Background: false,
406+
}
407+
408+
normalResult, err := toolsdk.WorkspaceBash.Handler(t.Context(), deps, normalArgs)
409+
require.NoError(t, err)
410+
411+
// Normal mode should return the actual output
412+
require.Equal(t, 0, normalResult.ExitCode)
413+
require.Equal(t, "hello world", normalResult.Output)
414+
415+
// Now run the same command in background mode
416+
backgroundArgs := toolsdk.WorkspaceBashArgs{
417+
Workspace: workspace.Name,
418+
Command: `echo "hello world"`,
419+
Background: true,
420+
}
421+
422+
backgroundResult, err := toolsdk.WorkspaceBash.Handler(t.Context(), deps, backgroundArgs)
423+
require.NoError(t, err)
424+
425+
t.Logf("Normal result: %q", normalResult.Output)
426+
t.Logf("Background result: %q", backgroundResult.Output)
427+
428+
// Background mode should return PID/log info, not the actual output
429+
require.Equal(t, 0, backgroundResult.ExitCode)
430+
require.Contains(t, backgroundResult.Output, "Command started with PID:")
431+
require.Contains(t, backgroundResult.Output, "Log path: /tmp/mcp-bg/")
432+
require.NotContains(t, backgroundResult.Output, "hello world")
433+
})
434+
435+
t.Run("BackgroundIgnoresTimeout", func(t *testing.T) {
436+
t.Parallel()
437+
438+
client, workspace, agentToken := setupWorkspaceForAgent(t)
439+
440+
// Start the agent and wait for it to be fully ready
441+
_ = agenttest.New(t, client.URL, agentToken)
442+
443+
// Wait for workspace agents to be ready
444+
coderdtest.NewWorkspaceAgentWaiter(t, client, workspace.ID).Wait()
445+
446+
deps, err := toolsdk.NewDeps(client)
447+
require.NoError(t, err)
448+
449+
args := toolsdk.WorkspaceBashArgs{
450+
Workspace: workspace.Name,
451+
Command: `sleep 1 && echo "done" > /tmp/done`, // Command that would normally timeout
452+
TimeoutMs: 1, // 1 ms timeout (shorter than command duration)
453+
Background: true, // But running in background should ignore timeout
454+
}
455+
456+
result, err := toolsdk.WorkspaceBash.Handler(t.Context(), deps, args)
457+
458+
// Should not error and should not timeout
459+
require.NoError(t, err)
460+
461+
t.Logf("Background with timeout result: exitCode=%d, output=%q", result.ExitCode, result.Output)
462+
463+
// Should have exit code 0 (background start successful)
464+
require.Equal(t, 0, result.ExitCode)
465+
466+
// Should return PID/log info, indicating the background command started successfully
467+
require.Contains(t, result.Output, "Command started with PID:")
468+
require.Contains(t, result.Output, "Log path: /tmp/mcp-bg/")
469+
470+
// Should NOT contain timeout message since background mode ignores timeout
471+
require.NotContains(t, result.Output, "Command canceled due to timeout")
472+
473+
// Wait for the background command to complete
474+
require.Eventually(t, func() bool {
475+
args := toolsdk.WorkspaceBashArgs{
476+
Workspace: workspace.Name,
477+
Command: `cat /tmp/done`,
478+
}
479+
result, err := toolsdk.WorkspaceBash.Handler(t.Context(), deps, args)
480+
return err == nil && result.Output == "done"
481+
}, testutil.WaitMedium, testutil.IntervalMedium)
482+
})
483+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy