github.com/safing/portbase@v0.19.5/utils/onceagain_test.go (about)

     1  package utils
     2  
     3  import (
     4  	"sync"
     5  	"sync/atomic"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/tevino/abool"
    10  )
    11  
    12  func TestOnceAgain(t *testing.T) {
    13  	t.Parallel()
    14  
    15  	oa := OnceAgain{}
    16  	executed := abool.New()
    17  	var testWg sync.WaitGroup
    18  
    19  	// One execution should gobble up the whole batch.
    20  	for i := 0; i < 10; i++ {
    21  		testWg.Add(100)
    22  		for i := 0; i < 100; i++ {
    23  			go func() {
    24  				oa.Do(func() {
    25  					if !executed.SetToIf(false, true) {
    26  						t.Errorf("concurrent execution!")
    27  					}
    28  					time.Sleep(10 * time.Millisecond)
    29  				})
    30  				testWg.Done()
    31  			}()
    32  		}
    33  		testWg.Wait()
    34  		executed.UnSet() // reset check
    35  	}
    36  
    37  	// Continuous use with re-execution.
    38  	// Choose values so that about 10 executions are expected
    39  	var execs uint32
    40  	testWg.Add(100)
    41  	for i := 0; i < 100; i++ {
    42  		go func() {
    43  			oa.Do(func() {
    44  				atomic.AddUint32(&execs, 1)
    45  				time.Sleep(10 * time.Millisecond)
    46  			})
    47  			testWg.Done()
    48  		}()
    49  
    50  		time.Sleep(1 * time.Millisecond)
    51  	}
    52  
    53  	testWg.Wait()
    54  	if execs <= 8 {
    55  		t.Errorf("unexpected low exec count: %d", execs)
    56  	}
    57  	if execs >= 12 {
    58  		t.Errorf("unexpected high exec count: %d", execs)
    59  	}
    60  }