diff --git a/test/utils/ktesting/main_test.go b/test/utils/ktesting/main_test.go index dcab727fc43..17c461f6610 100644 --- a/test/utils/ktesting/main_test.go +++ b/test/utils/ktesting/main_test.go @@ -29,6 +29,10 @@ func TestMain(m *testing.M) { // Bail out early when -help was given as parameter. flag.Parse() + // The unit tests assume that they run as a unit test, with progress reporting enabled. + // This leaks a goroutine, so we have to do it before IgnoreCurrent. + initSignals() + // Must be called *before* creating new goroutines. goleakOpts := []goleak.Option{ goleak.IgnoreCurrent(), diff --git a/test/utils/ktesting/signals.go b/test/utils/ktesting/signals.go index 1a9b9715fdc..b6ac765f259 100644 --- a/test/utils/ktesting/signals.go +++ b/test/utils/ktesting/signals.go @@ -27,7 +27,7 @@ import ( ) var ( - interruptCtx context.Context + interruptCtx = context.Background() defaultProgressReporter = new(progressReporter) defaultSignalChannel chan os.Signal @@ -39,10 +39,11 @@ type ginkgoReporter interface { AttachProgressReporter(reporter func() string) func() } -func init() { - // Setting up signals is intentionally done in an init function because - // then importing ktesting in a unit or integration test is sufficient - // to activate the signal behavior. +// initSignals is invoked once when ktesting is used for a `go test` unit test. +// It implements support for triggering a progress report in +// a running test when sending it a USR1 signal, similar to the corresponding +// Ginkgo feature. +func initSignals() { signalCtx, _ := signal.NotifyContext(context.Background(), os.Interrupt) cancelCtx, cancel := context.WithCancelCause(context.Background()) go func() { @@ -70,6 +71,8 @@ func init() { go defaultProgressReporter.run(interruptCtx, defaultSignalChannel) } +var initSignalsOnce sync.Once + type progressReporter struct { mutex sync.Mutex reporterCounter int64 diff --git a/test/utils/ktesting/tcontext.go b/test/utils/ktesting/tcontext.go index 8bc639c5af7..97960b67c0c 100644 --- a/test/utils/ktesting/tcontext.go +++ b/test/utils/ktesting/tcontext.go @@ -162,6 +162,15 @@ func Init(tb TB, opts ...InitOption) TContext { tCtx.Cleanup(func() { tCtx.Cancel(cleanupErr(tCtx.Name()).Error()) }) + + // Only enable signal handling if we are sure that we are not + // in a Ginkgo suite. Only structs from the testing package + // can implement this interface because it contains an "internal" + // method, so this has to run under `go test`. + if _, ok := tb.(testing.TB); ok { + initSignalsOnce.Do(initSignals) + } + return tCtx }