go.temporal.io/server@v1.23.0/common/timer/remote_gate_test.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package timer 26 27 import ( 28 "testing" 29 "time" 30 31 "github.com/stretchr/testify/require" 32 "github.com/stretchr/testify/suite" 33 ) 34 35 type ( 36 remoteGateSuite struct { 37 suite.Suite 38 *require.Assertions 39 40 currentTime time.Time 41 remoteTimerGate RemoteGate 42 } 43 ) 44 45 func TestRemoteTimerGateSuite(t *testing.T) { 46 s := new(remoteGateSuite) 47 suite.Run(t, s) 48 } 49 50 func (s *remoteGateSuite) SetupSuite() { 51 52 } 53 54 func (s *remoteGateSuite) TearDownSuite() { 55 56 } 57 58 func (s *remoteGateSuite) SetupTest() { 59 s.Assertions = require.New(s.T()) 60 61 s.currentTime = time.Now().UTC().Add(-10 * time.Minute) 62 s.remoteTimerGate = NewRemoteGate() 63 s.remoteTimerGate.SetCurrentTime(s.currentTime) 64 } 65 66 func (s *remoteGateSuite) TearDownTest() { 67 68 } 69 70 func (s *remoteGateSuite) TestTimerFire() { 71 now := s.currentTime 72 newTimer := now.Add(1 * time.Second) 73 deadline := now.Add(2 * time.Second) 74 s.remoteTimerGate.Update(newTimer) 75 76 select { 77 case <-s.remoteTimerGate.FireCh(): 78 s.Fail("timer should not fire when current time not updated") 79 case <-time.NewTimer(deadline.Sub(now)).C: 80 } 81 82 s.remoteTimerGate.SetCurrentTime(deadline) 83 select { 84 case <-s.remoteTimerGate.FireCh(): 85 default: 86 s.Fail("timer should fire") 87 } 88 } 89 90 func (s *remoteGateSuite) TestTimerFireAfterUpdate_Active_Updated_BeforeNow() { 91 now := s.currentTime 92 newTimer := now.Add(5 * time.Second) 93 updatedNewTimer := now.Add(-1 * time.Second) 94 deadline := now.Add(3 * time.Second) 95 96 s.remoteTimerGate.Update(newTimer) 97 select { 98 case <-s.remoteTimerGate.FireCh(): 99 s.Fail("timer should not fire when current time not updated") 100 case <-time.NewTimer(deadline.Sub(now)).C: 101 } 102 103 s.True(s.remoteTimerGate.Update(updatedNewTimer)) 104 select { 105 case <-s.remoteTimerGate.FireCh(): 106 default: 107 s.Fail("timer should fire") 108 } 109 } 110 111 func (s *remoteGateSuite) TestTimerFireAfterUpdate_Active_Updated() { 112 now := s.currentTime 113 newTimer := now.Add(5 * time.Second) 114 updatedNewTimer := now.Add(1 * time.Second) 115 deadline := now.Add(3 * time.Second) 116 s.remoteTimerGate.Update(newTimer) 117 s.True(s.remoteTimerGate.Update(updatedNewTimer)) 118 119 select { 120 case <-s.remoteTimerGate.FireCh(): 121 s.Fail("timer should not fire when current time not updated") 122 case <-time.NewTimer(deadline.Sub(now)).C: 123 } 124 125 s.remoteTimerGate.SetCurrentTime(updatedNewTimer) 126 select { 127 case <-s.remoteTimerGate.FireCh(): 128 default: 129 s.Fail("timer should fire") 130 } 131 } 132 133 func (s *remoteGateSuite) TestTimerFireAfterUpdate_Active_NotUpdated() { 134 now := s.currentTime 135 newTimer := now.Add(1 * time.Second) 136 updatedNewTimer := now.Add(3 * time.Second) 137 deadline := now.Add(2 * time.Second) 138 s.remoteTimerGate.Update(newTimer) 139 s.False(s.remoteTimerGate.Update(updatedNewTimer)) 140 141 select { 142 case <-s.remoteTimerGate.FireCh(): 143 s.Fail("timer should not fire when current time not updated") 144 case <-time.NewTimer(deadline.Sub(now)).C: 145 } 146 147 s.remoteTimerGate.SetCurrentTime(updatedNewTimer) 148 select { 149 case <-s.remoteTimerGate.FireCh(): 150 default: 151 s.Fail("timer should fire") 152 } 153 } 154 155 func (s *remoteGateSuite) TestTimerFireAfterUpdate_NotActive_Updated() { 156 now := s.currentTime 157 newTimer := now.Add(-5 * time.Second) 158 updatedNewTimer := now.Add(1 * time.Second) 159 deadline := now.Add(2 * time.Second) 160 161 s.remoteTimerGate.Update(newTimer) 162 // this is to drain existing signal 163 <-s.remoteTimerGate.FireCh() 164 // test setup up complete 165 166 s.True(s.remoteTimerGate.Update(updatedNewTimer)) 167 select { 168 case <-s.remoteTimerGate.FireCh(): 169 s.Fail("timer should not fire when current time not updated") 170 case <-time.NewTimer(deadline.Sub(now)).C: 171 } 172 173 s.remoteTimerGate.SetCurrentTime(updatedNewTimer) 174 select { 175 case <-s.remoteTimerGate.FireCh(): 176 default: 177 s.Fail("timer should fire") 178 } 179 } 180 181 func (s *remoteGateSuite) TestTimerFireAfterUpdate_NotActive_NotUpdated() { 182 now := s.currentTime 183 newTimer := now.Add(-5 * time.Second) 184 updatedNewTimer := now.Add(-1 * time.Second) 185 186 s.remoteTimerGate.Update(newTimer) 187 // this is to drain existing signal 188 <-s.remoteTimerGate.FireCh() 189 // test setup up complete 190 191 s.True(s.remoteTimerGate.Update(updatedNewTimer)) 192 select { 193 case <-s.remoteTimerGate.FireCh(): 194 default: 195 s.Fail("timer should fire when new timer is in the past") 196 } 197 } 198 199 func (s *remoteGateSuite) TestTimerSetCurrentTime_NoUpdate() { 200 now := s.currentTime 201 newCurrentTime := now.Add(-1 * time.Second) 202 s.False(s.remoteTimerGate.SetCurrentTime(newCurrentTime)) 203 select { 204 case <-s.remoteTimerGate.FireCh(): 205 s.Fail("timer should not fire") 206 default: 207 } 208 } 209 210 func (s *remoteGateSuite) TestTimerSetCurrentTime_Update_TimerAlreadyFired() { 211 now := s.currentTime 212 newTimer := now.Add(-1 * time.Second) 213 newCurrentTime := now.Add(1 * time.Second) 214 215 s.remoteTimerGate.Update(newTimer) 216 // this is to drain existing signal 217 <-s.remoteTimerGate.FireCh() 218 // test setup up complete 219 220 s.True(s.remoteTimerGate.SetCurrentTime(newCurrentTime)) 221 select { 222 case <-s.remoteTimerGate.FireCh(): 223 s.Fail("timer should not fire") 224 default: 225 } 226 } 227 228 func (s *remoteGateSuite) TestTimerSetCurrentTime_Update_TimerNotFired() { 229 now := s.currentTime 230 newTimer := now.Add(2 * time.Second) 231 newCurrentTime := now.Add(1 * time.Second) 232 233 s.remoteTimerGate.Update(newTimer) 234 s.True(s.remoteTimerGate.SetCurrentTime(newCurrentTime)) 235 select { 236 case <-s.remoteTimerGate.FireCh(): 237 s.Fail("timer should not fire") 238 default: 239 } 240 } 241 242 func (s *remoteGateSuite) TestTimerSetCurrentTime_Update_TimerFired() { 243 now := s.currentTime 244 newTimer := now.Add(2 * time.Second) 245 newCurrentTime := now.Add(2 * time.Second) 246 247 s.remoteTimerGate.Update(newTimer) 248 s.True(s.remoteTimerGate.SetCurrentTime(newCurrentTime)) 249 select { 250 case <-s.remoteTimerGate.FireCh(): 251 default: 252 s.Fail("timer should fire") 253 } 254 255 // should fire only once 256 newCurrentTime = newCurrentTime.Add(1 * time.Second) 257 s.True(s.remoteTimerGate.SetCurrentTime(newCurrentTime)) 258 select { 259 case <-s.remoteTimerGate.FireCh(): 260 s.Fail("timer should not fire") 261 default: 262 } 263 } 264 265 func (s *remoteGateSuite) TestTimerWillFire_Zero() { 266 // this test is to validate initial notification will trigger a scan of timer 267 s.remoteTimerGate.Update(time.Time{}) 268 s.False(s.remoteTimerGate.FireAfter(time.Now().UTC())) 269 } 270 271 func (s *remoteGateSuite) TestTimerWillFire_Active() { 272 now := s.currentTime 273 newTimer := now.Add(2 * time.Second) 274 timeBeforeNewTimer := now.Add(1 * time.Second) 275 timeAfterNewTimer := now.Add(3 * time.Second) 276 s.remoteTimerGate.Update(newTimer) 277 s.True(s.remoteTimerGate.FireAfter(timeBeforeNewTimer)) 278 s.False(s.remoteTimerGate.FireAfter(timeAfterNewTimer)) 279 } 280 281 func (s *remoteGateSuite) TestTimerWillFire_NotActive() { 282 now := s.currentTime 283 newTimer := now.Add(-2 * time.Second) 284 timeBeforeTimer := now.Add(-3 * time.Second) 285 timeAfterTimer := now.Add(1 * time.Second) 286 s.remoteTimerGate.Update(newTimer) 287 s.False(s.remoteTimerGate.FireAfter(timeBeforeTimer)) 288 s.False(s.remoteTimerGate.FireAfter(timeAfterTimer)) 289 }