github.com/comwrg/go/src@v0.0.0-20220319063731-c238d0440370/time/tick_test.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package time_test 6 7 import ( 8 "fmt" 9 "runtime" 10 "testing" 11 . "time" 12 ) 13 14 func TestTicker(t *testing.T) { 15 // We want to test that a ticker takes as much time as expected. 16 // Since we don't want the test to run for too long, we don't 17 // want to use lengthy times. This makes the test inherently flaky. 18 // So only report an error if it fails five times in a row. 19 20 count := 10 21 delta := 20 * Millisecond 22 23 // On Darwin ARM64 the tick frequency seems limited. Issue 35692. 24 if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && runtime.GOARCH == "arm64" { 25 // The following test will run ticker count/2 times then reset 26 // the ticker to double the duration for the rest of count/2. 27 // Since tick frequency is limited on Darwin ARM64, use even 28 // number to give the ticks more time to let the test pass. 29 // See CL 220638. 30 count = 6 31 delta = 100 * Millisecond 32 } 33 34 var errs []string 35 logErrs := func() { 36 for _, e := range errs { 37 t.Log(e) 38 } 39 } 40 41 for i := 0; i < 5; i++ { 42 ticker := NewTicker(delta) 43 t0 := Now() 44 for i := 0; i < count/2; i++ { 45 <-ticker.C 46 } 47 ticker.Reset(delta * 2) 48 for i := count / 2; i < count; i++ { 49 <-ticker.C 50 } 51 ticker.Stop() 52 t1 := Now() 53 dt := t1.Sub(t0) 54 target := 3 * delta * Duration(count/2) 55 slop := target * 3 / 10 56 if dt < target-slop || dt > target+slop { 57 errs = append(errs, fmt.Sprintf("%d %s ticks then %d %s ticks took %s, expected [%s,%s]", count/2, delta, count/2, delta*2, dt, target-slop, target+slop)) 58 if dt > target+slop { 59 // System may be overloaded; sleep a bit 60 // in the hopes it will recover. 61 Sleep(Second / 2) 62 } 63 continue 64 } 65 // Now test that the ticker stopped. 66 Sleep(2 * delta) 67 select { 68 case <-ticker.C: 69 errs = append(errs, "Ticker did not shut down") 70 continue 71 default: 72 // ok 73 } 74 75 // Test passed, so all done. 76 if len(errs) > 0 { 77 t.Logf("saw %d errors, ignoring to avoid flakiness", len(errs)) 78 logErrs() 79 } 80 81 return 82 } 83 84 t.Errorf("saw %d errors", len(errs)) 85 logErrs() 86 } 87 88 // Issue 21874 89 func TestTickerStopWithDirectInitialization(t *testing.T) { 90 c := make(chan Time) 91 tk := &Ticker{C: c} 92 tk.Stop() 93 } 94 95 // Test that a bug tearing down a ticker has been fixed. This routine should not deadlock. 96 func TestTeardown(t *testing.T) { 97 Delta := 100 * Millisecond 98 if testing.Short() { 99 Delta = 20 * Millisecond 100 } 101 for i := 0; i < 3; i++ { 102 ticker := NewTicker(Delta) 103 <-ticker.C 104 ticker.Stop() 105 } 106 } 107 108 // Test the Tick convenience wrapper. 109 func TestTick(t *testing.T) { 110 // Test that giving a negative duration returns nil. 111 if got := Tick(-1); got != nil { 112 t.Errorf("Tick(-1) = %v; want nil", got) 113 } 114 } 115 116 // Test that NewTicker panics when given a duration less than zero. 117 func TestNewTickerLtZeroDuration(t *testing.T) { 118 defer func() { 119 if err := recover(); err == nil { 120 t.Errorf("NewTicker(-1) should have panicked") 121 } 122 }() 123 NewTicker(-1) 124 } 125 126 func BenchmarkTicker(b *testing.B) { 127 benchmark(b, func(n int) { 128 ticker := NewTicker(Nanosecond) 129 for i := 0; i < n; i++ { 130 <-ticker.C 131 } 132 ticker.Stop() 133 }) 134 } 135 136 func BenchmarkTickerReset(b *testing.B) { 137 benchmark(b, func(n int) { 138 ticker := NewTicker(Nanosecond) 139 for i := 0; i < n; i++ { 140 ticker.Reset(Nanosecond * 2) 141 } 142 ticker.Stop() 143 }) 144 } 145 146 func BenchmarkTickerResetNaive(b *testing.B) { 147 benchmark(b, func(n int) { 148 ticker := NewTicker(Nanosecond) 149 for i := 0; i < n; i++ { 150 ticker.Stop() 151 ticker = NewTicker(Nanosecond * 2) 152 } 153 ticker.Stop() 154 }) 155 }