package lifecycle_test import ( "context" "log/slog" "sync" "testing" "time" "github.com/stretchr/testify/require" "sneak.berlin/go/webhooker/internal/lifecycle" ) // waitTimeout is the stop budget the timeout case gives a // goroutine that never returns. The test's own patience is the // go test deadline, so the only thing this value affects is how // long the case takes. const waitTimeout = 100 * time.Millisecond func discardLogger() *slog.Logger { return slog.New(slog.DiscardHandler) } func TestWaitForShutdown_DrainedGroup(t *testing.T) { t.Parallel() var wg sync.WaitGroup wg.Go(func() {}) require.NoError( t, lifecycle.WaitForShutdown( context.Background(), discardLogger(), "test component", &wg, ), ) } func TestWaitForShutdown_ContextExpires(t *testing.T) { t.Parallel() release := make(chan struct{}) t.Cleanup(func() { close(release) }) var wg sync.WaitGroup wg.Go(func() { <-release }) ctx, cancel := context.WithTimeout( context.Background(), waitTimeout, ) defer cancel() err := lifecycle.WaitForShutdown( ctx, discardLogger(), "test component", &wg, ) require.ErrorIs(t, err, context.DeadlineExceeded) require.ErrorContains(t, err, "test component") }