| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- package shell
- import (
- "context"
- "runtime"
- "strings"
- "testing"
- "time"
- )
- func TestBackgroundShellManager_Start(t *testing.T) {
- t.Skip("Skipping this until I figure out why its flaky")
- t.Parallel()
- ctx := context.Background()
- 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 := context.Background()
- 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 := context.Background()
- 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 := context.Background()
- 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 a bit for the command to complete
- time.Sleep(100 * time.Millisecond)
- if !bgShell.IsDone() {
- t.Error("expected shell to be done")
- }
- // Clean up
- manager.Kill(bgShell.ID)
- }
- func TestBackgroundShell_WithBlockFuncs(t *testing.T) {
- t.Parallel()
- ctx := context.Background()
- 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 := context.Background()
- 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 := context.Background()
- 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()
- // 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)
- }
- }
- }
|