github.com/kubernetes/utils@v0.0.0-20190308190857-21c4ce38f2a7/clock/testing/fake_clock_test.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package testing 18 19 import ( 20 "testing" 21 "time" 22 ) 23 24 func TestFakeClock(t *testing.T) { 25 startTime := time.Now() 26 tc := NewFakeClock(startTime) 27 tc.Step(time.Second) 28 now := tc.Now() 29 if now.Sub(startTime) != time.Second { 30 t.Errorf("input: %s now=%s gap=%s expected=%s", startTime, now, now.Sub(startTime), time.Second) 31 } 32 33 tt := tc.Now() 34 tc.SetTime(tt.Add(time.Hour)) 35 if tc.Now().Sub(tt) != time.Hour { 36 t.Errorf("input: %s now=%s gap=%s expected=%s", tt, tc.Now(), tc.Now().Sub(tt), time.Hour) 37 } 38 } 39 40 func TestFakeClockSleep(t *testing.T) { 41 startTime := time.Now() 42 tc := NewFakeClock(startTime) 43 tc.Sleep(time.Duration(1) * time.Hour) 44 now := tc.Now() 45 if now.Sub(startTime) != time.Hour { 46 t.Errorf("Fake sleep failed, expected time to advance by one hour, instead, its %v", now.Sub(startTime)) 47 } 48 } 49 50 func TestFakeAfter(t *testing.T) { 51 tc := NewFakeClock(time.Now()) 52 if tc.HasWaiters() { 53 t.Errorf("unexpected waiter?") 54 } 55 oneSec := tc.After(time.Second) 56 if !tc.HasWaiters() { 57 t.Errorf("unexpected lack of waiter?") 58 } 59 60 oneOhOneSec := tc.After(time.Second + time.Millisecond) 61 twoSec := tc.After(2 * time.Second) 62 select { 63 case <-oneSec: 64 t.Errorf("unexpected channel read") 65 case <-oneOhOneSec: 66 t.Errorf("unexpected channel read") 67 case <-twoSec: 68 t.Errorf("unexpected channel read") 69 default: 70 } 71 72 tc.Step(999 * time.Millisecond) 73 select { 74 case <-oneSec: 75 t.Errorf("unexpected channel read") 76 case <-oneOhOneSec: 77 t.Errorf("unexpected channel read") 78 case <-twoSec: 79 t.Errorf("unexpected channel read") 80 default: 81 } 82 83 tc.Step(time.Millisecond) 84 select { 85 case <-oneSec: 86 // Expected! 87 case <-oneOhOneSec: 88 t.Errorf("unexpected channel read") 89 case <-twoSec: 90 t.Errorf("unexpected channel read") 91 default: 92 t.Errorf("unexpected non-channel read") 93 } 94 tc.Step(time.Millisecond) 95 select { 96 case <-oneSec: 97 // should not double-trigger! 98 t.Errorf("unexpected channel read") 99 case <-oneOhOneSec: 100 // Expected! 101 case <-twoSec: 102 t.Errorf("unexpected channel read") 103 default: 104 t.Errorf("unexpected non-channel read") 105 } 106 } 107 108 func TestFakeTick(t *testing.T) { 109 tc := NewFakeClock(time.Now()) 110 if tc.HasWaiters() { 111 t.Errorf("unexpected waiter?") 112 } 113 oneSec := tc.Tick(time.Second) 114 if !tc.HasWaiters() { 115 t.Errorf("unexpected lack of waiter?") 116 } 117 118 oneOhOneSec := tc.Tick(time.Second + time.Millisecond) 119 twoSec := tc.Tick(2 * time.Second) 120 select { 121 case <-oneSec: 122 t.Errorf("unexpected channel read") 123 case <-oneOhOneSec: 124 t.Errorf("unexpected channel read") 125 case <-twoSec: 126 t.Errorf("unexpected channel read") 127 default: 128 } 129 130 tc.Step(999 * time.Millisecond) // t=.999 131 select { 132 case <-oneSec: 133 t.Errorf("unexpected channel read") 134 case <-oneOhOneSec: 135 t.Errorf("unexpected channel read") 136 case <-twoSec: 137 t.Errorf("unexpected channel read") 138 default: 139 } 140 141 tc.Step(time.Millisecond) // t=1.000 142 select { 143 case <-oneSec: 144 // Expected! 145 case <-oneOhOneSec: 146 t.Errorf("unexpected channel read") 147 case <-twoSec: 148 t.Errorf("unexpected channel read") 149 default: 150 t.Errorf("unexpected non-channel read") 151 } 152 tc.Step(time.Millisecond) // t=1.001 153 select { 154 case <-oneSec: 155 // should not double-trigger! 156 t.Errorf("unexpected channel read") 157 case <-oneOhOneSec: 158 // Expected! 159 case <-twoSec: 160 t.Errorf("unexpected channel read") 161 default: 162 t.Errorf("unexpected non-channel read") 163 } 164 165 tc.Step(time.Second) // t=2.001 166 tc.Step(time.Second) // t=3.001 167 tc.Step(time.Second) // t=4.001 168 tc.Step(time.Second) // t=5.001 169 170 // The one second ticker should not accumulate ticks 171 accumulatedTicks := 0 172 drained := false 173 for !drained { 174 select { 175 case <-oneSec: 176 accumulatedTicks++ 177 default: 178 drained = true 179 } 180 } 181 if accumulatedTicks != 1 { 182 t.Errorf("unexpected number of accumulated ticks: %d", accumulatedTicks) 183 } 184 } 185 186 func TestFakeStop(t *testing.T) { 187 tc := NewFakeClock(time.Now()) 188 timer := tc.NewTimer(time.Second) 189 if !tc.HasWaiters() { 190 t.Errorf("expected a waiter to be present, but it is not") 191 } 192 timer.Stop() 193 if tc.HasWaiters() { 194 t.Errorf("expected existing waiter to be cleaned up, but it is still present") 195 } 196 } 197 198 // This tests the pattern documented in the go docs here: https://golang.org/pkg/time/#Timer.Stop 199 // This pattern is required to safely reset a timer, so should be common. 200 // This also tests resetting the timer 201 func TestFakeStopDrain(t *testing.T) { 202 start := time.Time{} 203 tc := NewFakeClock(start) 204 timer := tc.NewTimer(time.Second) 205 tc.Step(1 * time.Second) 206 // Effectively `if !timer.Stop { <-t.C }` but with more asserts 207 if timer.Stop() { 208 t.Errorf("stop should report the timer had triggered") 209 } 210 if readTime := assertReadTime(t, timer.C()); !readTime.Equal(start.Add(1 * time.Second)) { 211 t.Errorf("timer should have ticked after 1 second, got %v", readTime) 212 } 213 214 timer.Reset(time.Second) 215 if !tc.HasWaiters() { 216 t.Errorf("expected a waiter to be present, but it is not") 217 } 218 select { 219 case <-timer.C(): 220 t.Fatal("got time early on clock; haven't stepped yet") 221 default: 222 } 223 tc.Step(1 * time.Second) 224 if readTime := assertReadTime(t, timer.C()); !readTime.Equal(start.Add(2 * time.Second)) { 225 t.Errorf("timer should have ticked again after reset + 1 more second, got %v", readTime) 226 } 227 } 228 229 func TestTimerNegative(t *testing.T) { 230 tc := NewFakeClock(time.Now()) 231 timer := tc.NewTimer(-1 * time.Second) 232 if !tc.HasWaiters() { 233 t.Errorf("expected a waiter to be present, but it is not") 234 } 235 // force waiters to be called 236 tc.Step(0) 237 tick := assertReadTime(t, timer.C()) 238 if tick != tc.Now() { 239 t.Errorf("expected -1s to turn into now: %v != %v", tick, tc.Now()) 240 } 241 } 242 243 func TestTickNegative(t *testing.T) { 244 // The stdlib 'Tick' returns nil for negative and zero values, so our fake 245 // should too. 246 tc := NewFakeClock(time.Now()) 247 if tick := tc.Tick(-1 * time.Second); tick != nil { 248 t.Errorf("expected negative tick to be nil: %v", tick) 249 } 250 if tick := tc.Tick(0); tick != nil { 251 t.Errorf("expected negative tick to be nil: %v", tick) 252 } 253 } 254 255 // assertReadTime asserts that the channel can be read and returns the time it 256 // reads from the channel. 257 func assertReadTime(t testing.TB, c <-chan time.Time) time.Time { 258 type helper interface { 259 Helper() 260 } 261 if h, ok := t.(helper); ok { 262 h.Helper() 263 } 264 select { 265 case ti, ok := <-c: 266 if !ok { 267 t.Fatalf("expected to read time from channel, but it was closed") 268 } 269 return ti 270 default: 271 t.Fatalf("expected to read time from channel, but couldn't") 272 } 273 panic("unreachable") 274 }