Download internal/shell/background_test.go from SaylorTwift/crush: direct link, hf CLI and curl.
- Browser
- Download file 7.75 kB
-
https://huggingface.co/SaylorTwift/crush/resolve/main/internal/shell/background_test.go
- Command line
-
hf download hf://SaylorTwift/crush/internal/shell/background_test.go
-
curl -L -o background_test.go https://huggingface.co/SaylorTwift/crush/resolve/main/internal/shell/background_test.go
7.75 kB
| package shell | |
| import ( | |
| "context" | |
| "runtime" | |
| "strings" | |
| "testing" | |
| "time" | |
| "github.com/stretchr/testify/require" | |
| ) | |
| func TestBackgroundShellManager_Start(t *testing.T) { | |
| t.Skip("Skipping this until I figure out why its flaky") | |
| t.Parallel() | |
| ctx := t.Context() | |
| workingDir := t.TempDir() | |
| manager := newBackgroundShellManager() | |
| bgShell, err := manager.Start(ctx, workingDir, nil, "echo 'hello world'", "") | |
| if err != nil { | |
| t.Fatalf("failed to start background shell: %v", err) | |
| } | |
| if bgShell.ID == "" { | |
| t.Error("expected shell ID to be non-empty") | |
| } | |
| // Wait for the command to complete | |
| bgShell.Wait() | |
| stdout, stderr, done, err := bgShell.GetOutput() | |
| if !done { | |
| t.Error("expected shell to be done") | |
| } | |
| if err != nil { | |
| t.Errorf("expected no error, got: %v", err) | |
| } | |
| if !strings.Contains(stdout, "hello world") { | |
| t.Errorf("expected stdout to contain 'hello world', got: %s", stdout) | |
| } | |
| if stderr != "" { | |
| t.Errorf("expected empty stderr, got: %s", stderr) | |
| } | |
| } | |
| func TestBackgroundShellManager_Get(t *testing.T) { | |
| t.Parallel() | |
| ctx := t.Context() | |
| workingDir := t.TempDir() | |
| manager := newBackgroundShellManager() | |
| bgShell, err := manager.Start(ctx, workingDir, nil, "echo 'test'", "") | |
| if err != nil { | |
| t.Fatalf("failed to start background shell: %v", err) | |
| } | |
| // Retrieve the shell | |
| retrieved, ok := manager.Get(bgShell.ID) | |
| if !ok { | |
| t.Error("expected to find the background shell") | |
| } | |
| if retrieved.ID != bgShell.ID { | |
| t.Errorf("expected shell ID %s, got %s", bgShell.ID, retrieved.ID) | |
| } | |
| // Clean up | |
| manager.Kill(bgShell.ID) | |
| } | |
| func TestBackgroundShellManager_Kill(t *testing.T) { | |
| t.Parallel() | |
| ctx := t.Context() | |
| workingDir := t.TempDir() | |
| manager := newBackgroundShellManager() | |
| // Start a long-running command | |
| bgShell, err := manager.Start(ctx, workingDir, nil, "sleep 10", "") | |
| if err != nil { | |
| t.Fatalf("failed to start background shell: %v", err) | |
| } | |
| // Kill it | |
| err = manager.Kill(bgShell.ID) | |
| if err != nil { | |
| t.Errorf("failed to kill background shell: %v", err) | |
| } | |
| // Verify it's no longer in the manager | |
| _, ok := manager.Get(bgShell.ID) | |
| if ok { | |
| t.Error("expected shell to be removed after kill") | |
| } | |
| // Verify the shell is done | |
| if !bgShell.IsDone() { | |
| t.Error("expected shell to be done after kill") | |
| } | |
| } | |
| func TestBackgroundShellManager_KillNonExistent(t *testing.T) { | |
| t.Parallel() | |
| manager := newBackgroundShellManager() | |
| err := manager.Kill("non-existent-id") | |
| if err == nil { | |
| t.Error("expected error when killing non-existent shell") | |
| } | |
| } | |
| func TestBackgroundShell_IsDone(t *testing.T) { | |
| t.Parallel() | |
| ctx := t.Context() | |
| workingDir := t.TempDir() | |
| manager := newBackgroundShellManager() | |
| bgShell, err := manager.Start(ctx, workingDir, nil, "echo 'quick'", "") | |
| if err != nil { | |
| t.Fatalf("failed to start background shell: %v", err) | |
| } | |
| // Wait for the command to complete (Windows is slower to spin up). | |
| require.Eventually(t, bgShell.IsDone, 5*time.Second, 50*time.Millisecond, "expected shell to be done") | |
| // Clean up | |
| manager.Kill(bgShell.ID) | |
| } | |
| func TestBackgroundShell_WithBlockFuncs(t *testing.T) { | |
| t.Parallel() | |
| ctx := t.Context() | |
| workingDir := t.TempDir() | |
| manager := newBackgroundShellManager() | |
| blockFuncs := []BlockFunc{ | |
| CommandsBlocker([]string{"curl", "wget"}), | |
| } | |
| bgShell, err := manager.Start(ctx, workingDir, blockFuncs, "curl example.com", "") | |
| if err != nil { | |
| t.Fatalf("failed to start background shell: %v", err) | |
| } | |
| // Wait for the command to complete | |
| bgShell.Wait() | |
| stdout, stderr, done, execErr := bgShell.GetOutput() | |
| if !done { | |
| t.Error("expected shell to be done") | |
| } | |
| // The command should have been blocked | |
| output := stdout + stderr | |
| if !strings.Contains(output, "not allowed") && execErr == nil { | |
| t.Errorf("expected command to be blocked, got stdout: %s, stderr: %s, err: %v", stdout, stderr, execErr) | |
| } | |
| // Clean up | |
| manager.Kill(bgShell.ID) | |
| } | |
| func TestBackgroundShellManager_List(t *testing.T) { | |
| if runtime.GOOS == "windows" { | |
| t.Skip("skipping flacky test on windows") | |
| } | |
| t.Parallel() | |
| ctx := t.Context() | |
| workingDir := t.TempDir() | |
| manager := newBackgroundShellManager() | |
| // Start two shells | |
| bgShell1, err := manager.Start(ctx, workingDir, nil, "sleep 1", "") | |
| if err != nil { | |
| t.Fatalf("failed to start first background shell: %v", err) | |
| } | |
| bgShell2, err := manager.Start(ctx, workingDir, nil, "sleep 1", "") | |
| if err != nil { | |
| t.Fatalf("failed to start second background shell: %v", err) | |
| } | |
| ids := manager.List() | |
| // Check that both shells are in the list | |
| found1 := false | |
| found2 := false | |
| for _, id := range ids { | |
| if id == bgShell1.ID { | |
| found1 = true | |
| } | |
| if id == bgShell2.ID { | |
| found2 = true | |
| } | |
| } | |
| if !found1 { | |
| t.Errorf("expected to find shell %s in list", bgShell1.ID) | |
| } | |
| if !found2 { | |
| t.Errorf("expected to find shell %s in list", bgShell2.ID) | |
| } | |
| // Clean up | |
| manager.Kill(bgShell1.ID) | |
| manager.Kill(bgShell2.ID) | |
| } | |
| func TestBackgroundShellManager_KillAll(t *testing.T) { | |
| t.Parallel() | |
| ctx := t.Context() | |
| workingDir := t.TempDir() | |
| manager := newBackgroundShellManager() | |
| // Start multiple long-running shells | |
| shell1, err := manager.Start(ctx, workingDir, nil, "sleep 10", "") | |
| if err != nil { | |
| t.Fatalf("failed to start shell 1: %v", err) | |
| } | |
| shell2, err := manager.Start(ctx, workingDir, nil, "sleep 10", "") | |
| if err != nil { | |
| t.Fatalf("failed to start shell 2: %v", err) | |
| } | |
| shell3, err := manager.Start(ctx, workingDir, nil, "sleep 10", "") | |
| if err != nil { | |
| t.Fatalf("failed to start shell 3: %v", err) | |
| } | |
| // Verify shells are running | |
| if shell1.IsDone() || shell2.IsDone() || shell3.IsDone() { | |
| t.Error("shells should not be done yet") | |
| } | |
| // Kill all shells | |
| manager.KillAll(t.Context()) | |
| // Verify all shells are done | |
| if !shell1.IsDone() { | |
| t.Error("shell1 should be done after KillAll") | |
| } | |
| if !shell2.IsDone() { | |
| t.Error("shell2 should be done after KillAll") | |
| } | |
| if !shell3.IsDone() { | |
| t.Error("shell3 should be done after KillAll") | |
| } | |
| // Verify they're removed from the manager | |
| if _, ok := manager.Get(shell1.ID); ok { | |
| t.Error("shell1 should be removed from manager") | |
| } | |
| if _, ok := manager.Get(shell2.ID); ok { | |
| t.Error("shell2 should be removed from manager") | |
| } | |
| if _, ok := manager.Get(shell3.ID); ok { | |
| t.Error("shell3 should be removed from manager") | |
| } | |
| // Verify list is empty (or doesn't contain our shells) | |
| ids := manager.List() | |
| for _, id := range ids { | |
| if id == shell1.ID || id == shell2.ID || id == shell3.ID { | |
| t.Errorf("shell %s should not be in list after KillAll", id) | |
| } | |
| } | |
| } | |
| func TestBackgroundShellManager_KillAll_Timeout(t *testing.T) { | |
| t.Parallel() | |
| // XXX: can't use synctest here - causes --race to trip. | |
| workingDir := t.TempDir() | |
| manager := newBackgroundShellManager() | |
| // Start a shell that traps signals and ignores cancellation. | |
| _, err := manager.Start(t.Context(), workingDir, nil, "trap '' TERM INT; sleep 60", "") | |
| require.NoError(t, err) | |
| // Short timeout to test the timeout path. | |
| ctx, cancel := context.WithTimeout(t.Context(), 100*time.Millisecond) | |
| t.Cleanup(cancel) | |
| start := time.Now() | |
| manager.KillAll(ctx) | |
| elapsed := time.Since(start) | |
| // Must return promptly after timeout, not hang for 60 seconds. | |
| require.Less(t, elapsed, 2*time.Second) | |
| } | |
| func TestBackgroundShell_WaitContext_Completed(t *testing.T) { | |
| t.Parallel() | |
| done := make(chan struct{}) | |
| close(done) | |
| bgShell := &BackgroundShell{done: done} | |
| ctx, cancel := context.WithTimeout(t.Context(), time.Second) | |
| t.Cleanup(cancel) | |
| require.True(t, bgShell.WaitContext(ctx)) | |
| } | |
| func TestBackgroundShell_WaitContext_Canceled(t *testing.T) { | |
| t.Parallel() | |
| bgShell := &BackgroundShell{done: make(chan struct{})} | |
| ctx, cancel := context.WithCancel(t.Context()) | |
| cancel() | |
| require.False(t, bgShell.WaitContext(ctx)) | |
| } | |