github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/timeutil/timer_test.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package timeutil 12 13 import ( 14 "fmt" 15 "testing" 16 "time" 17 ) 18 19 const timeStep = 10 * time.Millisecond 20 21 func TestTimerTimeout(t *testing.T) { 22 var timer Timer 23 defer func() { 24 if stopped := timer.Stop(); stopped { 25 t.Errorf("expected Stop to return false, got true") 26 } 27 }() 28 timer.Reset(timeStep) 29 30 <-timer.C 31 timer.Read = true 32 33 select { 34 case <-timer.C: 35 t.Errorf("expected timer to only timeout once after Reset; got two timeouts") 36 case <-time.After(5 * timeStep): 37 } 38 } 39 40 func TestTimerStop(t *testing.T) { 41 for sleepMult := time.Duration(0); sleepMult < 3; sleepMult++ { 42 sleepDur := sleepMult * timeStep 43 t.Run(fmt.Sprintf("sleepDur=%d*timeStep", sleepMult), func(t *testing.T) { 44 var timer Timer 45 timer.Reset(timeStep) 46 time.Sleep(sleepDur) 47 48 // Get a handle to the timer channel before calling Stop, because Stop 49 // clears the struct. 50 c := timer.C 51 52 // Even though we sleep for a certain duration which we know to be more 53 // or less than the timer's duration, we can't assert whether the timer 54 // fires before calling timer.Stop because we have no control over the 55 // scheduler. Instead, we handle both cases to avoid flakiness and assert 56 // that Stop returns the correct status. 57 stopped := timer.Stop() 58 select { 59 case <-c: 60 if stopped { 61 t.Errorf("timer unexpectedly fired after stopping") 62 } 63 case <-time.After(5 * timeStep): 64 if !stopped { 65 t.Errorf("timer did not fire after failing to stop") 66 } 67 } 68 }) 69 } 70 71 } 72 73 func TestTimerUninitializedStopNoop(t *testing.T) { 74 var timer Timer 75 if stopped := timer.Stop(); stopped { 76 t.Errorf("expected Stop to return false when the timer was never reset, got true") 77 } 78 } 79 80 func TestTimerResetBeforeTimeout(t *testing.T) { 81 var timer Timer 82 defer timer.Stop() 83 timer.Reset(timeStep) 84 85 timer.Reset(timeStep) 86 <-timer.C 87 timer.Read = true 88 89 select { 90 case <-timer.C: 91 t.Errorf("expected timer to only timeout once after Reset; got two timeouts") 92 case <-time.After(5 * timeStep): 93 } 94 } 95 96 func TestTimerResetAfterTimeoutAndNoRead(t *testing.T) { 97 var timer Timer 98 defer timer.Stop() 99 timer.Reset(timeStep) 100 101 time.Sleep(2 * timeStep) 102 103 timer.Reset(timeStep) 104 <-timer.C 105 timer.Read = true 106 107 select { 108 case <-timer.C: 109 t.Errorf("expected timer to only timeout once after Reset; got two timeouts") 110 case <-time.After(5 * timeStep): 111 } 112 } 113 114 func TestTimerResetAfterTimeoutAndRead(t *testing.T) { 115 var timer Timer 116 defer timer.Stop() 117 timer.Reset(timeStep) 118 119 <-timer.C 120 timer.Read = true 121 122 timer.Reset(timeStep) 123 <-timer.C 124 timer.Read = true 125 126 select { 127 case <-timer.C: 128 t.Errorf("expected timer to only timeout once after Reset; got two timeouts") 129 case <-time.After(5 * timeStep): 130 } 131 } 132 133 func TestTimerMakesProgressInLoop(t *testing.T) { 134 var timer Timer 135 defer timer.Stop() 136 for i := 0; i < 5; i++ { 137 timer.Reset(timeStep) 138 <-timer.C 139 timer.Read = true 140 } 141 }