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

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  func TestStablePoolRealWorld(t *testing.T) {
    13  	t.Parallel()
    14  	// "real world" simulation
    15  
    16  	cnt := 0
    17  	testPool := &StablePool{
    18  		New: func() interface{} {
    19  			cnt++
    20  			return cnt
    21  		},
    22  	}
    23  	var testWg sync.WaitGroup
    24  	var testWorkerWg sync.WaitGroup
    25  
    26  	// for i := 0; i < 100; i++ {
    27  	// 	cnt++
    28  	// 	testPool.Put(cnt)
    29  	// }
    30  	for i := 0; i < 100; i++ {
    31  		// block round
    32  		testWg.Add(1)
    33  		// add workers
    34  		testWorkerWg.Add(100)
    35  		for j := 0; j < 100; j++ {
    36  			k := j
    37  			go func() {
    38  				// wait for round to start
    39  				testWg.Wait()
    40  				// get value
    41  				x := testPool.Get()
    42  				// fmt.Println(x)
    43  				// "work"
    44  				time.Sleep(5 * time.Microsecond)
    45  				// re-insert 99%
    46  				if k%100 > 0 {
    47  					testPool.Put(x)
    48  				}
    49  				// mark as finished
    50  				testWorkerWg.Done()
    51  			}()
    52  		}
    53  		// start round
    54  		testWg.Done()
    55  		// wait for round to finish
    56  		testWorkerWg.Wait()
    57  	}
    58  	t.Logf("real world simulation: cnt=%d p.cnt=%d p.max=%d\n", cnt, testPool.Size(), testPool.Max())
    59  	assert.GreaterOrEqual(t, 200, cnt, "should not use more than 200 values")
    60  	assert.GreaterOrEqual(t, 100, testPool.Max(), "pool should have at most this max size")
    61  
    62  	// optimal usage test
    63  
    64  	optPool := &StablePool{}
    65  	for i := 0; i < 1000; i++ {
    66  		for j := 0; j < 100; j++ {
    67  			optPool.Put(j)
    68  		}
    69  		for k := 0; k < 100; k++ {
    70  			assert.Equal(t, k, optPool.Get(), "should match")
    71  		}
    72  	}
    73  	assert.Equal(t, 100, optPool.Max(), "pool should have exactly this max size")
    74  }
    75  
    76  func TestStablePoolFuzzing(t *testing.T) {
    77  	t.Parallel()
    78  	// fuzzing test
    79  
    80  	fuzzPool := &StablePool{}
    81  	var fuzzWg sync.WaitGroup
    82  	var fuzzWorkerWg sync.WaitGroup
    83  	// start goroutines and wait
    84  	fuzzWg.Add(1)
    85  	for i := 0; i < 1000; i++ {
    86  		fuzzWorkerWg.Add(2)
    87  		j := i
    88  		go func() {
    89  			fuzzWg.Wait()
    90  			fuzzPool.Put(j)
    91  			fuzzWorkerWg.Done()
    92  		}()
    93  		go func() {
    94  			fuzzWg.Wait()
    95  			fmt.Print(fuzzPool.Get())
    96  			fuzzWorkerWg.Done()
    97  		}()
    98  	}
    99  	// kick off
   100  	fuzzWg.Done()
   101  	// wait for all to finish
   102  	fuzzWorkerWg.Wait()
   103  }
   104  
   105  func TestStablePoolBreaking(t *testing.T) {
   106  	t.Parallel()
   107  	// try to break it
   108  
   109  	breakPool := &StablePool{}
   110  	for i := 0; i < 10; i++ {
   111  		for j := 0; j < 100; j++ {
   112  			breakPool.Put(nil)
   113  			breakPool.Put(j)
   114  			breakPool.Put(nil)
   115  		}
   116  		for k := 0; k < 100; k++ {
   117  			assert.Equal(t, k, breakPool.Get(), "should match")
   118  		}
   119  	}
   120  }