diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-07-15 15:47:03 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-07-20 07:32:13 +0300 |
commit | 52f009b5d14ee7dac418498c1b389cb11d43cf80 (patch) | |
tree | 67edf1cf9b654e588013363e02396ad6d99e16ce | |
parent | cead6a0e5f2cf0ac6ad8e32d42d9dce71d424a3f (diff) |
command: Verify that finalizers run when expected
Add tests to verify that command finalizers work as expected.
-rw-r--r-- | internal/command/command_test.go | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/internal/command/command_test.go b/internal/command/command_test.go index 397b32456..db491b0fc 100644 --- a/internal/command/command_test.go +++ b/internal/command/command_test.go @@ -460,3 +460,56 @@ gitaly_command_spawn_token_acquiring_seconds_total{cmd="echo",git_version="",grp ), ) } + +func TestCommand_withFinalizer(t *testing.T) { + t.Parallel() + + t.Run("context cancellation runs finalizer", func(t *testing.T) { + ctx, cancel := context.WithCancel(testhelper.Context(t)) + + finalizerCh := make(chan struct{}) + _, err := New(ctx, exec.Command("echo"), WithFinalizer(func(*Command) { + close(finalizerCh) + })) + require.NoError(t, err) + + cancel() + + <-finalizerCh + }) + + t.Run("Wait runs finalizer", func(t *testing.T) { + ctx := testhelper.Context(t) + + finalizerCh := make(chan struct{}) + cmd, err := New(ctx, exec.Command("echo"), WithFinalizer(func(*Command) { + close(finalizerCh) + })) + require.NoError(t, err) + + require.NoError(t, cmd.Wait()) + + <-finalizerCh + }) + + t.Run("process exit does not run finalizer", func(t *testing.T) { + ctx := testhelper.Context(t) + + finalizerCh := make(chan struct{}) + _, err := New(ctx, exec.Command("echo"), WithFinalizer(func(*Command) { + close(finalizerCh) + })) + require.NoError(t, err) + + select { + case <-finalizerCh: + // Command finalizers should only be running when we have either explicitly + // called `Wait()` on the command, or when the context has been cancelled. + // Otherwise we may run into the case where finalizers have already been ran + // on the exited process even though we may still be busy handling the + // output of that command, which may result in weird races. + require.FailNow(t, "finalizer should not have been ran") + case <-time.After(50 * time.Millisecond): + } + }) +} |