diff --git a/buffer_test.go b/buffer_test.go index 59443bc..79130b2 100644 --- a/buffer_test.go +++ b/buffer_test.go @@ -2,8 +2,6 @@ package process import ( "testing" - - "github.com/stretchr/testify/assert" ) func TestRingBuffer_Basics_Good(t *testing.T) { @@ -11,22 +9,22 @@ func TestRingBuffer_Basics_Good(t *testing.T) { rb := NewRingBuffer(10) n, err := rb.Write([]byte("hello")) - assert.NoError(t, err) - assert.Equal(t, 5, n) - assert.Equal(t, "hello", rb.String()) - assert.Equal(t, 5, rb.Len()) + assertNoError(t, err) + assertEqual(t, 5, n) + assertEqual(t, "hello", rb.String()) + assertEqual(t, 5, rb.Len()) }) t.Run("overflow wraps around", func(t *testing.T) { rb := NewRingBuffer(5) _, _ = rb.Write([]byte("hello")) - assert.Equal(t, "hello", rb.String()) + assertEqual(t, "hello", rb.String()) _, _ = rb.Write([]byte("world")) // Should contain "world" (overwrote "hello") - assert.Equal(t, 5, rb.Len()) - assert.Equal(t, "world", rb.String()) + assertEqual(t, 5, rb.Len()) + assertEqual(t, "world", rb.String()) }) t.Run("partial overflow", func(t *testing.T) { @@ -35,27 +33,27 @@ func TestRingBuffer_Basics_Good(t *testing.T) { _, _ = rb.Write([]byte("hello")) _, _ = rb.Write([]byte("worldx")) // Should contain "lloworldx" (11 chars, buffer is 10) - assert.Equal(t, 10, rb.Len()) + assertEqual(t, 10, rb.Len()) }) t.Run("empty buffer", func(t *testing.T) { rb := NewRingBuffer(10) - assert.Equal(t, "", rb.String()) - assert.Equal(t, 0, rb.Len()) - assert.Nil(t, rb.Bytes()) + assertEqual(t, "", rb.String()) + assertEqual(t, 0, rb.Len()) + assertNil(t, rb.Bytes()) }) t.Run("reset", func(t *testing.T) { rb := NewRingBuffer(10) _, _ = rb.Write([]byte("hello")) rb.Reset() - assert.Equal(t, "", rb.String()) - assert.Equal(t, 0, rb.Len()) + assertEqual(t, "", rb.String()) + assertEqual(t, 0, rb.Len()) }) t.Run("cap", func(t *testing.T) { rb := NewRingBuffer(42) - assert.Equal(t, 42, rb.Cap()) + assertEqual(t, 42, rb.Cap()) }) t.Run("bytes returns copy", func(t *testing.T) { @@ -63,11 +61,11 @@ func TestRingBuffer_Basics_Good(t *testing.T) { _, _ = rb.Write([]byte("hello")) bytes := rb.Bytes() - assert.Equal(t, []byte("hello"), bytes) + assertEqual(t, []byte("hello"), bytes) // Modifying returned bytes shouldn't affect buffer bytes[0] = 'x' - assert.Equal(t, "hello", rb.String()) + assertEqual(t, "hello", rb.String()) }) t.Run("zero or negative capacity is a no-op", func(t *testing.T) { @@ -75,12 +73,12 @@ func TestRingBuffer_Basics_Good(t *testing.T) { rb := NewRingBuffer(size) n, err := rb.Write([]byte("discarded")) - assert.NoError(t, err) - assert.Equal(t, len("discarded"), n) - assert.Equal(t, 0, rb.Cap()) - assert.Equal(t, 0, rb.Len()) - assert.Equal(t, "", rb.String()) - assert.Nil(t, rb.Bytes()) + assertNoError(t, err) + assertEqual(t, len("discarded"), n) + assertEqual(t, 0, rb.Cap()) + assertEqual(t, 0, rb.Len()) + assertEqual(t, "", rb.String()) + assertNil(t, rb.Bytes()) } }) } diff --git a/daemon_test.go b/daemon_test.go index 57c2cc6..0617e4f 100644 --- a/daemon_test.go +++ b/daemon_test.go @@ -8,9 +8,6 @@ import ( "sync" "testing" "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestDaemon_StartAndStop(t *testing.T) { @@ -23,18 +20,18 @@ func TestDaemon_StartAndStop(t *testing.T) { }) err := d.Start() - require.NoError(t, err) + requireNoError(t, err) addr := d.HealthAddr() - require.NotEmpty(t, addr) + requireNotEmpty(t, addr) resp, err := http.Get("http://" + addr + "/health") - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) + requireNoError(t, err) + assertEqual(t, http.StatusOK, resp.StatusCode) _ = resp.Body.Close() err = d.Stop() - require.NoError(t, err) + requireNoError(t, err) } func TestDaemon_StopMarksNotReadyBeforeShutdownCompletes(t *testing.T) { @@ -55,10 +52,10 @@ func TestDaemon_StopMarksNotReadyBeforeShutdownCompletes(t *testing.T) { }) err := d.Start() - require.NoError(t, err) + requireNoError(t, err) addr := d.HealthAddr() - require.NotEmpty(t, addr) + requireNotEmpty(t, addr) healthErr := make(chan error, 1) go func() { @@ -82,7 +79,7 @@ func TestDaemon_StopMarksNotReadyBeforeShutdownCompletes(t *testing.T) { stopDone <- d.Stop() }() - require.Eventually(t, func() bool { + requireEventually(t, func() bool { return !d.Ready() }, 500*time.Millisecond, 10*time.Millisecond, "daemon should become not ready before shutdown completes") @@ -96,14 +93,14 @@ func TestDaemon_StopMarksNotReadyBeforeShutdownCompletes(t *testing.T) { select { case err := <-stopDone: - require.NoError(t, err) + requireNoError(t, err) case <-time.After(2 * time.Second): t.Fatal("daemon stop did not finish after health check unblocked") } select { case err := <-healthErr: - require.NoError(t, err) + requireNoError(t, err) case <-time.After(2 * time.Second): t.Fatal("/health request did not finish") } @@ -134,10 +131,10 @@ func TestDaemon_StopUnregistersAfterHealthShutdownCompletes(t *testing.T) { }) err := d.Start() - require.NoError(t, err) + requireNoError(t, err) addr := d.HealthAddr() - require.NotEmpty(t, addr) + requireNotEmpty(t, addr) healthErr := make(chan error, 1) go func() { @@ -161,12 +158,12 @@ func TestDaemon_StopUnregistersAfterHealthShutdownCompletes(t *testing.T) { stopDone <- d.Stop() }() - require.Eventually(t, func() bool { + requireEventually(t, func() bool { return !d.Ready() }, 500*time.Millisecond, 10*time.Millisecond, "daemon should become not ready before shutdown completes") _, ok := reg.Get("test-app", "serve") - assert.True(t, ok, "daemon should remain registered until health shutdown completes") + assertTrue(t, ok, "daemon should remain registered until health shutdown completes") select { case err := <-stopDone: @@ -178,19 +175,19 @@ func TestDaemon_StopUnregistersAfterHealthShutdownCompletes(t *testing.T) { select { case err := <-stopDone: - require.NoError(t, err) + requireNoError(t, err) case <-time.After(2 * time.Second): t.Fatal("daemon stop did not finish after health check unblocked") } - require.Eventually(t, func() bool { + requireEventually(t, func() bool { _, ok := reg.Get("test-app", "serve") return !ok }, 500*time.Millisecond, 10*time.Millisecond, "daemon should unregister after health shutdown completes") select { case err := <-healthErr: - require.NoError(t, err) + requireNoError(t, err) case <-time.After(2 * time.Second): t.Fatal("/health request did not finish") } @@ -202,12 +199,12 @@ func TestDaemon_DoubleStartFails(t *testing.T) { }) err := d.Start() - require.NoError(t, err) + requireNoError(t, err) defer func() { _ = d.Stop() }() err = d.Start() - assert.Error(t, err) - assert.Contains(t, err.Error(), "already running") + assertError(t, err) + assertContains(t, err.Error(), "already running") } func TestDaemon_RunWithoutStartFails(t *testing.T) { @@ -217,16 +214,16 @@ func TestDaemon_RunWithoutStartFails(t *testing.T) { cancel() err := d.Run(ctx) - assert.Error(t, err) - assert.Contains(t, err.Error(), "not started") + assertError(t, err) + assertContains(t, err.Error(), "not started") } func TestDaemon_RunNilContextFails(t *testing.T) { d := NewDaemon(DaemonOptions{}) err := d.Run(nil) - require.Error(t, err) - assert.ErrorIs(t, err, ErrDaemonContextRequired) + requireError(t, err) + assertErrorIs(t, err, ErrDaemonContextRequired) } func TestDaemon_SetReady(t *testing.T) { @@ -235,37 +232,37 @@ func TestDaemon_SetReady(t *testing.T) { }) err := d.Start() - require.NoError(t, err) + requireNoError(t, err) defer func() { _ = d.Stop() }() addr := d.HealthAddr() resp, _ := http.Get("http://" + addr + "/ready") - assert.Equal(t, http.StatusOK, resp.StatusCode) + assertEqual(t, http.StatusOK, resp.StatusCode) _ = resp.Body.Close() - assert.True(t, d.Ready()) + assertTrue(t, d.Ready()) d.SetReady(false) - assert.False(t, d.Ready()) + assertFalse(t, d.Ready()) resp, _ = http.Get("http://" + addr + "/ready") - assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) + assertEqual(t, http.StatusServiceUnavailable, resp.StatusCode) _ = resp.Body.Close() } func TestDaemon_ReadyWithoutHealthServer(t *testing.T) { d := NewDaemon(DaemonOptions{}) - assert.False(t, d.Ready()) + assertFalse(t, d.Ready()) } func TestDaemon_NoHealthAddrReturnsEmpty(t *testing.T) { d := NewDaemon(DaemonOptions{}) - assert.Empty(t, d.HealthAddr()) + assertEqual(t, "", d.HealthAddr()) } func TestDaemon_DefaultShutdownTimeout(t *testing.T) { d := NewDaemon(DaemonOptions{}) - assert.Equal(t, 30*time.Second, d.opts.ShutdownTimeout) + assertEqual(t, 30*time.Second, d.opts.ShutdownTimeout) } func TestDaemon_RunBlocksUntilCancelled(t *testing.T) { @@ -274,7 +271,7 @@ func TestDaemon_RunBlocksUntilCancelled(t *testing.T) { }) err := d.Start() - require.NoError(t, err) + requireNoError(t, err) ctx, cancel := context.WithCancel(context.Background()) @@ -295,7 +292,7 @@ func TestDaemon_RunBlocksUntilCancelled(t *testing.T) { select { case err := <-done: - assert.NoError(t, err) + assertNoError(t, err) case <-time.After(2 * time.Second): t.Fatal("Run should return after context cancellation") } @@ -306,16 +303,16 @@ func TestDaemon_StopIdempotent(t *testing.T) { // Stop without Start should be a no-op err := d.Stop() - assert.NoError(t, err) + assertNoError(t, err) } func TestDaemon_AutoRegisters(t *testing.T) { dir := t.TempDir() reg := NewRegistry(filepath.Join(dir, "daemons")) wd, err := os.Getwd() - require.NoError(t, err) + requireNoError(t, err) exe, err := os.Executable() - require.NoError(t, err) + requireNoError(t, err) d := NewDaemon(DaemonOptions{ HealthAddr: "127.0.0.1:0", @@ -327,22 +324,22 @@ func TestDaemon_AutoRegisters(t *testing.T) { }) err = d.Start() - require.NoError(t, err) + requireNoError(t, err) // Should be registered entry, ok := reg.Get("test-app", "serve") - require.True(t, ok) - assert.Equal(t, os.Getpid(), entry.PID) - assert.NotEmpty(t, entry.Health) - assert.Equal(t, wd, entry.Project) - assert.Equal(t, exe, entry.Binary) + requireTrue(t, ok) + assertEqual(t, os.Getpid(), entry.PID) + assertNotEmpty(t, entry.Health) + assertEqual(t, wd, entry.Project) + assertEqual(t, exe, entry.Binary) // Stop should unregister err = d.Stop() - require.NoError(t, err) + requireNoError(t, err) _, ok = reg.Get("test-app", "serve") - assert.False(t, ok) + assertFalse(t, ok) } func TestDaemon_StartRollsBackOnRegistryFailure(t *testing.T) { @@ -350,8 +347,8 @@ func TestDaemon_StartRollsBackOnRegistryFailure(t *testing.T) { pidPath := filepath.Join(dir, "daemon.pid") regDir := filepath.Join(dir, "registry") - require.NoError(t, os.MkdirAll(regDir, 0o755)) - require.NoError(t, os.Chmod(regDir, 0o555)) + requireNoError(t, os.MkdirAll(regDir, 0o755)) + requireNoError(t, os.Chmod(regDir, 0o555)) d := NewDaemon(DaemonOptions{ PIDFile: pidPath, @@ -364,20 +361,20 @@ func TestDaemon_StartRollsBackOnRegistryFailure(t *testing.T) { }) err := d.Start() - require.Error(t, err) + requireError(t, err) _, statErr := os.Stat(pidPath) - assert.True(t, os.IsNotExist(statErr)) + assertTrue(t, os.IsNotExist(statErr)) addr := d.HealthAddr() - require.NotEmpty(t, addr) + requireNotEmpty(t, addr) client := &http.Client{Timeout: 250 * time.Millisecond} resp, reqErr := client.Get("http://" + addr + "/health") if resp != nil { _ = resp.Body.Close() } - assert.Error(t, reqErr) + assertError(t, reqErr) - assert.NoError(t, d.Stop()) + assertNoError(t, d.Stop()) } diff --git a/errors_test.go b/errors_test.go index 61d3f42..98bbbb8 100644 --- a/errors_test.go +++ b/errors_test.go @@ -2,14 +2,11 @@ package process import ( "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestServiceError(t *testing.T) { err := ServiceError("service failed", ErrContextRequired) - require.Error(t, err) - assert.Contains(t, err.Error(), "service failed") - assert.ErrorIs(t, err, ErrContextRequired) + requireError(t, err) + assertContains(t, err.Error(), "service failed") + assertErrorIs(t, err, ErrContextRequired) } diff --git a/exec/exec_test.go b/exec/exec_test.go index d5a498e..6d7b88b 100644 --- a/exec/exec_test.go +++ b/exec/exec_test.go @@ -2,6 +2,7 @@ package exec_test import ( "context" + "errors" "fmt" "os" "path/filepath" @@ -11,8 +12,6 @@ import ( "time" "dappco.re/go/core/process/exec" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // mockLogger captures log calls for testing @@ -159,7 +158,9 @@ func TestDefaultLogger_IsConcurrentSafe(t *testing.T) { } wg.Wait() - assert.NotNil(t, exec.DefaultLogger()) + if exec.DefaultLogger() == nil { + t.Fatal("expected non-nil default logger") + } } func TestCommand_UsesDefaultLogger(t *testing.T) { @@ -260,26 +261,42 @@ func TestCommand_Run_Background(t *testing.T) { func TestCommand_NilContextRejected(t *testing.T) { t.Run("start", func(t *testing.T) { err := exec.Command(nil, "echo", "test").Start() - require.Error(t, err) - assert.ErrorIs(t, err, exec.ErrCommandContextRequired) + if err == nil { + t.Fatal("expected error, got nil") + } + if !errors.Is(err, exec.ErrCommandContextRequired) { + t.Fatalf("expected ErrCommandContextRequired, got %v", err) + } }) t.Run("run", func(t *testing.T) { err := exec.Command(nil, "echo", "test").Run() - require.Error(t, err) - assert.ErrorIs(t, err, exec.ErrCommandContextRequired) + if err == nil { + t.Fatal("expected error, got nil") + } + if !errors.Is(err, exec.ErrCommandContextRequired) { + t.Fatalf("expected ErrCommandContextRequired, got %v", err) + } }) t.Run("output", func(t *testing.T) { _, err := exec.Command(nil, "echo", "test").Output() - require.Error(t, err) - assert.ErrorIs(t, err, exec.ErrCommandContextRequired) + if err == nil { + t.Fatal("expected error, got nil") + } + if !errors.Is(err, exec.ErrCommandContextRequired) { + t.Fatalf("expected ErrCommandContextRequired, got %v", err) + } }) t.Run("combined output", func(t *testing.T) { _, err := exec.Command(nil, "echo", "test").CombinedOutput() - require.Error(t, err) - assert.ErrorIs(t, err, exec.ErrCommandContextRequired) + if err == nil { + t.Fatal("expected error, got nil") + } + if !errors.Is(err, exec.ErrCommandContextRequired) { + t.Fatalf("expected ErrCommandContextRequired, got %v", err) + } }) } diff --git a/global_test.go b/global_test.go index f68ec92..c750e3e 100644 --- a/global_test.go +++ b/global_test.go @@ -9,8 +9,6 @@ import ( "time" framework "dappco.re/go/core" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestGlobal_DefaultNotInitialized(t *testing.T) { @@ -22,46 +20,46 @@ func TestGlobal_DefaultNotInitialized(t *testing.T) { } }() - assert.Nil(t, Default()) + assertNil(t, Default()) _, err := Start(context.Background(), "echo", "test") - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) _, err = Run(context.Background(), "echo", "test") - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) _, err = Get("proc-1") - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) _, err = Output("proc-1") - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) err = Input("proc-1", "test") - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) err = CloseStdin("proc-1") - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) - assert.Nil(t, List()) - assert.Nil(t, Running()) + assertNil(t, List()) + assertNil(t, Running()) err = Remove("proc-1") - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) // Clear is a no-op without a default service. Clear() err = Kill("proc-1") - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) err = KillPID(1234) - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) _, err = StartWithOptions(context.Background(), RunOptions{Command: "echo"}) - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) _, err = RunWithOptions(context.Background(), RunOptions{Command: "echo"}) - assert.ErrorIs(t, err, ErrServiceNotInitialized) + assertErrorIs(t, err, ErrServiceNotInitialized) } func newGlobalTestService(t *testing.T) *Service { @@ -69,7 +67,7 @@ func newGlobalTestService(t *testing.T) *Service { c := framework.New() factory := NewService(Options{}) raw, err := factory(c) - require.NoError(t, err) + requireNoError(t, err) return raw.(*Service) } @@ -85,13 +83,13 @@ func TestGlobal_SetDefault(t *testing.T) { svc := newGlobalTestService(t) err := SetDefault(svc) - require.NoError(t, err) - assert.Equal(t, svc, Default()) + requireNoError(t, err) + assertEqual(t, svc, Default()) }) t.Run("errors on nil", func(t *testing.T) { err := SetDefault(nil) - assert.Error(t, err) + assertError(t, err) }) } @@ -99,13 +97,13 @@ func TestGlobal_Register(t *testing.T) { c := framework.New() result := Register(c) - require.True(t, result.OK) + requireTrue(t, result.OK) svc, ok := result.Value.(*Service) - require.True(t, ok) - require.NotNil(t, svc) - assert.NotNil(t, svc.ServiceRuntime) - assert.Equal(t, DefaultBufferSize, svc.bufSize) + requireTrue(t, ok) + requireNotNil(t, svc) + assertNotNil(t, svc.ServiceRuntime) + assertEqual(t, DefaultBufferSize, svc.bufSize) } func TestGlobal_ConcurrentDefault(t *testing.T) { @@ -119,7 +117,7 @@ func TestGlobal_ConcurrentDefault(t *testing.T) { svc := newGlobalTestService(t) err := SetDefault(svc) - require.NoError(t, err) + requireNoError(t, err) var wg sync.WaitGroup for i := 0; i < 100; i++ { @@ -127,8 +125,8 @@ func TestGlobal_ConcurrentDefault(t *testing.T) { go func() { defer wg.Done() s := Default() - assert.NotNil(t, s) - assert.Equal(t, svc, s) + assertNotNil(t, s) + assertEqual(t, svc, s) }() } wg.Wait() @@ -159,7 +157,7 @@ func TestGlobal_ConcurrentSetDefault(t *testing.T) { wg.Wait() final := Default() - assert.NotNil(t, final) + assertNotNil(t, final) found := false for _, svc := range services { @@ -168,7 +166,7 @@ func TestGlobal_ConcurrentSetDefault(t *testing.T) { break } } - assert.True(t, found, "Default should be one of the set services") + assertTrue(t, found, "Default should be one of the set services") } func TestGlobal_ConcurrentOperations(t *testing.T) { @@ -182,7 +180,7 @@ func TestGlobal_ConcurrentOperations(t *testing.T) { svc := newGlobalTestService(t) err := SetDefault(svc) - require.NoError(t, err) + requireNoError(t, err) var wg sync.WaitGroup var processes []*Process @@ -218,7 +216,7 @@ func TestGlobal_ConcurrentOperations(t *testing.T) { } procMu.Unlock() - assert.Len(t, processes, 20) + assertLen(t, processes, 20) var wg2 sync.WaitGroup for _, p := range processes { @@ -226,8 +224,8 @@ func TestGlobal_ConcurrentOperations(t *testing.T) { go func(id string) { defer wg2.Done() got, err := Get(id) - assert.NoError(t, err) - assert.NotNil(t, got) + assertNoError(t, err) + assertNotNil(t, got) }(p.ID) } wg2.Wait() @@ -247,12 +245,12 @@ func TestGlobal_StartWithOptions(t *testing.T) { Command: "echo", Args: []string{"with", "options"}, }) - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.Equal(t, 0, proc.ExitCode) - assert.Contains(t, proc.Output(), "with options") + assertEqual(t, 0, proc.ExitCode) + assertContains(t, proc.Output(), "with options") } func TestGlobal_RunWithOptions(t *testing.T) { @@ -269,8 +267,8 @@ func TestGlobal_RunWithOptions(t *testing.T) { Command: "echo", Args: []string{"run", "options"}, }) - require.NoError(t, err) - assert.Contains(t, output, "run options") + requireNoError(t, err) + assertContains(t, output, "run options") } func TestGlobal_Output(t *testing.T) { @@ -284,12 +282,12 @@ func TestGlobal_Output(t *testing.T) { }() proc, err := Start(context.Background(), "echo", "global-output") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() output, err := Output(proc.ID) - require.NoError(t, err) - assert.Contains(t, output, "global-output") + requireNoError(t, err) + assertContains(t, output, "global-output") } func TestGlobal_InputAndCloseStdin(t *testing.T) { @@ -303,17 +301,17 @@ func TestGlobal_InputAndCloseStdin(t *testing.T) { }() proc, err := Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) err = Input(proc.ID, "global-input\n") - require.NoError(t, err) + requireNoError(t, err) err = CloseStdin(proc.ID) - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.Contains(t, proc.Output(), "global-input") + assertContains(t, proc.Output(), "global-input") } func TestGlobal_Wait(t *testing.T) { @@ -327,13 +325,13 @@ func TestGlobal_Wait(t *testing.T) { }() proc, err := Start(context.Background(), "echo", "global-wait") - require.NoError(t, err) + requireNoError(t, err) info, err := Wait(proc.ID) - require.NoError(t, err) - assert.Equal(t, proc.ID, info.ID) - assert.Equal(t, StatusExited, info.Status) - assert.Equal(t, 0, info.ExitCode) + requireNoError(t, err) + assertEqual(t, proc.ID, info.ID) + assertEqual(t, StatusExited, info.Status) + assertEqual(t, 0, info.ExitCode) } func TestGlobal_Signal(t *testing.T) { @@ -347,10 +345,10 @@ func TestGlobal_Signal(t *testing.T) { }() proc, err := Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) err = Signal(proc.ID, syscall.SIGTERM) - require.NoError(t, err) + requireNoError(t, err) select { case <-proc.Done(): @@ -370,7 +368,7 @@ func TestGlobal_SignalPID(t *testing.T) { }() cmd := exec.Command("sleep", "60") - require.NoError(t, cmd.Start()) + requireNoError(t, cmd.Start()) waitCh := make(chan error, 1) go func() { @@ -388,11 +386,11 @@ func TestGlobal_SignalPID(t *testing.T) { }) err := SignalPID(cmd.Process.Pid, syscall.SIGTERM) - require.NoError(t, err) + requireNoError(t, err) select { case err := <-waitCh: - require.Error(t, err) + requireError(t, err) case <-time.After(2 * time.Second): t.Fatal("unmanaged process should have been signalled through the global helper") } @@ -412,17 +410,17 @@ func TestGlobal_Running(t *testing.T) { defer cancel() proc, err := Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) running := Running() - assert.Len(t, running, 1) - assert.Equal(t, proc.ID, running[0].ID) + assertLen(t, running, 1) + assertEqual(t, proc.ID, running[0].ID) cancel() <-proc.Done() running = Running() - assert.Len(t, running, 0) + assertLen(t, running, 0) } func TestGlobal_RemoveAndClear(t *testing.T) { @@ -436,21 +434,21 @@ func TestGlobal_RemoveAndClear(t *testing.T) { }() proc, err := Start(context.Background(), "echo", "remove-me") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() err = Remove(proc.ID) - require.NoError(t, err) + requireNoError(t, err) _, err = Get(proc.ID) - require.ErrorIs(t, err, ErrProcessNotFound) + requireErrorIs(t, err, ErrProcessNotFound) proc2, err := Start(context.Background(), "echo", "clear-me") - require.NoError(t, err) + requireNoError(t, err) <-proc2.Done() Clear() _, err = Get(proc2.ID) - require.ErrorIs(t, err, ErrProcessNotFound) + requireErrorIs(t, err, ErrProcessNotFound) } diff --git a/go.mod b/go.mod index 8c8a9da..8452727 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( dappco.re/go/core/ws v0.4.0 github.com/gin-gonic/gin v1.12.0 github.com/gorilla/websocket v1.5.3 - github.com/stretchr/testify v1.11.1 ) require ( @@ -28,7 +27,6 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect github.com/coreos/go-oidc/v3 v3.17.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/gin-contrib/authz v1.0.6 // indirect @@ -75,7 +73,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/quic-go/qpack v0.6.0 // indirect github.com/quic-go/quic-go v0.59.0 // indirect github.com/redis/go-redis/v9 v9.18.0 // indirect diff --git a/go.sum b/go.sum index a15817f..049b75e 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,7 @@ dappco.re/go/core/io v0.2.0/go.mod h1:1QnQV6X9LNgFKfm8SkOtR9LLaj3bDcsOIeJOOyjbL5 dappco.re/go/core/log v0.1.0 h1:pa71Vq2TD2aoEUQWFKwNcaJ3GBY8HbaNGqtE688Unyc= dappco.re/go/core/log v0.1.0/go.mod h1:Nkqb8gsXhZAO8VLpx7B8i1iAmohhzqA20b9Zr8VUcJs= dappco.re/go/core/ws v0.4.0 h1:yEDV9whXyo+GWzBSjuB3NiLiH2bmBPBWD6rydwHyBn8= +dappco.re/go/core/ws v0.4.0/go.mod h1:L1rrgW6zU+DztcVBJW2yO5Lm3rGXpyUMOA8OL9zsAok= forge.lthn.ai/core/go-log v0.0.4 h1:KTuCEPgFmuM8KJfnyQ8vPOU1Jg654W74h8IJvfQMfv0= forge.lthn.ai/core/go-log v0.0.4/go.mod h1:r14MXKOD3LF/sI8XUJQhRk/SZHBE7jAFVuCfgkXoZPw= github.com/99designs/gqlgen v0.17.88 h1:neMQDgehMwT1vYIOx/w5ZYPUU/iMNAJzRO44I5Intoc= @@ -249,6 +250,7 @@ golang.org/x/arch v0.25.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= @@ -258,6 +260,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -272,6 +275,7 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -280,6 +284,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/health_test.go b/health_test.go index faf9b3b..6a2a6af 100644 --- a/health_test.go +++ b/health_test.go @@ -4,47 +4,44 @@ import ( "context" "net/http" "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestHealthServer_Endpoints(t *testing.T) { hs := NewHealthServer("127.0.0.1:0") - assert.True(t, hs.Ready()) + assertTrue(t, hs.Ready()) err := hs.Start() - require.NoError(t, err) + requireNoError(t, err) defer func() { _ = hs.Stop(context.Background()) }() addr := hs.Addr() - require.NotEmpty(t, addr) + requireNotEmpty(t, addr) resp, err := http.Get("http://" + addr + "/health") - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) + requireNoError(t, err) + assertEqual(t, http.StatusOK, resp.StatusCode) _ = resp.Body.Close() resp, err = http.Get("http://" + addr + "/ready") - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) + requireNoError(t, err) + assertEqual(t, http.StatusOK, resp.StatusCode) _ = resp.Body.Close() hs.SetReady(false) - assert.False(t, hs.Ready()) + assertFalse(t, hs.Ready()) resp, err = http.Get("http://" + addr + "/ready") - require.NoError(t, err) - assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) + requireNoError(t, err) + assertEqual(t, http.StatusServiceUnavailable, resp.StatusCode) _ = resp.Body.Close() } func TestHealthServer_Ready(t *testing.T) { hs := NewHealthServer("127.0.0.1:0") - assert.True(t, hs.Ready()) + assertTrue(t, hs.Ready()) hs.SetReady(false) - assert.False(t, hs.Ready()) + assertFalse(t, hs.Ready()) } func TestHealthServer_WithChecks(t *testing.T) { @@ -53,27 +50,27 @@ func TestHealthServer_WithChecks(t *testing.T) { healthy := true hs.AddCheck(func() error { if !healthy { - return assert.AnError + return errSentinel } return nil }) err := hs.Start() - require.NoError(t, err) + requireNoError(t, err) defer func() { _ = hs.Stop(context.Background()) }() addr := hs.Addr() resp, err := http.Get("http://" + addr + "/health") - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) + requireNoError(t, err) + assertEqual(t, http.StatusOK, resp.StatusCode) _ = resp.Body.Close() healthy = false resp, err = http.Get("http://" + addr + "/health") - require.NoError(t, err) - assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) + requireNoError(t, err) + assertEqual(t, http.StatusServiceUnavailable, resp.StatusCode) _ = resp.Body.Close() } @@ -84,14 +81,14 @@ func TestHealthServer_NilCheckIgnored(t *testing.T) { hs.AddCheck(check) err := hs.Start() - require.NoError(t, err) + requireNoError(t, err) defer func() { _ = hs.Stop(context.Background()) }() addr := hs.Addr() resp, err := http.Get("http://" + addr + "/health") - require.NoError(t, err) - assert.Equal(t, http.StatusOK, resp.StatusCode) + requireNoError(t, err) + assertEqual(t, http.StatusOK, resp.StatusCode) _ = resp.Body.Close() } @@ -100,49 +97,49 @@ func TestHealthServer_ChecksSnapshotIsStable(t *testing.T) { hs.AddCheck(func() error { return nil }) snapshot := hs.checksSnapshot() - hs.AddCheck(func() error { return assert.AnError }) + hs.AddCheck(func() error { return errSentinel }) - require.Len(t, snapshot, 1) - require.NotNil(t, snapshot[0]) + requireLen(t, snapshot, 1) + requireNotNil(t, snapshot[0]) } func TestWaitForHealth_Reachable(t *testing.T) { hs := NewHealthServer("127.0.0.1:0") - require.NoError(t, hs.Start()) + requireNoError(t, hs.Start()) defer func() { _ = hs.Stop(context.Background()) }() ok := WaitForHealth(hs.Addr(), 2_000) - assert.True(t, ok) + assertTrue(t, ok) } func TestWaitForHealth_Unreachable(t *testing.T) { ok := WaitForHealth("127.0.0.1:19999", 500) - assert.False(t, ok) + assertFalse(t, ok) } func TestWaitForReady_Reachable(t *testing.T) { hs := NewHealthServer("127.0.0.1:0") - require.NoError(t, hs.Start()) + requireNoError(t, hs.Start()) defer func() { _ = hs.Stop(context.Background()) }() ok := WaitForReady(hs.Addr(), 2_000) - assert.True(t, ok) + assertTrue(t, ok) } func TestWaitForReady_Unreachable(t *testing.T) { ok := WaitForReady("127.0.0.1:19999", 500) - assert.False(t, ok) + assertFalse(t, ok) } func TestHealthServer_StopMarksNotReady(t *testing.T) { hs := NewHealthServer("127.0.0.1:0") - require.NoError(t, hs.Start()) + requireNoError(t, hs.Start()) - require.NotEmpty(t, hs.Addr()) - assert.True(t, hs.Ready()) + requireNotEmpty(t, hs.Addr()) + assertTrue(t, hs.Ready()) - require.NoError(t, hs.Stop(context.Background())) + requireNoError(t, hs.Stop(context.Background())) - assert.False(t, hs.Ready()) - assert.NotEmpty(t, hs.Addr()) + assertFalse(t, hs.Ready()) + assertNotEmpty(t, hs.Addr()) } diff --git a/pidfile_test.go b/pidfile_test.go index a35c9cb..3bd7954 100644 --- a/pidfile_test.go +++ b/pidfile_test.go @@ -5,72 +5,70 @@ import ( "testing" "dappco.re/go/core" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestPIDFile_Acquire_Good(t *testing.T) { pidPath := core.JoinPath(t.TempDir(), "test.pid") pid := NewPIDFile(pidPath) err := pid.Acquire() - require.NoError(t, err) + requireNoError(t, err) data, err := os.ReadFile(pidPath) - require.NoError(t, err) - assert.NotEmpty(t, data) + requireNoError(t, err) + assertNotEmpty(t, data) err = pid.Release() - require.NoError(t, err) + requireNoError(t, err) _, err = os.Stat(pidPath) - assert.True(t, os.IsNotExist(err)) + assertTrue(t, os.IsNotExist(err)) } func TestPIDFile_AcquireStale_Good(t *testing.T) { pidPath := core.JoinPath(t.TempDir(), "stale.pid") - require.NoError(t, os.WriteFile(pidPath, []byte("999999999"), 0644)) + requireNoError(t, os.WriteFile(pidPath, []byte("999999999"), 0644)) pid := NewPIDFile(pidPath) err := pid.Acquire() - require.NoError(t, err) + requireNoError(t, err) err = pid.Release() - require.NoError(t, err) + requireNoError(t, err) } func TestPIDFile_CreateDirectory_Good(t *testing.T) { pidPath := core.JoinPath(t.TempDir(), "subdir", "nested", "test.pid") pid := NewPIDFile(pidPath) err := pid.Acquire() - require.NoError(t, err) + requireNoError(t, err) err = pid.Release() - require.NoError(t, err) + requireNoError(t, err) } func TestPIDFile_Path_Good(t *testing.T) { pid := NewPIDFile("/tmp/test.pid") - assert.Equal(t, "/tmp/test.pid", pid.Path()) + assertEqual(t, "/tmp/test.pid", pid.Path()) } func TestPIDFile_Release_MissingIsNoop(t *testing.T) { pidPath := core.JoinPath(t.TempDir(), "absent.pid") pid := NewPIDFile(pidPath) - require.NoError(t, pid.Release()) + requireNoError(t, pid.Release()) } func TestReadPID_Missing_Bad(t *testing.T) { pid, running := ReadPID("/nonexistent/path.pid") - assert.Equal(t, 0, pid) - assert.False(t, running) + assertEqual(t, 0, pid) + assertFalse(t, running) } func TestReadPID_Invalid_Bad(t *testing.T) { path := core.JoinPath(t.TempDir(), "bad.pid") - require.NoError(t, os.WriteFile(path, []byte("notanumber"), 0644)) + requireNoError(t, os.WriteFile(path, []byte("notanumber"), 0644)) pid, running := ReadPID(path) - assert.Equal(t, 0, pid) - assert.False(t, running) + assertEqual(t, 0, pid) + assertFalse(t, running) } func TestReadPID_Stale_Bad(t *testing.T) { path := core.JoinPath(t.TempDir(), "stale.pid") - require.NoError(t, os.WriteFile(path, []byte("999999999"), 0644)) + requireNoError(t, os.WriteFile(path, []byte("999999999"), 0644)) pid, running := ReadPID(path) - assert.Equal(t, 999999999, pid) - assert.False(t, running) + assertEqual(t, 999999999, pid) + assertFalse(t, running) } diff --git a/pkg/api/provider_test.go b/pkg/api/provider_test.go index b67934d..952e015 100644 --- a/pkg/api/provider_test.go +++ b/pkg/api/provider_test.go @@ -21,8 +21,6 @@ import ( corews "dappco.re/go/core/ws" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func init() { @@ -31,33 +29,33 @@ func init() { func TestProcessProvider_Name_Good(t *testing.T) { p := processapi.NewProvider(nil, nil, nil) - assert.Equal(t, "process", p.Name()) + assertEqual(t, "process", p.Name()) } func TestProcessProvider_BasePath_Good(t *testing.T) { p := processapi.NewProvider(nil, nil, nil) - assert.Equal(t, "/api/process", p.BasePath()) + assertEqual(t, "/api/process", p.BasePath()) } func TestProcessProvider_Channels_Good(t *testing.T) { p := processapi.NewProvider(nil, nil, nil) channels := p.Channels() - assert.Contains(t, channels, "process.daemon.started") - assert.Contains(t, channels, "process.daemon.stopped") - assert.Contains(t, channels, "process.daemon.health") + assertContains(t, channels, "process.daemon.started") + assertContains(t, channels, "process.daemon.stopped") + assertContains(t, channels, "process.daemon.health") } func TestProcessProvider_Describe_Good(t *testing.T) { p := processapi.NewProvider(nil, nil, nil) descs := p.Describe() - assert.GreaterOrEqual(t, len(descs), 5) + assertGreaterOrEqual(t, len(descs), 5) // Verify all descriptions have required fields for _, d := range descs { - assert.NotEmpty(t, d.Method) - assert.NotEmpty(t, d.Path) - assert.NotEmpty(t, d.Summary) - assert.NotEmpty(t, d.Tags) + assertNotEmpty(t, d.Method) + assertNotEmpty(t, d.Path) + assertNotEmpty(t, d.Summary) + assertNotEmpty(t, d.Tags) } foundPipelineRoute := false @@ -70,8 +68,8 @@ func TestProcessProvider_Describe_Good(t *testing.T) { foundSignalRoute = true } } - assert.True(t, foundPipelineRoute, "pipeline route should be described") - assert.True(t, foundSignalRoute, "signal route should be described") + assertTrue(t, foundPipelineRoute, "pipeline route should be described") + assertTrue(t, foundSignalRoute, "signal route should be described") } func TestProcessProvider_ListDaemons_Good(t *testing.T) { @@ -85,18 +83,18 @@ func TestProcessProvider_ListDaemons_Good(t *testing.T) { req, _ := http.NewRequest("GET", "/api/process/daemons", nil) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[[]any] err := json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - assert.True(t, resp.Success) + requireNoError(t, err) + assertTrue(t, resp.Success) } func TestProcessProvider_ListDaemons_BroadcastsStarted_Good(t *testing.T) { dir := t.TempDir() registry := newTestRegistry(dir) - require.NoError(t, registry.Register(process.DaemonEntry{ + requireNoError(t, registry.Register(process.DaemonEntry{ Code: "test", Daemon: "serve", PID: os.Getpid(), @@ -114,7 +112,7 @@ func TestProcessProvider_ListDaemons_BroadcastsStarted_Good(t *testing.T) { conn := connectWS(t, server.URL) defer conn.Close() - require.Eventually(t, func() bool { + requireEventually(t, func() bool { return hub.ClientCount() == 1 }, time.Second, 10*time.Millisecond) @@ -123,16 +121,16 @@ func TestProcessProvider_ListDaemons_BroadcastsStarted_Good(t *testing.T) { req, _ := http.NewRequest("GET", "/api/process/daemons", nil) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) events := readWSEvents(t, conn, "process.daemon.started") started := events["process.daemon.started"] - require.NotNil(t, started) + requireNotNil(t, started) startedData := started.Data.(map[string]any) - assert.Equal(t, "test", startedData["code"]) - assert.Equal(t, "serve", startedData["daemon"]) - assert.Equal(t, float64(os.Getpid()), startedData["pid"]) + assertEqual(t, "test", startedData["code"]) + assertEqual(t, "serve", startedData["daemon"]) + assertEqual(t, float64(os.Getpid()), startedData["pid"]) } func TestProcessProvider_GetDaemon_Bad(t *testing.T) { @@ -145,7 +143,7 @@ func TestProcessProvider_GetDaemon_Bad(t *testing.T) { req, _ := http.NewRequest("GET", "/api/process/daemons/test/nonexistent", nil) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusNotFound, w.Code) + assertEqual(t, http.StatusNotFound, w.Code) } func TestProcessProvider_HealthCheck_Bad(t *testing.T) { @@ -159,7 +157,7 @@ func TestProcessProvider_HealthCheck_Bad(t *testing.T) { defer healthSrv.Close() hostPort := strings.TrimPrefix(healthSrv.URL, "http://") - require.NoError(t, registry.Register(process.DaemonEntry{ + requireNoError(t, registry.Register(process.DaemonEntry{ Code: "test", Daemon: "broken", PID: os.Getpid(), @@ -173,40 +171,40 @@ func TestProcessProvider_HealthCheck_Bad(t *testing.T) { req, _ := http.NewRequest("GET", "/api/process/daemons/test/broken/health", nil) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusServiceUnavailable, w.Code) + assertEqual(t, http.StatusServiceUnavailable, w.Code) var resp goapi.Response[map[string]any] err := json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) + requireNoError(t, err) + requireTrue(t, resp.Success) - assert.Equal(t, false, resp.Data["healthy"]) - assert.Equal(t, hostPort, resp.Data["address"]) - assert.Equal(t, "upstream health check failed", resp.Data["reason"]) + assertEqual(t, false, resp.Data["healthy"]) + assertEqual(t, hostPort, resp.Data["address"]) + assertEqual(t, "upstream health check failed", resp.Data["reason"]) } func TestProcessProvider_RegistersAsRouteGroup_Good(t *testing.T) { p := processapi.NewProvider(nil, nil, nil) engine, err := goapi.New() - require.NoError(t, err) + requireNoError(t, err) engine.Register(p) - assert.Len(t, engine.Groups(), 1) - assert.Equal(t, "process", engine.Groups()[0].Name()) + assertLen(t, engine.Groups(), 1) + assertEqual(t, "process", engine.Groups()[0].Name()) } func TestProcessProvider_Channels_RegisterAsStreamGroup_Good(t *testing.T) { p := processapi.NewProvider(nil, nil, nil) engine, err := goapi.New() - require.NoError(t, err) + requireNoError(t, err) engine.Register(p) // Engine.Channels() discovers StreamGroups channels := engine.Channels() - assert.Contains(t, channels, "process.daemon.started") + assertContains(t, channels, "process.daemon.started") } func TestProcessProvider_RunPipeline_Good(t *testing.T) { @@ -224,19 +222,19 @@ func TestProcessProvider_RunPipeline_Good(t *testing.T) { ] }`) req, err := http.NewRequest("POST", "/api/process/pipelines/run", body) - require.NoError(t, err) + requireNoError(t, err) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[process.RunAllResult] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - assert.True(t, resp.Success) - assert.Equal(t, 2, resp.Data.Passed) - assert.Len(t, resp.Data.Results, 2) + requireNoError(t, err) + assertTrue(t, resp.Success) + assertEqual(t, 2, resp.Data.Passed) + assertLen(t, resp.Data.Results, 2) } func TestProcessProvider_RunPipeline_Unavailable(t *testing.T) { @@ -246,18 +244,18 @@ func TestProcessProvider_RunPipeline_Unavailable(t *testing.T) { w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/pipelines/run", strings.NewReader(`{"mode":"all","specs":[]}`)) - require.NoError(t, err) + requireNoError(t, err) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) - assert.Equal(t, http.StatusServiceUnavailable, w.Code) + assertEqual(t, http.StatusServiceUnavailable, w.Code) } func TestProcessProvider_ListProcesses_Good(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "echo", "hello-api") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() p := processapi.NewProvider(nil, svc, nil) @@ -265,28 +263,28 @@ func TestProcessProvider_ListProcesses_Good(t *testing.T) { w := httptest.NewRecorder() req, err := http.NewRequest("GET", "/api/process/processes", nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[[]process.Info] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - require.Len(t, resp.Data, 1) - assert.Equal(t, proc.ID, resp.Data[0].ID) - assert.Equal(t, "echo", resp.Data[0].Command) + requireNoError(t, err) + requireTrue(t, resp.Success) + requireLen(t, resp.Data, 1) + assertEqual(t, proc.ID, resp.Data[0].ID) + assertEqual(t, "echo", resp.Data[0].Command) } func TestProcessProvider_ListProcesses_RunningOnly_Good(t *testing.T) { svc := newTestProcessService(t) runningProc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) exitedProc, err := svc.Start(context.Background(), "echo", "done") - require.NoError(t, err) + requireNoError(t, err) <-exitedProc.Done() p := processapi.NewProvider(nil, svc, nil) @@ -294,20 +292,20 @@ func TestProcessProvider_ListProcesses_RunningOnly_Good(t *testing.T) { w := httptest.NewRecorder() req, err := http.NewRequest("GET", "/api/process/processes?runningOnly=true", nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[[]process.Info] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - require.Len(t, resp.Data, 1) - assert.Equal(t, runningProc.ID, resp.Data[0].ID) - assert.Equal(t, process.StatusRunning, resp.Data[0].Status) + requireNoError(t, err) + requireTrue(t, resp.Success) + requireLen(t, resp.Data, 1) + assertEqual(t, runningProc.ID, resp.Data[0].ID) + assertEqual(t, process.StatusRunning, resp.Data[0].Status) - require.NoError(t, svc.Kill(runningProc.ID)) + requireNoError(t, svc.Kill(runningProc.ID)) <-runningProc.Done() } @@ -323,26 +321,26 @@ func TestProcessProvider_StartProcess_Good(t *testing.T) { "killGroup": true }`) req, err := http.NewRequest("POST", "/api/process/processes", body) - require.NoError(t, err) + requireNoError(t, err) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[process.Info] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Equal(t, "sleep", resp.Data.Command) - assert.Equal(t, process.StatusRunning, resp.Data.Status) - assert.True(t, resp.Data.Running) - assert.NotEmpty(t, resp.Data.ID) + requireNoError(t, err) + requireTrue(t, resp.Success) + assertEqual(t, "sleep", resp.Data.Command) + assertEqual(t, process.StatusRunning, resp.Data.Status) + assertTrue(t, resp.Data.Running) + assertNotEmpty(t, resp.Data.ID) managed, err := svc.Get(resp.Data.ID) - require.NoError(t, err) - require.NoError(t, svc.Kill(managed.ID)) + requireNoError(t, err) + requireNoError(t, svc.Kill(managed.ID)) select { case <-managed.Done(): case <-time.After(5 * time.Second): @@ -360,25 +358,25 @@ func TestProcessProvider_RunProcess_Good(t *testing.T) { "args": ["run-check"] }`) req, err := http.NewRequest("POST", "/api/process/processes/run", body) - require.NoError(t, err) + requireNoError(t, err) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[string] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Contains(t, resp.Data, "run-check") + requireNoError(t, err) + requireTrue(t, resp.Success) + assertContains(t, resp.Data, "run-check") } func TestProcessProvider_GetProcess_Good(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "echo", "single") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() p := processapi.NewProvider(nil, svc, nil) @@ -386,23 +384,23 @@ func TestProcessProvider_GetProcess_Good(t *testing.T) { w := httptest.NewRecorder() req, err := http.NewRequest("GET", "/api/process/processes/"+proc.ID, nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[process.Info] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Equal(t, proc.ID, resp.Data.ID) - assert.Equal(t, "echo", resp.Data.Command) + requireNoError(t, err) + requireTrue(t, resp.Success) + assertEqual(t, proc.ID, resp.Data.ID) + assertEqual(t, "echo", resp.Data.Command) } func TestProcessProvider_GetProcessOutput_Good(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "echo", "output-check") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() p := processapi.NewProvider(nil, svc, nil) @@ -410,97 +408,97 @@ func TestProcessProvider_GetProcessOutput_Good(t *testing.T) { w := httptest.NewRecorder() req, err := http.NewRequest("GET", "/api/process/processes/"+proc.ID+"/output", nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[string] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Contains(t, resp.Data, "output-check") + requireNoError(t, err) + requireTrue(t, resp.Success) + assertContains(t, resp.Data, "output-check") } func TestProcessProvider_WaitProcess_Good(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "echo", "wait-check") - require.NoError(t, err) + requireNoError(t, err) p := processapi.NewProvider(nil, svc, nil) r := setupRouter(p) w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/processes/"+proc.ID+"/wait", nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[process.Info] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Equal(t, proc.ID, resp.Data.ID) - assert.Equal(t, process.StatusExited, resp.Data.Status) - assert.Equal(t, 0, resp.Data.ExitCode) + requireNoError(t, err) + requireTrue(t, resp.Success) + assertEqual(t, proc.ID, resp.Data.ID) + assertEqual(t, process.StatusExited, resp.Data.Status) + assertEqual(t, 0, resp.Data.ExitCode) } func TestProcessProvider_WaitProcess_NonZeroExit_Good(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "sh", "-c", "exit 7") - require.NoError(t, err) + requireNoError(t, err) p := processapi.NewProvider(nil, svc, nil) r := setupRouter(p) w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/processes/"+proc.ID+"/wait", nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusConflict, w.Code) + assertEqual(t, http.StatusConflict, w.Code) var resp goapi.Response[any] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.False(t, resp.Success) - require.NotNil(t, resp.Error) - assert.Equal(t, "wait_failed", resp.Error.Code) - assert.Contains(t, resp.Error.Message, "process exited with code 7") + requireNoError(t, err) + requireFalse(t, resp.Success) + requireNotNil(t, resp.Error) + assertEqual(t, "wait_failed", resp.Error.Code) + assertContains(t, resp.Error.Message, "process exited with code 7") details, ok := resp.Error.Details.(map[string]any) - require.True(t, ok) - assert.Equal(t, "exited", details["status"]) - assert.Equal(t, float64(7), details["exitCode"]) - assert.Equal(t, proc.ID, details["id"]) + requireTrue(t, ok) + assertEqual(t, "exited", details["status"]) + assertEqual(t, float64(7), details["exitCode"]) + assertEqual(t, proc.ID, details["id"]) } func TestProcessProvider_InputAndCloseStdin_Good(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) p := processapi.NewProvider(nil, svc, nil) r := setupRouter(p) inputReq := strings.NewReader("{\"input\":\"hello-api\\n\"}") inputHTTPReq, err := http.NewRequest("POST", "/api/process/processes/"+proc.ID+"/input", inputReq) - require.NoError(t, err) + requireNoError(t, err) inputHTTPReq.Header.Set("Content-Type", "application/json") inputResp := httptest.NewRecorder() r.ServeHTTP(inputResp, inputHTTPReq) - assert.Equal(t, http.StatusOK, inputResp.Code) + assertEqual(t, http.StatusOK, inputResp.Code) closeReq, err := http.NewRequest("POST", "/api/process/processes/"+proc.ID+"/close-stdin", nil) - require.NoError(t, err) + requireNoError(t, err) closeResp := httptest.NewRecorder() r.ServeHTTP(closeResp, closeReq) - assert.Equal(t, http.StatusOK, closeResp.Code) + assertEqual(t, http.StatusOK, closeResp.Code) select { case <-proc.Done(): @@ -508,36 +506,36 @@ func TestProcessProvider_InputAndCloseStdin_Good(t *testing.T) { t.Fatal("process should have exited after stdin was closed") } - assert.Contains(t, proc.Output(), "hello-api") + assertContains(t, proc.Output(), "hello-api") } func TestProcessProvider_KillProcess_Good(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) p := processapi.NewProvider(nil, svc, nil) r := setupRouter(p) w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/processes/"+proc.ID+"/kill", nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[map[string]any] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Equal(t, true, resp.Data["killed"]) + requireNoError(t, err) + requireTrue(t, resp.Success) + assertEqual(t, true, resp.Data["killed"]) select { case <-proc.Done(): case <-time.After(5 * time.Second): t.Fatal("process should have been killed") } - assert.Equal(t, process.StatusKilled, proc.Status) + assertEqual(t, process.StatusKilled, proc.Status) } func TestProcessProvider_KillProcess_ByPID_Good(t *testing.T) { @@ -546,7 +544,7 @@ func TestProcessProvider_KillProcess_ByPID_Good(t *testing.T) { r := setupRouter(p) cmd := exec.Command("sleep", "60") - require.NoError(t, cmd.Start()) + requireNoError(t, cmd.Start()) waitCh := make(chan error, 1) go func() { @@ -565,20 +563,20 @@ func TestProcessProvider_KillProcess_ByPID_Good(t *testing.T) { w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/processes/"+strconv.Itoa(cmd.Process.Pid)+"/kill", nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[map[string]any] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Equal(t, true, resp.Data["killed"]) + requireNoError(t, err) + requireTrue(t, resp.Success) + assertEqual(t, true, resp.Data["killed"]) select { case err := <-waitCh: - require.Error(t, err) + requireError(t, err) case <-time.After(5 * time.Second): t.Fatal("unmanaged process should have been killed by PID") } @@ -587,31 +585,31 @@ func TestProcessProvider_KillProcess_ByPID_Good(t *testing.T) { func TestProcessProvider_SignalProcess_Good(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) p := processapi.NewProvider(nil, svc, nil) r := setupRouter(p) w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/processes/"+proc.ID+"/signal", strings.NewReader(`{"signal":"SIGTERM"}`)) - require.NoError(t, err) + requireNoError(t, err) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[map[string]any] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Equal(t, true, resp.Data["signalled"]) + requireNoError(t, err) + requireTrue(t, resp.Success) + assertEqual(t, true, resp.Data["signalled"]) select { case <-proc.Done(): case <-time.After(5 * time.Second): t.Fatal("process should have been signalled") } - assert.Equal(t, process.StatusKilled, proc.Status) + assertEqual(t, process.StatusKilled, proc.Status) } func TestProcessProvider_SignalProcess_ByPID_Good(t *testing.T) { @@ -620,7 +618,7 @@ func TestProcessProvider_SignalProcess_ByPID_Good(t *testing.T) { r := setupRouter(p) cmd := exec.Command("sleep", "60") - require.NoError(t, cmd.Start()) + requireNoError(t, cmd.Start()) waitCh := make(chan error, 1) go func() { @@ -639,21 +637,21 @@ func TestProcessProvider_SignalProcess_ByPID_Good(t *testing.T) { w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/processes/"+strconv.Itoa(cmd.Process.Pid)+"/signal", strings.NewReader(`{"signal":"SIGTERM"}`)) - require.NoError(t, err) + requireNoError(t, err) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[map[string]any] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - require.True(t, resp.Success) - assert.Equal(t, true, resp.Data["signalled"]) + requireNoError(t, err) + requireTrue(t, resp.Success) + assertEqual(t, true, resp.Data["signalled"]) select { case err := <-waitCh: - require.Error(t, err) + requireError(t, err) case <-time.After(5 * time.Second): t.Fatal("unmanaged process should have been signalled by PID") } @@ -662,21 +660,21 @@ func TestProcessProvider_SignalProcess_ByPID_Good(t *testing.T) { func TestProcessProvider_SignalProcess_InvalidSignal_Bad(t *testing.T) { svc := newTestProcessService(t) proc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) p := processapi.NewProvider(nil, svc, nil) r := setupRouter(p) w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/processes/"+proc.ID+"/signal", strings.NewReader(`{"signal":"NOPE"}`)) - require.NoError(t, err) + requireNoError(t, err) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) - assert.Equal(t, http.StatusBadRequest, w.Code) - assert.True(t, proc.IsRunning()) + assertEqual(t, http.StatusBadRequest, w.Code) + assertTrue(t, proc.IsRunning()) - require.NoError(t, svc.Kill(proc.ID)) + requireNoError(t, svc.Kill(proc.ID)) <-proc.Done() } @@ -695,35 +693,35 @@ func TestProcessProvider_BroadcastsProcessEvents_Good(t *testing.T) { conn := connectWS(t, server.URL) defer conn.Close() - require.Eventually(t, func() bool { + requireEventually(t, func() bool { return hub.ClientCount() == 1 }, time.Second, 10*time.Millisecond) proc, err := svc.Start(context.Background(), "sh", "-c", "echo live-event") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() events := readWSEvents(t, conn, "process.started", "process.output", "process.exited") started := events["process.started"] - require.NotNil(t, started) + requireNotNil(t, started) startedData := started.Data.(map[string]any) - assert.Equal(t, proc.ID, startedData["id"]) - assert.Equal(t, "sh", startedData["command"]) - assert.Equal(t, float64(proc.Info().PID), startedData["pid"]) + assertEqual(t, proc.ID, startedData["id"]) + assertEqual(t, "sh", startedData["command"]) + assertEqual(t, float64(proc.Info().PID), startedData["pid"]) output := events["process.output"] - require.NotNil(t, output) + requireNotNil(t, output) outputData := output.Data.(map[string]any) - assert.Equal(t, proc.ID, outputData["id"]) - assert.Equal(t, "stdout", outputData["stream"]) - assert.Contains(t, outputData["line"], "live-event") + assertEqual(t, proc.ID, outputData["id"]) + assertEqual(t, "stdout", outputData["stream"]) + assertContains(t, outputData["line"], "live-event") exited := events["process.exited"] - require.NotNil(t, exited) + requireNotNil(t, exited) exitedData := exited.Data.(map[string]any) - assert.Equal(t, proc.ID, exitedData["id"]) - assert.Equal(t, float64(0), exitedData["exitCode"]) + assertEqual(t, proc.ID, exitedData["id"]) + assertEqual(t, float64(0), exitedData["exitCode"]) } func TestProcessProvider_BroadcastsKilledEvents_Good(t *testing.T) { @@ -741,14 +739,14 @@ func TestProcessProvider_BroadcastsKilledEvents_Good(t *testing.T) { conn := connectWS(t, server.URL) defer conn.Close() - require.Eventually(t, func() bool { + requireEventually(t, func() bool { return hub.ClientCount() == 1 }, time.Second, 10*time.Millisecond) proc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) - require.NoError(t, svc.Kill(proc.ID)) + requireNoError(t, svc.Kill(proc.ID)) select { case <-proc.Done(): @@ -759,17 +757,17 @@ func TestProcessProvider_BroadcastsKilledEvents_Good(t *testing.T) { events := readWSEvents(t, conn, "process.killed", "process.exited") killed := events["process.killed"] - require.NotNil(t, killed) + requireNotNil(t, killed) killedData := killed.Data.(map[string]any) - assert.Equal(t, proc.ID, killedData["id"]) - assert.Equal(t, "SIGKILL", killedData["signal"]) - assert.Equal(t, float64(-1), killedData["exitCode"]) + assertEqual(t, proc.ID, killedData["id"]) + assertEqual(t, "SIGKILL", killedData["signal"]) + assertEqual(t, float64(-1), killedData["exitCode"]) exited := events["process.exited"] - require.NotNil(t, exited) + requireNotNil(t, exited) exitedData := exited.Data.(map[string]any) - assert.Equal(t, proc.ID, exitedData["id"]) - assert.Equal(t, float64(-1), exitedData["exitCode"]) + assertEqual(t, proc.ID, exitedData["id"]) + assertEqual(t, float64(-1), exitedData["exitCode"]) } func TestProcessProvider_ProcessRoutes_Unavailable(t *testing.T) { @@ -797,9 +795,9 @@ func TestProcessProvider_ProcessRoutes_Unavailable(t *testing.T) { method = "POST" } req, err := http.NewRequest(method, path, nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusServiceUnavailable, w.Code) + assertEqual(t, http.StatusServiceUnavailable, w.Code) } } @@ -809,23 +807,23 @@ func TestProcessProvider_RFCListAlias_Good(t *testing.T) { r := setupRouter(p) proc, err := svc.Start(context.Background(), "sleep", "0.1") - require.NoError(t, err) + requireNoError(t, err) t.Cleanup(func() { _ = svc.Kill(proc.ID) }) w := httptest.NewRecorder() req, err := http.NewRequest("GET", "/api/process/process/list?runningOnly=true", nil) - require.NoError(t, err) + requireNoError(t, err) r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[[]string] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - assert.True(t, resp.Success) - assert.Contains(t, resp.Data, proc.ID) + requireNoError(t, err) + assertTrue(t, resp.Success) + assertContains(t, resp.Data, proc.ID) } func TestProcessProvider_RFCStartAlias_Good(t *testing.T) { @@ -836,20 +834,20 @@ func TestProcessProvider_RFCStartAlias_Good(t *testing.T) { body := strings.NewReader(`{"command":"sleep","args":["0.1"]}`) w := httptest.NewRecorder() req, err := http.NewRequest("POST", "/api/process/process/start", body) - require.NoError(t, err) + requireNoError(t, err) req.Header.Set("Content-Type", "application/json") r.ServeHTTP(w, req) - assert.Equal(t, http.StatusOK, w.Code) + assertEqual(t, http.StatusOK, w.Code) var resp goapi.Response[string] err = json.Unmarshal(w.Body.Bytes(), &resp) - require.NoError(t, err) - assert.True(t, resp.Success) - assert.NotEmpty(t, resp.Data) + requireNoError(t, err) + assertTrue(t, resp.Success) + assertNotEmpty(t, resp.Data) proc, err := svc.Get(resp.Data) - require.NoError(t, err) + requireNoError(t, err) select { case <-proc.Done(): @@ -857,8 +855,8 @@ func TestProcessProvider_RFCStartAlias_Good(t *testing.T) { t.Fatal("RFC alias start should detach from the HTTP request context") } - assert.Equal(t, process.StatusExited, proc.Status) - assert.Equal(t, 0, proc.ExitCode) + assertEqual(t, process.StatusExited, proc.Status) + assertEqual(t, 0, proc.ExitCode) } // -- Test helpers ------------------------------------------------------------- @@ -880,7 +878,7 @@ func newTestProcessService(t *testing.T) *process.Service { c := core.New() factory := process.NewService(process.Options{}) raw, err := factory(c) - require.NoError(t, err) + requireNoError(t, err) return raw.(*process.Service) } @@ -890,7 +888,7 @@ func connectWS(t *testing.T, serverURL string) *websocket.Conn { wsURL := "ws" + strings.TrimPrefix(serverURL, "http") conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil) - require.NoError(t, err) + requireNoError(t, err) return conn } @@ -906,10 +904,10 @@ func readWSEvents(t *testing.T, conn *websocket.Conn, channels ...string) map[st deadline := time.Now().Add(3 * time.Second) for len(events) < len(channels) && time.Now().Before(deadline) { - require.NoError(t, conn.SetReadDeadline(time.Now().Add(500*time.Millisecond))) + requireNoError(t, conn.SetReadDeadline(time.Now().Add(500*time.Millisecond))) _, payload, err := conn.ReadMessage() - require.NoError(t, err) + requireNoError(t, err) for _, line := range strings.Split(strings.TrimSpace(string(payload)), "\n") { if strings.TrimSpace(line) == "" { @@ -917,7 +915,7 @@ func readWSEvents(t *testing.T, conn *websocket.Conn, channels ...string) map[st } var msg corews.Message - require.NoError(t, json.Unmarshal([]byte(line), &msg)) + requireNoError(t, json.Unmarshal([]byte(line), &msg)) if _, ok := want[msg.Channel]; ok { events[msg.Channel] = msg @@ -925,6 +923,6 @@ func readWSEvents(t *testing.T, conn *websocket.Conn, channels ...string) map[st } } - require.Len(t, events, len(channels)) + requireLen(t, events, len(channels)) return events } diff --git a/process_test.go b/process_test.go index 596bc31..790a0d9 100644 --- a/process_test.go +++ b/process_test.go @@ -6,9 +6,6 @@ import ( "syscall" "testing" "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) var _ *Process = (*ManagedProcess)(nil) @@ -17,18 +14,18 @@ func TestProcess_Info(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "hello") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() info := proc.Info() - assert.Equal(t, proc.ID, info.ID) - assert.Equal(t, "echo", info.Command) - assert.Equal(t, []string{"hello"}, info.Args) - assert.False(t, info.Running) - assert.Equal(t, StatusExited, info.Status) - assert.Equal(t, 0, info.ExitCode) - assert.Greater(t, info.Duration, time.Duration(0)) + assertEqual(t, proc.ID, info.ID) + assertEqual(t, "echo", info.Command) + assertEqual(t, []string{"hello"}, info.Args) + assertFalse(t, info.Running) + assertEqual(t, StatusExited, info.Status) + assertEqual(t, 0, info.ExitCode) + assertGreater(t, info.Duration, time.Duration(0)) } func TestProcess_Info_Pending(t *testing.T) { @@ -39,8 +36,8 @@ func TestProcess_Info_Pending(t *testing.T) { } info := proc.Info() - assert.Equal(t, StatusPending, info.Status) - assert.False(t, info.Running) + assertEqual(t, StatusPending, info.Status) + assertFalse(t, info.Running) } func TestProcess_Info_RunningDuration(t *testing.T) { @@ -50,13 +47,13 @@ func TestProcess_Info_RunningDuration(t *testing.T) { defer cancel() proc, err := svc.Start(ctx, "sleep", "10") - require.NoError(t, err) + requireNoError(t, err) time.Sleep(10 * time.Millisecond) info := proc.Info() - assert.True(t, info.Running) - assert.Equal(t, StatusRunning, info.Status) - assert.Greater(t, info.Duration, time.Duration(0)) + assertTrue(t, info.Running) + assertEqual(t, StatusRunning, info.Status) + assertGreater(t, info.Duration, time.Duration(0)) cancel() <-proc.Done() @@ -66,17 +63,17 @@ func TestProcess_InfoSnapshot(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "snapshot") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() info := proc.Info() - require.NotEmpty(t, info.Args) + requireNotEmpty(t, info.Args) info.Args[0] = "mutated" - assert.Equal(t, "snapshot", proc.Args[0]) - assert.Equal(t, "mutated", info.Args[0]) + assertEqual(t, "snapshot", proc.Args[0]) + assertEqual(t, "mutated", info.Args[0]) } func TestProcess_Output(t *testing.T) { @@ -84,25 +81,25 @@ func TestProcess_Output(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "hello world") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() output := proc.Output() - assert.Contains(t, output, "hello world") + assertContains(t, output, "hello world") }) t.Run("OutputBytes returns copy", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "test") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() bytes := proc.OutputBytes() - assert.NotNil(t, bytes) - assert.Contains(t, string(bytes), "test") + assertNotNil(t, bytes) + assertContains(t, string(bytes), "test") }) } @@ -114,27 +111,27 @@ func TestProcess_IsRunning(t *testing.T) { defer cancel() proc, err := svc.Start(ctx, "sleep", "10") - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, proc.IsRunning()) - assert.True(t, proc.Info().Running) + assertTrue(t, proc.IsRunning()) + assertTrue(t, proc.Info().Running) cancel() <-proc.Done() - assert.False(t, proc.IsRunning()) - assert.False(t, proc.Info().Running) + assertFalse(t, proc.IsRunning()) + assertFalse(t, proc.Info().Running) }) t.Run("false after completion", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "done") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.False(t, proc.IsRunning()) + assertFalse(t, proc.IsRunning()) }) } @@ -143,20 +140,20 @@ func TestProcess_Wait(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "ok") - require.NoError(t, err) + requireNoError(t, err) err = proc.Wait() - assert.NoError(t, err) + assertNoError(t, err) }) t.Run("returns error on failure", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "sh", "-c", "exit 1") - require.NoError(t, err) + requireNoError(t, err) err = proc.Wait() - assert.Error(t, err) + assertError(t, err) }) } @@ -165,7 +162,7 @@ func TestProcess_Done(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "test") - require.NoError(t, err) + requireNoError(t, err) select { case <-proc.Done(): @@ -184,12 +181,12 @@ func TestProcess_Kill(t *testing.T) { defer cancel() proc, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, proc.IsRunning()) + assertTrue(t, proc.IsRunning()) err = proc.Kill() - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -198,19 +195,19 @@ func TestProcess_Kill(t *testing.T) { t.Fatal("process should have been killed") } - assert.Equal(t, StatusKilled, proc.Status) + assertEqual(t, StatusKilled, proc.Status) }) t.Run("noop on completed process", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "done") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() err = proc.Kill() - assert.NoError(t, err) + assertNoError(t, err) }) } @@ -220,29 +217,29 @@ func TestProcess_SendInput(t *testing.T) { // Use cat to echo back stdin proc, err := svc.Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) err = proc.SendInput("hello\n") - assert.NoError(t, err) + assertNoError(t, err) err = proc.CloseStdin() - assert.NoError(t, err) + assertNoError(t, err) <-proc.Done() - assert.Contains(t, proc.Output(), "hello") + assertContains(t, proc.Output(), "hello") }) t.Run("error on completed process", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "done") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() err = proc.SendInput("test") - assert.ErrorIs(t, err, ErrProcessNotRunning) + assertErrorIs(t, err, ErrProcessNotRunning) }) } @@ -254,10 +251,10 @@ func TestProcess_Signal(t *testing.T) { defer cancel() proc, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) err = proc.Signal(os.Interrupt) - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -266,18 +263,18 @@ func TestProcess_Signal(t *testing.T) { t.Fatal("process should have been terminated by signal") } - assert.Equal(t, StatusKilled, proc.Status) + assertEqual(t, StatusKilled, proc.Status) }) t.Run("error on completed process", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "done") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() err = proc.Signal(os.Interrupt) - assert.ErrorIs(t, err, ErrProcessNotRunning) + assertErrorIs(t, err, ErrProcessNotRunning) }) t.Run("signals process group when kill group is enabled", func(t *testing.T) { @@ -289,10 +286,10 @@ func TestProcess_Signal(t *testing.T) { Detach: true, KillGroup: true, }) - require.NoError(t, err) + requireNoError(t, err) err = proc.Signal(os.Interrupt) - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -311,16 +308,16 @@ func TestProcess_Signal(t *testing.T) { Detach: true, KillGroup: true, }) - require.NoError(t, err) + requireNoError(t, err) err = proc.Signal(syscall.Signal(0)) - assert.NoError(t, err) + assertNoError(t, err) time.Sleep(300 * time.Millisecond) - assert.True(t, proc.IsRunning()) + assertTrue(t, proc.IsRunning()) err = proc.Kill() - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -335,10 +332,10 @@ func TestProcess_CloseStdin(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) err = proc.CloseStdin() - assert.NoError(t, err) + assertNoError(t, err) // Process should exit now that stdin is closed select { @@ -353,17 +350,17 @@ func TestProcess_CloseStdin(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) // First close err = proc.CloseStdin() - assert.NoError(t, err) + assertNoError(t, err) <-proc.Done() // Second close should be safe (stdin already nil) err = proc.CloseStdin() - assert.NoError(t, err) + assertNoError(t, err) }) } @@ -376,7 +373,7 @@ func TestProcess_Timeout(t *testing.T) { Args: []string{"60"}, Timeout: 200 * time.Millisecond, }) - require.NoError(t, err) + requireNoError(t, err) select { case <-proc.Done(): @@ -385,8 +382,8 @@ func TestProcess_Timeout(t *testing.T) { t.Fatal("process should have been killed by timeout") } - assert.False(t, proc.IsRunning()) - assert.Equal(t, StatusKilled, proc.Status) + assertFalse(t, proc.IsRunning()) + assertEqual(t, StatusKilled, proc.Status) }) t.Run("no timeout when zero", func(t *testing.T) { @@ -397,10 +394,10 @@ func TestProcess_Timeout(t *testing.T) { Args: []string{"fast"}, Timeout: 0, }) - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.Equal(t, 0, proc.ExitCode) + assertEqual(t, 0, proc.ExitCode) }) } @@ -414,12 +411,12 @@ func TestProcess_Shutdown(t *testing.T) { Args: []string{"60"}, GracePeriod: 100 * time.Millisecond, }) - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, proc.IsRunning()) + assertTrue(t, proc.IsRunning()) err = proc.Shutdown() - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -428,7 +425,7 @@ func TestProcess_Shutdown(t *testing.T) { t.Fatal("shutdown should have completed") } - assert.Equal(t, StatusKilled, proc.Status) + assertEqual(t, StatusKilled, proc.Status) }) t.Run("immediate kill without grace period", func(t *testing.T) { @@ -438,10 +435,10 @@ func TestProcess_Shutdown(t *testing.T) { Command: "sleep", Args: []string{"60"}, }) - require.NoError(t, err) + requireNoError(t, err) err = proc.Shutdown() - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -463,13 +460,13 @@ func TestProcess_KillGroup(t *testing.T) { Detach: true, KillGroup: true, }) - require.NoError(t, err) + requireNoError(t, err) // Give child time to spawn time.Sleep(100 * time.Millisecond) err = proc.Kill() - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -478,7 +475,7 @@ func TestProcess_KillGroup(t *testing.T) { t.Fatal("process group should have been killed") } - assert.Equal(t, StatusKilled, proc.Status) + assertEqual(t, StatusKilled, proc.Status) }) } @@ -492,7 +489,7 @@ func TestProcess_TimeoutWithGrace(t *testing.T) { Timeout: 200 * time.Millisecond, GracePeriod: 100 * time.Millisecond, }) - require.NoError(t, err) + requireNoError(t, err) select { case <-proc.Done(): @@ -501,6 +498,6 @@ func TestProcess_TimeoutWithGrace(t *testing.T) { t.Fatal("process should have been killed by timeout") } - assert.Equal(t, StatusKilled, proc.Status) + assertEqual(t, StatusKilled, proc.Status) }) } diff --git a/program_test.go b/program_test.go index 7d38a76..7d2d273 100644 --- a/program_test.go +++ b/program_test.go @@ -2,14 +2,12 @@ package process_test import ( "context" + "errors" "os/exec" "path/filepath" "testing" "time" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - process "dappco.re/go/core/process" ) @@ -22,60 +20,94 @@ func testCtx(t *testing.T) context.Context { func TestProgram_Find_KnownBinary(t *testing.T) { p := &process.Program{Name: "echo"} - require.NoError(t, p.Find()) - assert.NotEmpty(t, p.Path) + if err := p.Find(); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if p.Path == "" { + t.Fatal("expected non-empty path") + } } func TestProgram_Find_UnknownBinary(t *testing.T) { p := &process.Program{Name: "no-such-binary-xyzzy-42"} err := p.Find() - require.Error(t, err) - assert.ErrorIs(t, err, process.ErrProgramNotFound) + if err == nil { + t.Fatal("expected error, got nil") + } + if !errors.Is(err, process.ErrProgramNotFound) { + t.Fatalf("expected ErrProgramNotFound, got %v", err) + } } func TestProgram_Find_UsesExistingPath(t *testing.T) { path, err := exec.LookPath("echo") - require.NoError(t, err) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } p := &process.Program{Path: path} - require.NoError(t, p.Find()) - assert.Equal(t, path, p.Path) + if err := p.Find(); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if p.Path != path { + t.Fatalf("want %v, got %v", path, p.Path) + } } func TestProgram_Find_PrefersExistingPathOverName(t *testing.T) { path, err := exec.LookPath("echo") - require.NoError(t, err) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } p := &process.Program{ Name: "no-such-binary-xyzzy-42", Path: path, } - require.NoError(t, p.Find()) - assert.Equal(t, path, p.Path) + if err := p.Find(); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if p.Path != path { + t.Fatalf("want %v, got %v", path, p.Path) + } } func TestProgram_Find_EmptyName(t *testing.T) { p := &process.Program{} - require.Error(t, p.Find()) + if err := p.Find(); err == nil { + t.Fatal("expected error, got nil") + } } func TestProgram_Run_ReturnsOutput(t *testing.T) { p := &process.Program{Name: "echo"} - require.NoError(t, p.Find()) + if err := p.Find(); err != nil { + t.Fatalf("unexpected error: %v", err) + } out, err := p.Run(testCtx(t), "hello") - require.NoError(t, err) - assert.Equal(t, "hello", out) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if out != "hello" { + t.Fatalf("want %q, got %q", "hello", out) + } } func TestProgram_Run_PreservesLeadingWhitespace(t *testing.T) { p := &process.Program{Name: "sh"} - require.NoError(t, p.Find()) + if err := p.Find(); err != nil { + t.Fatalf("unexpected error: %v", err) + } out, err := p.Run(testCtx(t), "-c", "printf ' hello \n'") - require.NoError(t, err) - assert.Equal(t, " hello", out) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if out != " hello" { + t.Fatalf("want %q, got %q", " hello", out) + } } func TestProgram_Run_WithoutFind_FallsBackToName(t *testing.T) { @@ -83,46 +115,72 @@ func TestProgram_Run_WithoutFind_FallsBackToName(t *testing.T) { p := &process.Program{Name: "echo"} out, err := p.Run(testCtx(t), "fallback") - require.NoError(t, err) - assert.Equal(t, "fallback", out) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if out != "fallback" { + t.Fatalf("want %q, got %q", "fallback", out) + } } func TestProgram_RunDir_UsesDirectory(t *testing.T) { p := &process.Program{Name: "pwd"} - require.NoError(t, p.Find()) + if err := p.Find(); err != nil { + t.Fatalf("unexpected error: %v", err) + } dir := t.TempDir() out, err := p.RunDir(testCtx(t), dir) - require.NoError(t, err) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } // Resolve symlinks on both sides for portability (macOS uses /private/ prefix). canonicalDir, err := filepath.EvalSymlinks(dir) - require.NoError(t, err) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } canonicalOut, err := filepath.EvalSymlinks(out) - require.NoError(t, err) - assert.Equal(t, canonicalDir, canonicalOut) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if canonicalDir != canonicalOut { + t.Fatalf("want %q, got %q", canonicalDir, canonicalOut) + } } func TestProgram_Run_FailingCommand(t *testing.T) { p := &process.Program{Name: "false"} - require.NoError(t, p.Find()) + if err := p.Find(); err != nil { + t.Fatalf("unexpected error: %v", err) + } _, err := p.Run(testCtx(t)) - require.Error(t, err) + if err == nil { + t.Fatal("expected error, got nil") + } } func TestProgram_Run_NilContextRejected(t *testing.T) { p := &process.Program{Name: "echo"} _, err := p.Run(nil, "test") - require.Error(t, err) - assert.ErrorIs(t, err, process.ErrProgramContextRequired) + if err == nil { + t.Fatal("expected error, got nil") + } + if !errors.Is(err, process.ErrProgramContextRequired) { + t.Fatalf("expected ErrProgramContextRequired, got %v", err) + } } func TestProgram_RunDir_EmptyNameRejected(t *testing.T) { p := &process.Program{} _, err := p.RunDir(testCtx(t), "", "test") - require.Error(t, err) - assert.ErrorIs(t, err, process.ErrProgramNameRequired) + if err == nil { + t.Fatal("expected error, got nil") + } + if !errors.Is(err, process.ErrProgramNameRequired) { + t.Fatalf("expected ErrProgramNameRequired, got %v", err) + } } diff --git a/registry_test.go b/registry_test.go index a3f1c41..e18e865 100644 --- a/registry_test.go +++ b/registry_test.go @@ -5,9 +5,6 @@ import ( "path/filepath" "testing" "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestRegistry_RegisterAndGet(t *testing.T) { @@ -26,17 +23,17 @@ func TestRegistry_RegisterAndGet(t *testing.T) { } err := reg.Register(entry) - require.NoError(t, err) + requireNoError(t, err) got, ok := reg.Get("myapp", "worker") - require.True(t, ok) - assert.Equal(t, "myapp", got.Code) - assert.Equal(t, "worker", got.Daemon) - assert.Equal(t, os.Getpid(), got.PID) - assert.Equal(t, "healthy", got.Health) - assert.Equal(t, "test-project", got.Project) - assert.Equal(t, "/usr/bin/worker", got.Binary) - assert.Equal(t, started, got.Started) + requireTrue(t, ok) + assertEqual(t, "myapp", got.Code) + assertEqual(t, "worker", got.Daemon) + assertEqual(t, os.Getpid(), got.PID) + assertEqual(t, "healthy", got.Health) + assertEqual(t, "test-project", got.Project) + assertEqual(t, "/usr/bin/worker", got.Binary) + assertEqual(t, started, got.Started) } func TestRegistry_Unregister(t *testing.T) { @@ -50,19 +47,19 @@ func TestRegistry_Unregister(t *testing.T) { } err := reg.Register(entry) - require.NoError(t, err) + requireNoError(t, err) // File should exist path := filepath.Join(dir, "myapp-server.json") _, err = os.Stat(path) - require.NoError(t, err) + requireNoError(t, err) err = reg.Unregister("myapp", "server") - require.NoError(t, err) + requireNoError(t, err) // File should be gone _, err = os.Stat(path) - assert.True(t, os.IsNotExist(err)) + assertTrue(t, os.IsNotExist(err)) } func TestRegistry_UnregisterMissingIsNoop(t *testing.T) { @@ -70,7 +67,7 @@ func TestRegistry_UnregisterMissingIsNoop(t *testing.T) { reg := NewRegistry(dir) err := reg.Unregister("missing", "entry") - require.NoError(t, err) + requireNoError(t, err) } func TestRegistry_List(t *testing.T) { @@ -78,15 +75,15 @@ func TestRegistry_List(t *testing.T) { reg := NewRegistry(dir) err := reg.Register(DaemonEntry{Code: "app1", Daemon: "web", PID: os.Getpid()}) - require.NoError(t, err) + requireNoError(t, err) err = reg.Register(DaemonEntry{Code: "app2", Daemon: "api", PID: os.Getpid()}) - require.NoError(t, err) + requireNoError(t, err) entries, err := reg.List() - require.NoError(t, err) - require.Len(t, entries, 2) - assert.Equal(t, "app1", entries[0].Code) - assert.Equal(t, "app2", entries[1].Code) + requireNoError(t, err) + requireLen(t, entries, 2) + assertEqual(t, "app1", entries[0].Code) + assertEqual(t, "app2", entries[1].Code) } func TestRegistry_List_PrunesStale(t *testing.T) { @@ -94,20 +91,20 @@ func TestRegistry_List_PrunesStale(t *testing.T) { reg := NewRegistry(dir) err := reg.Register(DaemonEntry{Code: "dead", Daemon: "proc", PID: 999999999}) - require.NoError(t, err) + requireNoError(t, err) // File should exist before listing path := filepath.Join(dir, "dead-proc.json") _, err = os.Stat(path) - require.NoError(t, err) + requireNoError(t, err) entries, err := reg.List() - require.NoError(t, err) - assert.Empty(t, entries) + requireNoError(t, err) + assertEmpty(t, entries) // Stale file should be removed _, err = os.Stat(path) - assert.True(t, os.IsNotExist(err)) + assertTrue(t, os.IsNotExist(err)) } func TestRegistry_Get_NotFound(t *testing.T) { @@ -115,8 +112,8 @@ func TestRegistry_Get_NotFound(t *testing.T) { reg := NewRegistry(dir) got, ok := reg.Get("nope", "missing") - assert.Nil(t, got) - assert.False(t, ok) + assertNil(t, got) + assertFalse(t, ok) } func TestRegistry_CreatesDirectory(t *testing.T) { @@ -124,14 +121,14 @@ func TestRegistry_CreatesDirectory(t *testing.T) { reg := NewRegistry(dir) err := reg.Register(DaemonEntry{Code: "app", Daemon: "srv", PID: os.Getpid()}) - require.NoError(t, err) + requireNoError(t, err) info, err := os.Stat(dir) - require.NoError(t, err) - assert.True(t, info.IsDir()) + requireNoError(t, err) + assertTrue(t, info.IsDir()) } func TestDefaultRegistry(t *testing.T) { reg := DefaultRegistry() - assert.NotNil(t, reg) + assertNotNil(t, reg) } diff --git a/runner_test.go b/runner_test.go index f27e078..81a2af8 100644 --- a/runner_test.go +++ b/runner_test.go @@ -5,8 +5,6 @@ import ( "testing" framework "dappco.re/go/core" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func newTestRunner(t *testing.T) *Runner { @@ -15,7 +13,7 @@ func newTestRunner(t *testing.T) *Runner { c := framework.New() factory := NewService(Options{}) raw, err := factory(c) - require.NoError(t, err) + requireNoError(t, err) return NewRunner(raw.(*Service)) } @@ -29,12 +27,12 @@ func TestRunner_RunSequential(t *testing.T) { {Name: "second", Command: "echo", Args: []string{"2"}}, {Name: "third", Command: "echo", Args: []string{"3"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, result.Success()) - assert.Equal(t, 3, result.Passed) - assert.Equal(t, 0, result.Failed) - assert.Equal(t, 0, result.Skipped) + assertTrue(t, result.Success()) + assertEqual(t, 3, result.Passed) + assertEqual(t, 0, result.Failed) + assertEqual(t, 0, result.Skipped) }) t.Run("stops on failure", func(t *testing.T) { @@ -45,18 +43,18 @@ func TestRunner_RunSequential(t *testing.T) { {Name: "fails", Command: "sh", Args: []string{"-c", "exit 1"}}, {Name: "third", Command: "echo", Args: []string{"3"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.False(t, result.Success()) - assert.Equal(t, 1, result.Passed) - assert.Equal(t, 1, result.Failed) - assert.Equal(t, 1, result.Skipped) - require.Len(t, result.Results, 3) - assert.Equal(t, 0, result.Results[0].ExitCode) - assert.NoError(t, result.Results[0].Error) - assert.Equal(t, 1, result.Results[1].ExitCode) - assert.NoError(t, result.Results[1].Error) - assert.True(t, result.Results[2].Skipped) + assertFalse(t, result.Success()) + assertEqual(t, 1, result.Passed) + assertEqual(t, 1, result.Failed) + assertEqual(t, 1, result.Skipped) + requireLen(t, result.Results, 3) + assertEqual(t, 0, result.Results[0].ExitCode) + assertNoError(t, result.Results[0].Error) + assertEqual(t, 1, result.Results[1].ExitCode) + assertNoError(t, result.Results[1].Error) + assertTrue(t, result.Results[2].Skipped) }) t.Run("allow failure continues", func(t *testing.T) { @@ -67,12 +65,12 @@ func TestRunner_RunSequential(t *testing.T) { {Name: "fails", Command: "sh", Args: []string{"-c", "exit 1"}, AllowFailure: true}, {Name: "third", Command: "echo", Args: []string{"3"}}, }) - require.NoError(t, err) + requireNoError(t, err) // Still counts as failed but pipeline continues - assert.Equal(t, 2, result.Passed) - assert.Equal(t, 1, result.Failed) - assert.Equal(t, 0, result.Skipped) + assertEqual(t, 2, result.Passed) + assertEqual(t, 1, result.Failed) + assertEqual(t, 0, result.Skipped) }) } @@ -85,11 +83,11 @@ func TestRunner_RunParallel(t *testing.T) { {Name: "second", Command: "echo", Args: []string{"2"}}, {Name: "third", Command: "echo", Args: []string{"3"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, result.Success()) - assert.Equal(t, 3, result.Passed) - assert.Len(t, result.Results, 3) + assertTrue(t, result.Success()) + assertEqual(t, 3, result.Passed) + assertLen(t, result.Results, 3) }) t.Run("failure doesnt stop others", func(t *testing.T) { @@ -100,11 +98,11 @@ func TestRunner_RunParallel(t *testing.T) { {Name: "fails", Command: "sh", Args: []string{"-c", "exit 1"}}, {Name: "third", Command: "echo", Args: []string{"3"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.False(t, result.Success()) - assert.Equal(t, 2, result.Passed) - assert.Equal(t, 1, result.Failed) + assertFalse(t, result.Success()) + assertEqual(t, 2, result.Passed) + assertEqual(t, 1, result.Failed) }) } @@ -117,10 +115,10 @@ func TestRunner_RunAll(t *testing.T) { {Name: "first", Command: "echo", Args: []string{"1"}}, {Name: "second", Command: "echo", Args: []string{"2"}, After: []string{"first"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, result.Success()) - assert.Equal(t, 3, result.Passed) + assertTrue(t, result.Success()) + assertEqual(t, 3, result.Passed) }) t.Run("skips dependents on failure", func(t *testing.T) { @@ -131,12 +129,12 @@ func TestRunner_RunAll(t *testing.T) { {Name: "second", Command: "echo", Args: []string{"2"}, After: []string{"first"}}, {Name: "third", Command: "echo", Args: []string{"3"}, After: []string{"second"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.False(t, result.Success()) - assert.Equal(t, 0, result.Passed) - assert.Equal(t, 1, result.Failed) - assert.Equal(t, 2, result.Skipped) + assertFalse(t, result.Success()) + assertEqual(t, 0, result.Passed) + assertEqual(t, 1, result.Failed) + assertEqual(t, 2, result.Skipped) }) t.Run("parallel independent specs", func(t *testing.T) { @@ -149,10 +147,10 @@ func TestRunner_RunAll(t *testing.T) { {Name: "c", Command: "echo", Args: []string{"c"}}, {Name: "final", Command: "echo", Args: []string{"done"}, After: []string{"a", "b", "c"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, result.Success()) - assert.Equal(t, 4, result.Passed) + assertTrue(t, result.Success()) + assertEqual(t, 4, result.Passed) }) t.Run("preserves input order", func(t *testing.T) { @@ -165,11 +163,11 @@ func TestRunner_RunAll(t *testing.T) { } result, err := runner.RunAll(context.Background(), specs) - require.NoError(t, err) + requireNoError(t, err) - require.Len(t, result.Results, len(specs)) + requireLen(t, result.Results, len(specs)) for i, res := range result.Results { - assert.Equal(t, specs[i].Name, res.Name) + assertEqual(t, specs[i].Name, res.Name) } }) } @@ -182,15 +180,15 @@ func TestRunner_RunAll_CircularDeps(t *testing.T) { {Name: "a", Command: "echo", Args: []string{"a"}, After: []string{"b"}}, {Name: "b", Command: "echo", Args: []string{"b"}, After: []string{"a"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, result.Success()) - assert.Equal(t, 0, result.Failed) - assert.Equal(t, 2, result.Skipped) + assertTrue(t, result.Success()) + assertEqual(t, 0, result.Failed) + assertEqual(t, 2, result.Skipped) for _, res := range result.Results { - assert.True(t, res.Skipped) - assert.Equal(t, 0, res.ExitCode) - assert.Error(t, res.Error) + assertTrue(t, res.Skipped) + assertEqual(t, 0, res.ExitCode) + assertError(t, res.Error) } }) @@ -200,15 +198,15 @@ func TestRunner_RunAll_CircularDeps(t *testing.T) { result, err := runner.RunAll(context.Background(), []RunSpec{ {Name: "a", Command: "echo", Args: []string{"a"}, After: []string{"missing"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, result.Success()) - assert.Equal(t, 0, result.Failed) - assert.Equal(t, 1, result.Skipped) - require.Len(t, result.Results, 1) - assert.True(t, result.Results[0].Skipped) - assert.Equal(t, 0, result.Results[0].ExitCode) - assert.Error(t, result.Results[0].Error) + assertTrue(t, result.Success()) + assertEqual(t, 0, result.Failed) + assertEqual(t, 1, result.Skipped) + requireLen(t, result.Results, 1) + assertTrue(t, result.Results[0].Skipped) + assertEqual(t, 0, result.Results[0].ExitCode) + assertError(t, result.Results[0].Error) }) } @@ -223,17 +221,17 @@ func TestRunner_ContextCancellation(t *testing.T) { {Name: "first", Command: "echo", Args: []string{"1"}}, {Name: "second", Command: "echo", Args: []string{"2"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.Equal(t, 0, result.Passed) - assert.Equal(t, 0, result.Failed) - assert.Equal(t, 2, result.Skipped) - require.Len(t, result.Results, 2) + assertEqual(t, 0, result.Passed) + assertEqual(t, 0, result.Failed) + assertEqual(t, 2, result.Skipped) + requireLen(t, result.Results, 2) for _, res := range result.Results { - assert.True(t, res.Skipped) - assert.Equal(t, 1, res.ExitCode) - assert.Error(t, res.Error) - assert.Contains(t, res.Error.Error(), "context canceled") + assertTrue(t, res.Skipped) + assertEqual(t, 1, res.ExitCode) + assertError(t, res.Error) + assertContains(t, res.Error.Error(), "context canceled") } }) @@ -247,17 +245,17 @@ func TestRunner_ContextCancellation(t *testing.T) { {Name: "first", Command: "echo", Args: []string{"1"}}, {Name: "second", Command: "echo", Args: []string{"2"}, After: []string{"first"}}, }) - require.NoError(t, err) + requireNoError(t, err) - assert.Equal(t, 0, result.Passed) - assert.Equal(t, 0, result.Failed) - assert.Equal(t, 2, result.Skipped) - require.Len(t, result.Results, 2) + assertEqual(t, 0, result.Passed) + assertEqual(t, 0, result.Failed) + assertEqual(t, 2, result.Skipped) + requireLen(t, result.Results, 2) for _, res := range result.Results { - assert.True(t, res.Skipped) - assert.Equal(t, 1, res.ExitCode) - assert.Error(t, res.Error) - assert.Contains(t, res.Error.Error(), "context canceled") + assertTrue(t, res.Skipped) + assertEqual(t, 1, res.ExitCode) + assertError(t, res.Error) + assertContains(t, res.Error.Error(), "context canceled") } }) } @@ -265,22 +263,22 @@ func TestRunner_ContextCancellation(t *testing.T) { func TestRunResult_Passed(t *testing.T) { t.Run("success", func(t *testing.T) { r := RunResult{ExitCode: 0} - assert.True(t, r.Passed()) + assertTrue(t, r.Passed()) }) t.Run("non-zero exit", func(t *testing.T) { r := RunResult{ExitCode: 1} - assert.False(t, r.Passed()) + assertFalse(t, r.Passed()) }) t.Run("skipped", func(t *testing.T) { r := RunResult{ExitCode: 0, Skipped: true} - assert.False(t, r.Passed()) + assertFalse(t, r.Passed()) }) t.Run("error", func(t *testing.T) { - r := RunResult{ExitCode: 0, Error: assert.AnError} - assert.False(t, r.Passed()) + r := RunResult{ExitCode: 0, Error: errSentinel} + assertFalse(t, r.Passed()) }) } @@ -288,32 +286,32 @@ func TestRunner_NilService(t *testing.T) { runner := NewRunner(nil) _, err := runner.RunAll(context.Background(), nil) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerNoService) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerNoService) _, err = runner.RunSequential(context.Background(), nil) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerNoService) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerNoService) _, err = runner.RunParallel(context.Background(), nil) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerNoService) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerNoService) } func TestRunner_NilContext(t *testing.T) { runner := newTestRunner(t) _, err := runner.RunAll(nil, nil) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerContextRequired) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerContextRequired) _, err = runner.RunSequential(nil, nil) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerContextRequired) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerContextRequired) _, err = runner.RunParallel(nil, nil) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerContextRequired) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerContextRequired) } func TestRunner_InvalidSpecNames(t *testing.T) { @@ -323,32 +321,32 @@ func TestRunner_InvalidSpecNames(t *testing.T) { _, err := runner.RunSequential(context.Background(), []RunSpec{ {Name: "", Command: "echo", Args: []string{"a"}}, }) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerInvalidSpecName) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerInvalidSpecName) }) t.Run("rejects empty dependency names", func(t *testing.T) { _, err := runner.RunAll(context.Background(), []RunSpec{ {Name: "one", Command: "echo", Args: []string{"a"}, After: []string{""}}, }) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerInvalidDependencyName) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerInvalidDependencyName) }) t.Run("rejects duplicated dependency names", func(t *testing.T) { _, err := runner.RunAll(context.Background(), []RunSpec{ {Name: "one", Command: "echo", Args: []string{"a"}, After: []string{"two", "two"}}, }) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerInvalidDependencyName) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerInvalidDependencyName) }) t.Run("rejects self dependency", func(t *testing.T) { _, err := runner.RunAll(context.Background(), []RunSpec{ {Name: "one", Command: "echo", Args: []string{"a"}, After: []string{"one"}}, }) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerInvalidDependencyName) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerInvalidDependencyName) }) t.Run("rejects duplicate names", func(t *testing.T) { @@ -356,8 +354,8 @@ func TestRunner_InvalidSpecNames(t *testing.T) { {Name: "same", Command: "echo", Args: []string{"a"}}, {Name: "same", Command: "echo", Args: []string{"b"}}, }) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerInvalidSpecName) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerInvalidSpecName) }) t.Run("rejects duplicate names in parallel mode", func(t *testing.T) { @@ -365,7 +363,7 @@ func TestRunner_InvalidSpecNames(t *testing.T) { {Name: "one", Command: "echo", Args: []string{"a"}}, {Name: "one", Command: "echo", Args: []string{"b"}}, }) - require.Error(t, err) - assert.ErrorIs(t, err, ErrRunnerInvalidSpecName) + requireError(t, err) + assertErrorIs(t, err, ErrRunnerInvalidSpecName) }) } diff --git a/service_test.go b/service_test.go index 455cce9..f6ba1ec 100644 --- a/service_test.go +++ b/service_test.go @@ -10,8 +10,6 @@ import ( "time" framework "dappco.re/go/core" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func newTestService(t *testing.T) (*Service, *framework.Core) { @@ -20,7 +18,7 @@ func newTestService(t *testing.T) (*Service, *framework.Core) { c := framework.New() factory := NewService(Options{BufferSize: 1024}) raw, err := factory(c) - require.NoError(t, err) + requireNoError(t, err) svc := raw.(*Service) return svc, c @@ -56,19 +54,19 @@ func TestService_Start(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "hello") - require.NoError(t, err) - require.NotNil(t, proc) + requireNoError(t, err) + requireNotNil(t, proc) - assert.NotEmpty(t, proc.ID) - assert.Equal(t, "echo", proc.Command) - assert.Equal(t, []string{"hello"}, proc.Args) + assertNotEmpty(t, proc.ID) + assertEqual(t, "echo", proc.Command) + assertEqual(t, []string{"hello"}, proc.Args) // Wait for completion <-proc.Done() - assert.Equal(t, StatusExited, proc.Status) - assert.Equal(t, 0, proc.ExitCode) - assert.Contains(t, proc.Output(), "hello") + assertEqual(t, StatusExited, proc.Status) + assertEqual(t, 0, proc.ExitCode) + assertContains(t, proc.Output(), "hello") }) t.Run("works without core runtime", func(t *testing.T) { @@ -78,51 +76,51 @@ func TestService_Start(t *testing.T) { } proc, err := svc.Start(context.Background(), "echo", "standalone") - require.NoError(t, err) - require.NotNil(t, proc) + requireNoError(t, err) + requireNotNil(t, proc) <-proc.Done() - assert.Equal(t, StatusExited, proc.Status) - assert.Equal(t, 0, proc.ExitCode) - assert.Contains(t, proc.Output(), "standalone") + assertEqual(t, StatusExited, proc.Status) + assertEqual(t, 0, proc.ExitCode) + assertContains(t, proc.Output(), "standalone") }) t.Run("failing command", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "sh", "-c", "exit 42") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.Equal(t, StatusExited, proc.Status) - assert.Equal(t, 42, proc.ExitCode) + assertEqual(t, StatusExited, proc.Status) + assertEqual(t, 42, proc.ExitCode) }) t.Run("non-existent command", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "nonexistent_command_xyz") - assert.Error(t, err) - require.NotNil(t, proc) - assert.Equal(t, StatusFailed, proc.Status) - assert.Equal(t, -1, proc.ExitCode) - assert.NotNil(t, proc.Done()) + assertError(t, err) + requireNotNil(t, proc) + assertEqual(t, StatusFailed, proc.Status) + assertEqual(t, -1, proc.ExitCode) + assertNotNil(t, proc.Done()) <-proc.Done() got, getErr := svc.Get(proc.ID) - require.NoError(t, getErr) - assert.Equal(t, proc.ID, got.ID) - assert.Equal(t, StatusFailed, got.Status) + requireNoError(t, getErr) + assertEqual(t, proc.ID, got.ID) + assertEqual(t, StatusFailed, got.Status) }) t.Run("empty command is rejected", func(t *testing.T) { svc, _ := newTestService(t) _, err := svc.StartWithOptions(context.Background(), RunOptions{}) - require.Error(t, err) - assert.Contains(t, err.Error(), "command is required") + requireError(t, err) + assertContains(t, err.Error(), "command is required") }) t.Run("nil context is rejected", func(t *testing.T) { @@ -131,8 +129,8 @@ func TestService_Start(t *testing.T) { _, err := svc.StartWithOptions(nil, RunOptions{ Command: "echo", }) - require.Error(t, err) - assert.ErrorIs(t, err, ErrContextRequired) + requireError(t, err) + assertErrorIs(t, err, ErrContextRequired) }) t.Run("with working directory", func(t *testing.T) { @@ -142,13 +140,13 @@ func TestService_Start(t *testing.T) { Command: "pwd", Dir: "/tmp", }) - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() // On macOS /tmp is a symlink to /private/tmp output := strings.TrimSpace(proc.Output()) - assert.True(t, output == "/tmp" || output == "/private/tmp", "got: %s", output) + assertTrue(t, output == "/tmp" || output == "/private/tmp", "got: %s", output) }) t.Run("context cancellation", func(t *testing.T) { @@ -156,7 +154,7 @@ func TestService_Start(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) proc, err := svc.Start(ctx, "sleep", "10") - require.NoError(t, err) + requireNoError(t, err) // Cancel immediately cancel() @@ -177,11 +175,11 @@ func TestService_Start(t *testing.T) { Args: []string{"no-capture"}, DisableCapture: true, }) - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.Equal(t, StatusExited, proc.Status) - assert.Equal(t, "", proc.Output(), "output should be empty when capture is disabled") + assertEqual(t, StatusExited, proc.Status) + assertEqual(t, "", proc.Output()) }) t.Run("with environment variables", func(t *testing.T) { @@ -192,10 +190,10 @@ func TestService_Start(t *testing.T) { Args: []string{"-c", "echo $MY_TEST_VAR"}, Env: []string{"MY_TEST_VAR=hello_env"}, }) - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.Contains(t, proc.Output(), "hello_env") + assertContains(t, proc.Output(), "hello_env") }) t.Run("detach survives parent context", func(t *testing.T) { @@ -208,7 +206,7 @@ func TestService_Start(t *testing.T) { Args: []string{"detached"}, Detach: true, }) - require.NoError(t, err) + requireNoError(t, err) // Cancel the parent context cancel() @@ -216,8 +214,8 @@ func TestService_Start(t *testing.T) { // Detached process should still complete normally select { case <-proc.Done(): - assert.Equal(t, StatusExited, proc.Status) - assert.Equal(t, 0, proc.ExitCode) + assertEqual(t, StatusExited, proc.Status) + assertEqual(t, 0, proc.ExitCode) case <-time.After(2 * time.Second): t.Fatal("detached process should have completed") } @@ -231,8 +229,8 @@ func TestService_Start(t *testing.T) { Args: []string{"1"}, KillGroup: true, }) - require.Error(t, err) - assert.Contains(t, err.Error(), "KillGroup requires Detach") + requireError(t, err) + assertContains(t, err.Error(), "KillGroup requires Detach") }) } @@ -241,16 +239,16 @@ func TestService_Run(t *testing.T) { svc, _ := newTestService(t) output, err := svc.Run(context.Background(), "echo", "hello world") - require.NoError(t, err) - assert.Contains(t, output, "hello world") + requireNoError(t, err) + assertContains(t, output, "hello world") }) t.Run("returns error on failure", func(t *testing.T) { svc, _ := newTestService(t) _, err := svc.Run(context.Background(), "sh", "-c", "exit 1") - assert.Error(t, err) - assert.Contains(t, err.Error(), "exited with code 1") + assertError(t, err) + assertContains(t, err.Error(), "exited with code 1") }) } @@ -261,7 +259,7 @@ func TestService_Actions(t *testing.T) { // Register process service on Core factory := NewService(Options{}) raw, err := factory(c) - require.NoError(t, err) + requireNoError(t, err) svc := raw.(*Service) var started []ActionProcessStarted @@ -283,7 +281,7 @@ func TestService_Actions(t *testing.T) { return framework.Result{OK: true} }) proc, err := svc.Start(context.Background(), "echo", "test") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() @@ -293,11 +291,11 @@ func TestService_Actions(t *testing.T) { mu.Lock() defer mu.Unlock() - assert.Len(t, started, 1) - assert.Equal(t, "echo", started[0].Command) - assert.Equal(t, []string{"test"}, started[0].Args) + assertLen(t, started, 1) + assertEqual(t, "echo", started[0].Command) + assertEqual(t, []string{"test"}, started[0].Args) - assert.NotEmpty(t, outputs) + assertNotEmpty(t, outputs) foundTest := false for _, o := range outputs { if strings.Contains(o.Line, "test") { @@ -305,11 +303,11 @@ func TestService_Actions(t *testing.T) { break } } - assert.True(t, foundTest, "should have output containing 'test'") + assertTrue(t, foundTest, "should have output containing 'test'") - assert.Len(t, exited, 1) - assert.Equal(t, 0, exited[0].ExitCode) - assert.Nil(t, exited[0].Error) + assertLen(t, exited, 1) + assertEqual(t, 0, exited[0].ExitCode) + assertNil(t, exited[0].Error) }) t.Run("broadcasts killed events", func(t *testing.T) { @@ -317,7 +315,7 @@ func TestService_Actions(t *testing.T) { factory := NewService(Options{}) raw, err := factory(c) - require.NoError(t, err) + requireNoError(t, err) svc := raw.(*Service) var killed []ActionProcessKilled @@ -337,17 +335,17 @@ func TestService_Actions(t *testing.T) { }) proc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) err = svc.Kill(proc.ID) - require.NoError(t, err) + requireNoError(t, err) time.Sleep(10 * time.Millisecond) mu.Lock() - require.Len(t, killed, 1) - assert.Equal(t, proc.ID, killed[0].ID) - assert.NotEmpty(t, killed[0].Signal) + requireLen(t, killed, 1) + assertEqual(t, proc.ID, killed[0].ID) + assertNotEmpty(t, killed[0].Signal) mu.Unlock() select { @@ -360,11 +358,11 @@ func TestService_Actions(t *testing.T) { mu.Lock() defer mu.Unlock() - assert.Len(t, exited, 1) - assert.Equal(t, proc.ID, exited[0].ID) - require.Error(t, exited[0].Error) - assert.Contains(t, exited[0].Error.Error(), "process was killed") - assert.Equal(t, StatusKilled, proc.Status) + assertLen(t, exited, 1) + assertEqual(t, proc.ID, exited[0].ID) + requireError(t, exited[0].Error) + assertContains(t, exited[0].Error.Error(), "process was killed") + assertEqual(t, StatusKilled, proc.Status) }) t.Run("broadcasts exited event on start failure", func(t *testing.T) { @@ -372,7 +370,7 @@ func TestService_Actions(t *testing.T) { factory := NewService(Options{}) raw, err := factory(c) - require.NoError(t, err) + requireNoError(t, err) svc := raw.(*Service) var exited []ActionProcessExited @@ -388,16 +386,16 @@ func TestService_Actions(t *testing.T) { }) _, err = svc.Start(context.Background(), "definitely-not-a-real-binary-xyz") - require.Error(t, err) + requireError(t, err) time.Sleep(10 * time.Millisecond) mu.Lock() defer mu.Unlock() - require.Len(t, exited, 1) - assert.Equal(t, -1, exited[0].ExitCode) - require.Error(t, exited[0].Error) - assert.Contains(t, exited[0].Error.Error(), "failed to start process") + requireLen(t, exited, 1) + assertEqual(t, -1, exited[0].ExitCode) + requireError(t, exited[0].Error) + assertContains(t, exited[0].Error.Error(), "failed to start process") }) t.Run("broadcasts exited error on non-zero exit", func(t *testing.T) { @@ -405,7 +403,7 @@ func TestService_Actions(t *testing.T) { factory := NewService(Options{}) raw, err := factory(c) - require.NoError(t, err) + requireNoError(t, err) svc := raw.(*Service) var exited []ActionProcessExited @@ -421,17 +419,17 @@ func TestService_Actions(t *testing.T) { }) proc, err := svc.Start(context.Background(), "sh", "-c", "exit 7") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() time.Sleep(10 * time.Millisecond) mu.Lock() defer mu.Unlock() - require.Len(t, exited, 1) - assert.Equal(t, 7, exited[0].ExitCode) - require.Error(t, exited[0].Error) - assert.Contains(t, exited[0].Error.Error(), "process exited with code 7") + requireLen(t, exited, 1) + assertEqual(t, 7, exited[0].ExitCode) + requireError(t, exited[0].Error) + assertContains(t, exited[0].Error.Error(), "process exited with code 7") }) } @@ -446,9 +444,9 @@ func TestService_List(t *testing.T) { <-proc2.Done() list := svc.List() - assert.Len(t, list, 2) - assert.Equal(t, proc1.ID, list[0].ID) - assert.Equal(t, proc2.ID, list[1].ID) + assertLen(t, list, 2) + assertEqual(t, proc1.ID, list[0].ID) + assertEqual(t, proc2.ID, list[1].ID) }) t.Run("get by id", func(t *testing.T) { @@ -458,15 +456,15 @@ func TestService_List(t *testing.T) { <-proc.Done() got, err := svc.Get(proc.ID) - require.NoError(t, err) - assert.Equal(t, proc.ID, got.ID) + requireNoError(t, err) + assertEqual(t, proc.ID, got.ID) }) t.Run("get not found", func(t *testing.T) { svc, _ := newTestService(t) _, err := svc.Get("nonexistent") - assert.ErrorIs(t, err, ErrProcessNotFound) + assertErrorIs(t, err, ErrProcessNotFound) }) } @@ -478,10 +476,10 @@ func TestService_Remove(t *testing.T) { <-proc.Done() err := svc.Remove(proc.ID) - require.NoError(t, err) + requireNoError(t, err) _, err = svc.Get(proc.ID) - assert.ErrorIs(t, err, ErrProcessNotFound) + assertErrorIs(t, err, ErrProcessNotFound) }) t.Run("cannot remove running process", func(t *testing.T) { @@ -493,7 +491,7 @@ func TestService_Remove(t *testing.T) { proc, _ := svc.Start(ctx, "sleep", "10") err := svc.Remove(proc.ID) - assert.Error(t, err) + assertError(t, err) cancel() <-proc.Done() @@ -510,11 +508,11 @@ func TestService_Clear(t *testing.T) { <-proc1.Done() <-proc2.Done() - assert.Len(t, svc.List(), 2) + assertLen(t, svc.List(), 2) svc.Clear() - assert.Len(t, svc.List(), 0) + assertLen(t, svc.List(), 0) }) } @@ -526,10 +524,10 @@ func TestService_Kill(t *testing.T) { defer cancel() proc, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) err = svc.Kill(proc.ID) - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -538,14 +536,14 @@ func TestService_Kill(t *testing.T) { t.Fatal("process should have been killed") } - assert.Equal(t, StatusKilled, proc.Status) + assertEqual(t, StatusKilled, proc.Status) }) t.Run("error on unknown id", func(t *testing.T) { svc, _ := newTestService(t) err := svc.Kill("nonexistent") - assert.ErrorIs(t, err, ErrProcessNotFound) + assertErrorIs(t, err, ErrProcessNotFound) }) } @@ -555,7 +553,7 @@ func TestService_KillPID(t *testing.T) { // Ignore SIGTERM so the test proves KillPID uses a forceful signal. cmd := exec.Command("sh", "-c", "trap '' TERM; while :; do :; done") - require.NoError(t, cmd.Start()) + requireNoError(t, cmd.Start()) waitCh := make(chan error, 1) go func() { @@ -573,17 +571,17 @@ func TestService_KillPID(t *testing.T) { }) err := svc.KillPID(cmd.Process.Pid) - require.NoError(t, err) + requireNoError(t, err) select { case err := <-waitCh: - require.Error(t, err) + requireError(t, err) var exitErr *exec.ExitError - require.ErrorAs(t, err, &exitErr) + requireErrorAs(t, err, &exitErr) ws, ok := exitErr.Sys().(syscall.WaitStatus) - require.True(t, ok) - assert.True(t, ws.Signaled()) - assert.Equal(t, syscall.SIGKILL, ws.Signal()) + requireTrue(t, ok) + assertTrue(t, ws.Signaled()) + assertEqual(t, syscall.SIGKILL, ws.Signal()) case <-time.After(2 * time.Second): t.Fatal("unmanaged process should have been killed") } @@ -595,10 +593,10 @@ func TestService_Signal(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) err = svc.Signal(proc.ID, syscall.SIGTERM) - assert.NoError(t, err) + assertNoError(t, err) select { case <-proc.Done(): @@ -606,14 +604,14 @@ func TestService_Signal(t *testing.T) { t.Fatal("process should have been signalled") } - assert.Equal(t, StatusKilled, proc.Status) + assertEqual(t, StatusKilled, proc.Status) }) t.Run("signals unmanaged process by pid", func(t *testing.T) { svc, _ := newTestService(t) cmd := exec.Command("sleep", "60") - require.NoError(t, cmd.Start()) + requireNoError(t, cmd.Start()) waitCh := make(chan error, 1) go func() { @@ -631,17 +629,17 @@ func TestService_Signal(t *testing.T) { }) err := svc.SignalPID(cmd.Process.Pid, syscall.SIGTERM) - require.NoError(t, err) + requireNoError(t, err) select { case err := <-waitCh: - require.Error(t, err) + requireError(t, err) var exitErr *exec.ExitError - require.ErrorAs(t, err, &exitErr) + requireErrorAs(t, err, &exitErr) ws, ok := exitErr.Sys().(syscall.WaitStatus) - require.True(t, ok) - assert.True(t, ws.Signaled()) - assert.Equal(t, syscall.SIGTERM, ws.Signal()) + requireTrue(t, ok) + assertTrue(t, ws.Signaled()) + assertEqual(t, syscall.SIGTERM, ws.Signal()) case <-time.After(2 * time.Second): t.Fatal("unmanaged process should have been signalled") } @@ -653,19 +651,19 @@ func TestService_Output(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "captured") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() output, err := svc.Output(proc.ID) - require.NoError(t, err) - assert.Contains(t, output, "captured") + requireNoError(t, err) + assertContains(t, output, "captured") }) t.Run("error on unknown id", func(t *testing.T) { svc, _ := newTestService(t) _, err := svc.Output("nonexistent") - assert.ErrorIs(t, err, ErrProcessNotFound) + assertErrorIs(t, err, ErrProcessNotFound) }) } @@ -674,24 +672,24 @@ func TestService_Input(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) err = svc.Input(proc.ID, "service-input\n") - require.NoError(t, err) + requireNoError(t, err) err = svc.CloseStdin(proc.ID) - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.Contains(t, proc.Output(), "service-input") + assertContains(t, proc.Output(), "service-input") }) t.Run("error on unknown id", func(t *testing.T) { svc, _ := newTestService(t) err := svc.Input("nonexistent", "test") - assert.ErrorIs(t, err, ErrProcessNotFound) + assertErrorIs(t, err, ErrProcessNotFound) }) } @@ -700,10 +698,10 @@ func TestService_CloseStdin(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) err = svc.CloseStdin(proc.ID) - require.NoError(t, err) + requireNoError(t, err) select { case <-proc.Done(): @@ -716,7 +714,7 @@ func TestService_CloseStdin(t *testing.T) { svc, _ := newTestService(t) err := svc.CloseStdin("nonexistent") - assert.ErrorIs(t, err, ErrProcessNotFound) + assertErrorIs(t, err, ErrProcessNotFound) }) } @@ -725,33 +723,33 @@ func TestService_Wait(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "echo", "waited") - require.NoError(t, err) + requireNoError(t, err) info, err := svc.Wait(proc.ID) - require.NoError(t, err) - assert.Equal(t, proc.ID, info.ID) - assert.Equal(t, StatusExited, info.Status) - assert.Equal(t, 0, info.ExitCode) + requireNoError(t, err) + assertEqual(t, proc.ID, info.ID) + assertEqual(t, StatusExited, info.Status) + assertEqual(t, 0, info.ExitCode) }) t.Run("returns error on unknown id", func(t *testing.T) { svc, _ := newTestService(t) _, err := svc.Wait("nonexistent") - assert.ErrorIs(t, err, ErrProcessNotFound) + assertErrorIs(t, err, ErrProcessNotFound) }) t.Run("returns info alongside failure", func(t *testing.T) { svc, _ := newTestService(t) proc, err := svc.Start(context.Background(), "sh", "-c", "exit 7") - require.NoError(t, err) + requireNoError(t, err) info, err := svc.Wait(proc.ID) - require.Error(t, err) - assert.Equal(t, proc.ID, info.ID) - assert.Equal(t, StatusExited, info.Status) - assert.Equal(t, 7, info.ExitCode) + requireError(t, err) + assertEqual(t, proc.ID, info.ID) + assertEqual(t, StatusExited, info.Status) + assertEqual(t, 7, info.ExitCode) }) } @@ -763,14 +761,14 @@ func TestService_OnShutdown(t *testing.T) { defer cancel() proc1, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) proc2, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) - assert.True(t, proc1.IsRunning()) - assert.True(t, proc2.IsRunning()) + assertTrue(t, proc1.IsRunning()) + assertTrue(t, proc2.IsRunning()) - assert.NoError(t, resultErr(svc.OnShutdown(context.Background()))) + assertNoError(t, resultErr(svc.OnShutdown(context.Background()))) select { case <-proc1.Done(): @@ -792,11 +790,11 @@ func TestService_OnShutdown(t *testing.T) { Args: []string{"-c", "trap '' TERM; sleep 60"}, GracePeriod: 5 * time.Second, }) - require.NoError(t, err) - require.True(t, proc.IsRunning()) + requireNoError(t, err) + requireTrue(t, proc.IsRunning()) start := time.Now() - require.NoError(t, resultErr(svc.OnShutdown(context.Background()))) + requireNoError(t, resultErr(svc.OnShutdown(context.Background()))) select { case <-proc.Done(): @@ -804,8 +802,8 @@ func TestService_OnShutdown(t *testing.T) { t.Fatal("process should have been killed immediately on shutdown") } - assert.Less(t, time.Since(start), 2*time.Second) - assert.Equal(t, StatusKilled, proc.Status) + assertLess(t, time.Since(start), 2*time.Second) + assertEqual(t, StatusKilled, proc.Status) }) } @@ -813,19 +811,19 @@ func TestService_OnStartup(t *testing.T) { t.Run("registers detached process.start action", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) ctx, cancel := context.WithCancel(context.Background()) result := c.Action("process.start").Run(ctx, framework.NewOptions( framework.Option{Key: "command", Value: "sleep"}, framework.Option{Key: "args", Value: []string{"0.1"}}, )) - require.True(t, result.OK) + requireTrue(t, result.OK) id, ok := result.Value.(string) - require.True(t, ok) + requireTrue(t, ok) proc, err := svc.Get(id) - require.NoError(t, err) + requireNoError(t, err) cancel() @@ -835,54 +833,54 @@ func TestService_OnStartup(t *testing.T) { t.Fatal("detached action-started process should complete") } - assert.Equal(t, StatusExited, proc.Status) - assert.Equal(t, 0, proc.ExitCode) + assertEqual(t, StatusExited, proc.Status) + assertEqual(t, 0, proc.ExitCode) }) t.Run("registers process.start task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) result := performTask(svc, c, TaskProcessStart{ Command: "sleep", Args: []string{"1"}, }) - require.True(t, result.OK) + requireTrue(t, result.OK) info, ok := result.Value.(Info) - require.True(t, ok) - assert.NotEmpty(t, info.ID) - assert.Equal(t, StatusRunning, info.Status) - assert.True(t, info.Running) + requireTrue(t, ok) + assertNotEmpty(t, info.ID) + assertEqual(t, StatusRunning, info.Status) + assertTrue(t, info.Running) proc, err := svc.Get(info.ID) - require.NoError(t, err) - assert.True(t, proc.IsRunning()) + requireNoError(t, err) + assertTrue(t, proc.IsRunning()) <-proc.Done() - assert.Equal(t, StatusExited, proc.Status) + assertEqual(t, StatusExited, proc.Status) }) t.Run("registers process.run task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) result := performTask(svc, c, TaskProcessRun{ Command: "echo", Args: []string{"action-run"}, }) - require.True(t, result.OK) - assert.Contains(t, result.Value.(string), "action-run") + requireTrue(t, result.OK) + assertContains(t, result.Value.(string), "action-run") }) t.Run("forwards task execution options", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) result := performTask(svc, c, TaskProcessRun{ Command: "sleep", @@ -891,18 +889,18 @@ func TestService_OnStartup(t *testing.T) { GracePeriod: 50 * time.Millisecond, }) - require.False(t, result.OK) - assert.Nil(t, result.Value) + requireFalse(t, result.OK) + assertNil(t, result.Value) }) t.Run("registers process.kill task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) - require.True(t, proc.IsRunning()) + requireNoError(t, err) + requireTrue(t, proc.IsRunning()) var killed []ActionProcessKilled c.RegisterAction(func(cc *framework.Core, msg framework.Message) framework.Result { @@ -913,7 +911,7 @@ func TestService_OnStartup(t *testing.T) { }) result := performTask(svc, c, TaskProcessKill{PID: proc.Info().PID}) - require.True(t, result.OK) + requireTrue(t, result.OK) select { case <-proc.Done(): @@ -921,25 +919,25 @@ func TestService_OnStartup(t *testing.T) { t.Fatal("process should have been killed by pid") } - assert.Equal(t, StatusKilled, proc.Status) - require.Len(t, killed, 1) - assert.Equal(t, proc.ID, killed[0].ID) - assert.NotEmpty(t, killed[0].Signal) + assertEqual(t, StatusKilled, proc.Status) + requireLen(t, killed, 1) + assertEqual(t, proc.ID, killed[0].ID) + assertNotEmpty(t, killed[0].Signal) }) t.Run("registers process.signal task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) result := performTask(svc, c, TaskProcessSignal{ ID: proc.ID, Signal: syscall.SIGTERM, }) - require.True(t, result.OK) + requireTrue(t, result.OK) select { case <-proc.Done(): @@ -947,27 +945,27 @@ func TestService_OnStartup(t *testing.T) { t.Fatal("process should have been signalled through core") } - assert.Equal(t, StatusKilled, proc.Status) + assertEqual(t, StatusKilled, proc.Status) }) t.Run("allows signal zero liveness checks", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) ctx, cancel := context.WithCancel(context.Background()) defer cancel() proc, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) result := performTask(svc, c, TaskProcessSignal{ ID: proc.ID, Signal: syscall.Signal(0), }) - require.True(t, result.OK) + requireTrue(t, result.OK) - assert.True(t, proc.IsRunning()) + assertTrue(t, proc.IsRunning()) cancel() <-proc.Done() @@ -976,7 +974,7 @@ func TestService_OnStartup(t *testing.T) { t.Run("signal zero does not kill process groups", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.StartWithOptions(context.Background(), RunOptions{ Command: "sh", @@ -984,80 +982,80 @@ func TestService_OnStartup(t *testing.T) { Detach: true, KillGroup: true, }) - require.NoError(t, err) + requireNoError(t, err) result := performTask(svc, c, TaskProcessSignal{ ID: proc.ID, Signal: syscall.Signal(0), }) - require.True(t, result.OK) + requireTrue(t, result.OK) time.Sleep(300 * time.Millisecond) - assert.True(t, proc.IsRunning()) + assertTrue(t, proc.IsRunning()) err = proc.Kill() - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() }) t.Run("registers process.wait task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "echo", "action-wait") - require.NoError(t, err) + requireNoError(t, err) result := performTask(svc, c, TaskProcessWait{ID: proc.ID}) - require.True(t, result.OK) + requireTrue(t, result.OK) info, ok := result.Value.(Info) - require.True(t, ok) - assert.Equal(t, proc.ID, info.ID) - assert.Equal(t, StatusExited, info.Status) - assert.Equal(t, 0, info.ExitCode) + requireTrue(t, ok) + assertEqual(t, proc.ID, info.ID) + assertEqual(t, StatusExited, info.Status) + assertEqual(t, 0, info.ExitCode) }) t.Run("preserves final snapshot when process.wait task fails", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "sh", "-c", "exit 7") - require.NoError(t, err) + requireNoError(t, err) result := performTask(svc, c, TaskProcessWait{ID: proc.ID}) - require.True(t, result.OK) + requireTrue(t, result.OK) errValue, ok := result.Value.(error) - require.True(t, ok) + requireTrue(t, ok) var waitErr *TaskProcessWaitError - require.ErrorAs(t, errValue, &waitErr) - assert.Contains(t, waitErr.Error(), "process exited with code 7") - assert.Equal(t, proc.ID, waitErr.Info.ID) - assert.Equal(t, StatusExited, waitErr.Info.Status) - assert.Equal(t, 7, waitErr.Info.ExitCode) + requireErrorAs(t, errValue, &waitErr) + assertContains(t, waitErr.Error(), "process exited with code 7") + assertEqual(t, proc.ID, waitErr.Info.ID) + assertEqual(t, StatusExited, waitErr.Info.Status) + assertEqual(t, 7, waitErr.Info.ExitCode) }) t.Run("registers process.list task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) ctx, cancel := context.WithCancel(context.Background()) defer cancel() proc, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) result := performTask(svc, c, TaskProcessList{RunningOnly: true}) - require.True(t, result.OK) + requireTrue(t, result.OK) infos, ok := result.Value.([]Info) - require.True(t, ok) - require.Len(t, infos, 1) - assert.Equal(t, proc.ID, infos[0].ID) - assert.True(t, infos[0].Running) + requireTrue(t, ok) + requireLen(t, infos, 1) + assertEqual(t, proc.ID, infos[0].ID) + assertTrue(t, infos[0].Running) cancel() <-proc.Done() @@ -1066,115 +1064,115 @@ func TestService_OnStartup(t *testing.T) { t.Run("registers process.get task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "echo", "snapshot") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() result := performTask(svc, c, TaskProcessGet{ID: proc.ID}) - require.True(t, result.OK) + requireTrue(t, result.OK) info, ok := result.Value.(Info) - require.True(t, ok) - assert.Equal(t, proc.ID, info.ID) - assert.Equal(t, proc.Command, info.Command) - assert.Equal(t, proc.Args, info.Args) - assert.Equal(t, proc.Status, info.Status) - assert.Equal(t, proc.ExitCode, info.ExitCode) - assert.Equal(t, proc.Info().PID, info.PID) + requireTrue(t, ok) + assertEqual(t, proc.ID, info.ID) + assertEqual(t, proc.Command, info.Command) + assertEqual(t, proc.Args, info.Args) + assertEqual(t, proc.Status, info.Status) + assertEqual(t, proc.ExitCode, info.ExitCode) + assertEqual(t, proc.Info().PID, info.PID) }) t.Run("registers process.remove task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "echo", "remove-through-core") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() result := performTask(svc, c, TaskProcessRemove{ID: proc.ID}) - require.True(t, result.OK) + requireTrue(t, result.OK) _, err = svc.Get(proc.ID) - assert.ErrorIs(t, err, ErrProcessNotFound) + assertErrorIs(t, err, ErrProcessNotFound) }) t.Run("registers process.clear task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) first, err := svc.Start(context.Background(), "echo", "clear-through-core-1") - require.NoError(t, err) + requireNoError(t, err) second, err := svc.Start(context.Background(), "echo", "clear-through-core-2") - require.NoError(t, err) + requireNoError(t, err) <-first.Done() <-second.Done() - require.Len(t, svc.List(), 2) + requireLen(t, svc.List(), 2) result := performTask(svc, c, TaskProcessClear{}) - require.True(t, result.OK) - assert.Len(t, svc.List(), 0) + requireTrue(t, result.OK) + assertLen(t, svc.List(), 0) }) t.Run("registers process.output task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "echo", "snapshot-output") - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() result := performTask(svc, c, TaskProcessOutput{ID: proc.ID}) - require.True(t, result.OK) + requireTrue(t, result.OK) output, ok := result.Value.(string) - require.True(t, ok) - assert.Contains(t, output, "snapshot-output") + requireTrue(t, ok) + assertContains(t, output, "snapshot-output") }) t.Run("registers process.input task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) result := performTask(svc, c, TaskProcessInput{ ID: proc.ID, Input: "typed-through-core\n", }) - require.True(t, result.OK) + requireTrue(t, result.OK) err = proc.CloseStdin() - require.NoError(t, err) + requireNoError(t, err) <-proc.Done() - assert.Contains(t, proc.Output(), "typed-through-core") + assertContains(t, proc.Output(), "typed-through-core") }) t.Run("registers process.close_stdin task", func(t *testing.T) { svc, c := newTestService(t) - require.NoError(t, resultErr(svc.OnStartup(context.Background()))) + requireNoError(t, resultErr(svc.OnStartup(context.Background()))) proc, err := svc.Start(context.Background(), "cat") - require.NoError(t, err) + requireNoError(t, err) result := performTask(svc, c, TaskProcessInput{ ID: proc.ID, Input: "close-through-core\n", }) - require.True(t, result.OK) + requireTrue(t, result.OK) result = performTask(svc, c, TaskProcessCloseStdin{ID: proc.ID}) - require.True(t, result.OK) + requireTrue(t, result.OK) select { case <-proc.Done(): @@ -1182,7 +1180,7 @@ func TestService_OnStartup(t *testing.T) { t.Fatal("process should have exited after stdin was closed") } - assert.Contains(t, proc.Output(), "close-through-core") + assertContains(t, proc.Output(), "close-through-core") }) } @@ -1194,8 +1192,8 @@ func TestService_RunWithOptions(t *testing.T) { Command: "echo", Args: []string{"opts-test"}, }) - require.NoError(t, err) - assert.Contains(t, output, "opts-test") + requireNoError(t, err) + assertContains(t, output, "opts-test") }) t.Run("returns error on failure", func(t *testing.T) { @@ -1205,8 +1203,8 @@ func TestService_RunWithOptions(t *testing.T) { Command: "sh", Args: []string{"-c", "exit 2"}, }) - assert.Error(t, err) - assert.Contains(t, err.Error(), "exited with code 2") + assertError(t, err) + assertContains(t, err.Error(), "exited with code 2") }) t.Run("rejects nil context", func(t *testing.T) { @@ -1215,8 +1213,8 @@ func TestService_RunWithOptions(t *testing.T) { _, err := svc.RunWithOptions(nil, RunOptions{ Command: "echo", }) - require.Error(t, err) - assert.ErrorIs(t, err, ErrContextRequired) + requireError(t, err) + assertErrorIs(t, err, ErrContextRequired) }) } @@ -1228,23 +1226,23 @@ func TestService_Running(t *testing.T) { defer cancel() proc1, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) doneProc, err := svc.Start(context.Background(), "echo", "done") - require.NoError(t, err) + requireNoError(t, err) <-doneProc.Done() running := svc.Running() - assert.Len(t, running, 1) - assert.Equal(t, proc1.ID, running[0].ID) + assertLen(t, running, 1) + assertEqual(t, proc1.ID, running[0].ID) proc2, err := svc.Start(ctx, "sleep", "60") - require.NoError(t, err) + requireNoError(t, err) running = svc.Running() - assert.Len(t, running, 2) - assert.Equal(t, proc1.ID, running[0].ID) - assert.Equal(t, proc2.ID, running[1].ID) + assertLen(t, running, 2) + assertEqual(t, proc1.ID, running[0].ID) + assertEqual(t, proc2.ID, running[1].ID) cancel() <-proc1.Done()