59 lines
1.7 KiB
Go
59 lines
1.7 KiB
Go
package builtin
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"reasonix/internal/event"
|
|
"reasonix/internal/jobs"
|
|
"reasonix/internal/sandbox"
|
|
)
|
|
|
|
// A foreground bash command keeps the Windows sandbox's short lock wait so a
|
|
// queued turn fails fast with the holder named; a background job blocks nobody
|
|
// while it queues, so it opts into the patient wait instead of dying while
|
|
// another sandboxed command holds the workspace.
|
|
func TestBashSandboxLockWaitForegroundVsBackground(t *testing.T) {
|
|
sh := sandbox.ResolveShell("", "", nil)
|
|
var mu sync.Mutex
|
|
var waits []time.Duration
|
|
oldCommand := bashSandboxCommand
|
|
bashSandboxCommand = func(spec sandbox.Spec, sh sandbox.Shell, command string) ([]string, bool) {
|
|
mu.Lock()
|
|
waits = append(waits, spec.WindowsLockWait)
|
|
mu.Unlock()
|
|
return unconfinedShellArgv(sh, command), false
|
|
}
|
|
defer func() { bashSandboxCommand = oldCommand }()
|
|
|
|
if _, err := (bash{shell: sh}).Execute(context.Background(), argsJSON(t, map[string]any{
|
|
"command": echoForShell(sh, "fg"),
|
|
})); err != nil {
|
|
t.Fatalf("foreground bash: %v", err)
|
|
}
|
|
|
|
m := jobs.NewManager(event.Discard)
|
|
defer m.Close()
|
|
ctx := jobs.WithManager(context.Background(), m)
|
|
if _, err := (bash{shell: sh}).Execute(ctx, argsJSON(t, map[string]any{
|
|
"command": echoForShell(sh, "bg"),
|
|
"run_in_background": true,
|
|
})); err != nil {
|
|
t.Fatalf("background bash: %v", err)
|
|
}
|
|
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
if len(waits) != 2 {
|
|
t.Fatalf("sandbox wraps = %d, want 2", len(waits))
|
|
}
|
|
if waits[0] != 0 {
|
|
t.Fatalf("foreground WindowsLockWait = %s, want 0 (the short interactive default)", waits[0])
|
|
}
|
|
if waits[1] != windowsBackgroundSandboxLockWait {
|
|
t.Fatalf("background WindowsLockWait = %s, want %s", waits[1], windowsBackgroundSandboxLockWait)
|
|
}
|
|
}
|