github.com/xmidt-org/webpa-common@v1.11.9/capacitor/capacitor_test.go (about) 1 package capacitor 2 3 import ( 4 "fmt" 5 "sync" 6 "sync/atomic" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/mock" 12 "github.com/stretchr/testify/require" 13 "github.com/xmidt-org/webpa-common/clock/clocktest" 14 ) 15 16 func ExampleBasicUsage() { 17 var ( 18 c = New() 19 w = new(sync.WaitGroup) 20 ) 21 22 w.Add(1) 23 24 // this may or may not be executed, depending on timing of the machine where this is run 25 c.Submit(func() {}) 26 27 // we'll wait until this is executed 28 c.Submit(func() { 29 fmt.Println("Discharged") 30 w.Done() 31 }) 32 33 w.Wait() 34 35 // Output: 36 // Discharged 37 } 38 39 func testWithDelayDefault(t *testing.T) { 40 var ( 41 assert = assert.New(t) 42 c = new(capacitor) 43 ) 44 45 WithDelay(0)(c) 46 assert.Equal(DefaultDelay, c.delay) 47 } 48 49 func testWithDelayCustom(t *testing.T) { 50 var ( 51 assert = assert.New(t) 52 c = new(capacitor) 53 ) 54 55 WithDelay(31 * time.Minute)(c) 56 assert.Equal(31*time.Minute, c.delay) 57 } 58 59 func TestWithDelay(t *testing.T) { 60 t.Run("Default", testWithDelayDefault) 61 t.Run("Custom", testWithDelayCustom) 62 } 63 64 func testWithClockDefault(t *testing.T) { 65 var ( 66 assert = assert.New(t) 67 c = new(capacitor) 68 ) 69 70 WithClock(nil)(c) 71 assert.NotNil(c.c) 72 } 73 74 func testWithClockCustom(t *testing.T) { 75 var ( 76 assert = assert.New(t) 77 cl = new(clocktest.Mock) 78 c = new(capacitor) 79 ) 80 81 WithClock(cl)(c) 82 assert.Equal(cl, c.c) 83 } 84 85 func TestWithClock(t *testing.T) { 86 t.Run("Default", testWithClockDefault) 87 t.Run("Custom", testWithClockCustom) 88 } 89 90 func testCapacitorSubmit(t *testing.T) { 91 var ( 92 assert = assert.New(t) 93 require = require.New(t) 94 95 stopped = make(chan struct{}) 96 calls int32 97 f = func() { 98 atomic.AddInt32(&calls, 1) 99 } 100 101 cl = new(clocktest.Mock) 102 timer = new(clocktest.MockTimer) 103 trigger = make(chan time.Time, 1) 104 c = New(WithDelay(time.Minute), WithClock(cl)) 105 ) 106 107 require.NotNil(c) 108 cl.OnNewTimer(time.Minute, timer).Once() 109 timer.OnC(trigger).Once() 110 timer.OnStop(true).Once().Run(func(mock.Arguments) { 111 close(stopped) 112 }) 113 114 for i := 0; i < 10; i++ { 115 c.Submit(f) 116 } 117 118 trigger <- time.Time{} 119 120 select { 121 case <-stopped: 122 // passing 123 case <-time.After(5 * time.Second): 124 assert.Fail("The capacitor did not discharge properly") 125 } 126 127 cl.AssertExpectations(t) 128 timer.AssertExpectations(t) 129 assert.Equal(int32(1), atomic.LoadInt32(&calls)) 130 } 131 132 func testCapacitorDischarge(t *testing.T) { 133 var ( 134 assert = assert.New(t) 135 require = require.New(t) 136 137 stopped = make(chan struct{}) 138 calls int32 139 f = func() { 140 atomic.AddInt32(&calls, 1) 141 } 142 143 cl = new(clocktest.Mock) 144 timer = new(clocktest.MockTimer) 145 trigger = make(chan time.Time) 146 c = New(WithDelay(time.Minute), WithClock(cl)) 147 ) 148 149 require.NotNil(c) 150 cl.OnNewTimer(time.Minute, timer).Once() 151 timer.OnC(trigger).Once() 152 timer.OnStop(true).Once().Run(func(mock.Arguments) { 153 close(stopped) 154 }) 155 156 for i := 0; i < 10; i++ { 157 c.Submit(f) 158 } 159 160 c.Discharge() 161 c.Discharge() // idempotent 162 163 select { 164 case <-stopped: 165 // passing 166 case <-time.After(5 * time.Second): 167 assert.Fail("The capacitor did not discharge properly") 168 } 169 170 cl.AssertExpectations(t) 171 timer.AssertExpectations(t) 172 assert.Equal(int32(1), atomic.LoadInt32(&calls)) 173 } 174 175 func testCapacitorCancel(t *testing.T) { 176 var ( 177 assert = assert.New(t) 178 require = require.New(t) 179 180 stopped = make(chan struct{}) 181 calls int32 182 f = func() { 183 atomic.AddInt32(&calls, 1) 184 } 185 186 cl = new(clocktest.Mock) 187 timer = new(clocktest.MockTimer) 188 trigger = make(chan time.Time) 189 c = New(WithDelay(time.Minute), WithClock(cl)) 190 ) 191 192 require.NotNil(c) 193 cl.OnNewTimer(time.Minute, timer).Once() 194 timer.OnC(trigger).Once() 195 timer.OnStop(true).Once().Run(func(mock.Arguments) { 196 close(stopped) 197 }) 198 199 for i := 0; i < 10; i++ { 200 c.Submit(f) 201 } 202 203 c.Cancel() 204 c.Cancel() // idempotent 205 206 select { 207 case <-stopped: 208 // passing 209 case <-time.After(5 * time.Second): 210 assert.Fail("The capacitor did not discharge properly") 211 } 212 213 cl.AssertExpectations(t) 214 timer.AssertExpectations(t) 215 assert.Zero(atomic.LoadInt32(&calls)) 216 } 217 218 func TestCapacitor(t *testing.T) { 219 t.Run("Submit", testCapacitorSubmit) 220 t.Run("Discharge", testCapacitorDischarge) 221 t.Run("Cancel", testCapacitorCancel) 222 }