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