package utils import ( "sync" "sync/atomic" "testing" "time" "github.com/tevino/abool" ) func TestOnceAgain(t *testing.T) { t.Parallel() oa := OnceAgain{} executed := abool.New() var testWg sync.WaitGroup // One execution should gobble up the whole batch. for i := 0; i < 10; i++ { testWg.Add(100) for i := 0; i < 100; i++ { go func() { oa.Do(func() { if !executed.SetToIf(false, true) { t.Errorf("concurrent execution!") } time.Sleep(10 * time.Millisecond) }) testWg.Done() }() } testWg.Wait() executed.UnSet() // reset check } // Continuous use with re-execution. // Choose values so that about 10 executions are expected var execs uint32 testWg.Add(100) for i := 0; i < 100; i++ { go func() { oa.Do(func() { atomic.AddUint32(&execs, 1) time.Sleep(10 * time.Millisecond) }) testWg.Done() }() time.Sleep(1 * time.Millisecond) } testWg.Wait() if execs <= 8 { t.Errorf("unexpected low exec count: %d", execs) } if execs >= 12 { t.Errorf("unexpected high exec count: %d", execs) } }