func testPool(t *testing.T, nWorkers int, nJobs int, shouldCancel bool) { clock := times.NewMockedClock() waitTimeout := 100 * time.Millisecond // the "After" method may be called even if shouldCancel is false // because we call pool shutdown at the end of the test. clock.On("After", waitTimeout).Return(clock.AfterChannel) shutdownTimeout := 10000 * time.Millisecond clock.On("After", shutdownTimeout).Return(clock.AfterChannel) pool := NewPool(logger, nWorkers, waitTimeout, clock) var wg sync.WaitGroup for i := 0; i < nJobs; i++ { jobID := fmt.Sprintf("job-%d", i) _ = jobID wg.Add(1) go func() { defer wg.Done() exercisePool(t, pool, jobID, shouldCancel) }() } wg.Wait() // give time for (some of) the jobs to complete normally time.Sleep(10 * time.Millisecond) // send cancel signal to all running jobs and wait to finish assert.True(t, pool.ShutdownAndWait(shutdownTimeout)) // Not verifying clock.After(waitTimeout) here. Refer to proc.go. We can't guarantee that 'doneChan' is not set the // first time waitEither(doneChan, clock.After) is checked. clock.AssertCalled(t, "After", shutdownTimeout) }
func createTestCase(t *testing.T, innerFunctionPanics bool) TestCase { // create job jobState := make(chan bool) job := func() { jobState <- true if innerFunctionPanics { panic("panic") } jobState <- false } return TestCase{ Clock: times.NewMockedClock(), CancelFlag: NewChanneledCancelFlag(), CancelWaitMillis: time.Duration(100 * time.Millisecond), InnerFunctionPanics: innerFunctionPanics, innerFunction: job, innerFunctionState: jobState, testFunctionState: make(chan bool), t: t, } }