github.com/prysmaticlabs/prysm@v1.4.4/shared/asyncutil/debounce_test.go (about) 1 package asyncutil 2 3 import ( 4 "context" 5 "sync" 6 "testing" 7 "time" 8 9 "github.com/prysmaticlabs/prysm/shared/testutil" 10 "github.com/prysmaticlabs/prysm/shared/testutil/assert" 11 "github.com/prysmaticlabs/prysm/shared/testutil/require" 12 ) 13 14 func TestDebounce_NoEvents(t *testing.T) { 15 eventsChan := make(chan interface{}, 100) 16 ctx, cancel := context.WithCancel(context.Background()) 17 interval := time.Second 18 timesHandled := 0 19 wg := &sync.WaitGroup{} 20 wg.Add(1) 21 go func() { 22 time.AfterFunc(interval, func() { 23 cancel() 24 }) 25 }() 26 go func() { 27 Debounce(ctx, interval, eventsChan, func(event interface{}) { 28 timesHandled++ 29 }) 30 wg.Done() 31 }() 32 if testutil.WaitTimeout(wg, interval*2) { 33 t.Fatalf("Test should have exited by now, timed out") 34 } 35 assert.Equal(t, 0, timesHandled, "Wrong number of handled calls") 36 } 37 38 func TestDebounce_CtxClosing(t *testing.T) { 39 eventsChan := make(chan interface{}, 100) 40 ctx, cancel := context.WithCancel(context.Background()) 41 interval := time.Second 42 timesHandled := 0 43 wg := &sync.WaitGroup{} 44 wg.Add(1) 45 go func() { 46 ticker := time.NewTicker(time.Millisecond * 100) 47 defer ticker.Stop() 48 for { 49 select { 50 case <-ctx.Done(): 51 return 52 case <-ticker.C: 53 eventsChan <- struct{}{} 54 } 55 } 56 }() 57 go func() { 58 time.AfterFunc(interval, func() { 59 cancel() 60 }) 61 }() 62 go func() { 63 Debounce(ctx, interval, eventsChan, func(event interface{}) { 64 timesHandled++ 65 }) 66 wg.Done() 67 }() 68 if testutil.WaitTimeout(wg, interval*2) { 69 t.Fatalf("Test should have exited by now, timed out") 70 } 71 assert.Equal(t, 0, timesHandled, "Wrong number of handled calls") 72 } 73 74 func TestDebounce_SingleHandlerInvocation(t *testing.T) { 75 eventsChan := make(chan interface{}, 100) 76 ctx, cancel := context.WithCancel(context.Background()) 77 interval := time.Second 78 timesHandled := 0 79 go Debounce(ctx, interval, eventsChan, func(event interface{}) { 80 timesHandled++ 81 }) 82 for i := 0; i < 100; i++ { 83 eventsChan <- struct{}{} 84 } 85 // We should expect 100 rapid fire changes to only have caused 86 // 1 handler to trigger after the debouncing period. 87 time.Sleep(interval * 2) 88 assert.Equal(t, 1, timesHandled, "Wrong number of handled calls") 89 cancel() 90 } 91 92 func TestDebounce_MultipleHandlerInvocation(t *testing.T) { 93 eventsChan := make(chan interface{}, 100) 94 ctx, cancel := context.WithCancel(context.Background()) 95 interval := time.Second 96 timesHandled := 0 97 go Debounce(ctx, interval, eventsChan, func(event interface{}) { 98 timesHandled++ 99 }) 100 for i := 0; i < 100; i++ { 101 eventsChan <- struct{}{} 102 } 103 require.Equal(t, 0, timesHandled, "Events must prevent from handler execution") 104 105 // By this time the first event should be triggered. 106 time.Sleep(2 * time.Second) 107 assert.Equal(t, 1, timesHandled, "Wrong number of handled calls") 108 109 // Second event. 110 eventsChan <- struct{}{} 111 time.Sleep(2 * time.Second) 112 assert.Equal(t, 2, timesHandled, "Wrong number of handled calls") 113 114 cancel() 115 }