Christopher Wedgwood | 1e66428 | 2010-02-04 13:09:02 -0800 | [diff] [blame] | 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 ( |
Russ Cox | eb69292 | 2011-11-01 22:05:34 -0400 | [diff] [blame] | 8 | "errors" |
Andrew Gerrand | d54c4ec | 2011-03-30 11:40:00 +1100 | [diff] [blame] | 9 | "fmt" |
Dmitriy Vyukov | dc6726b | 2011-11-14 21:59:48 +0300 | [diff] [blame] | 10 | "runtime" |
Brad Fitzpatrick | ab4af52 | 2014-10-21 13:26:40 +0200 | [diff] [blame] | 11 | "strings" |
Sokolov Yura | fcf6a7e | 2013-08-21 18:51:37 +0400 | [diff] [blame] | 12 | "sync" |
Dmitriy Vyukov | dc6726b | 2011-11-14 21:59:48 +0300 | [diff] [blame] | 13 | "sync/atomic" |
Russ Cox | 965845a | 2011-11-02 15:54:16 -0400 | [diff] [blame] | 14 | "testing" |
Christopher Wedgwood | 1e66428 | 2010-02-04 13:09:02 -0800 | [diff] [blame] | 15 | . "time" |
| 16 | ) |
| 17 | |
Alex Brainman | 74b62b4 | 2014-08-01 11:18:11 +1000 | [diff] [blame] | 18 | // Go runtime uses different Windows timers for time.Now and sleeping. |
| 19 | // These can tick at different frequencies and can arrive out of sync. |
| 20 | // The effect can be seen, for example, as time.Sleep(100ms) is actually |
| 21 | // shorter then 100ms when measured as difference between time.Now before and |
| 22 | // after time.Sleep call. This was observed on Windows XP SP3 (windows/386). |
| 23 | // windowsInaccuracy is to ignore such errors. |
| 24 | const windowsInaccuracy = 17 * Millisecond |
| 25 | |
Christopher Wedgwood | 1e66428 | 2010-02-04 13:09:02 -0800 | [diff] [blame] | 26 | func TestSleep(t *testing.T) { |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 27 | const delay = 100 * Millisecond |
Christopher Wedgwood | 1e66428 | 2010-02-04 13:09:02 -0800 | [diff] [blame] | 28 | go func() { |
| 29 | Sleep(delay / 2) |
Russ Cox | 75d337e | 2011-08-26 15:15:23 -0400 | [diff] [blame] | 30 | Interrupt() |
Christopher Wedgwood | 1e66428 | 2010-02-04 13:09:02 -0800 | [diff] [blame] | 31 | }() |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 32 | start := Now() |
Christopher Wedgwood | 1e66428 | 2010-02-04 13:09:02 -0800 | [diff] [blame] | 33 | Sleep(delay) |
Alex Brainman | 74b62b4 | 2014-08-01 11:18:11 +1000 | [diff] [blame] | 34 | delayadj := delay |
| 35 | if runtime.GOOS == "windows" { |
| 36 | delayadj -= windowsInaccuracy |
| 37 | } |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 38 | duration := Now().Sub(start) |
Alex Brainman | 74b62b4 | 2014-08-01 11:18:11 +1000 | [diff] [blame] | 39 | if duration < delayadj { |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 40 | t.Fatalf("Sleep(%s) slept for only %s", delay, duration) |
Christopher Wedgwood | 1e66428 | 2010-02-04 13:09:02 -0800 | [diff] [blame] | 41 | } |
| 42 | } |
Andrew Gerrand | 1e66a21 | 2010-10-11 13:45:26 +1100 | [diff] [blame] | 43 | |
Roger Peppe | 212e074 | 2011-01-10 11:51:38 -0800 | [diff] [blame] | 44 | // Test the basic function calling behavior. Correct queueing |
| 45 | // behavior is tested elsewhere, since After and AfterFunc share |
| 46 | // the same code. |
| 47 | func TestAfterFunc(t *testing.T) { |
| 48 | i := 10 |
| 49 | c := make(chan bool) |
| 50 | var f func() |
| 51 | f = func() { |
| 52 | i-- |
| 53 | if i >= 0 { |
| 54 | AfterFunc(0, f) |
David Symonds | 2949f3b | 2011-12-08 15:42:44 +1100 | [diff] [blame] | 55 | Sleep(1 * Second) |
Roger Peppe | 212e074 | 2011-01-10 11:51:38 -0800 | [diff] [blame] | 56 | } else { |
| 57 | c <- true |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | AfterFunc(0, f) |
| 62 | <-c |
| 63 | } |
| 64 | |
Dmitriy Vyukov | dc6726b | 2011-11-14 21:59:48 +0300 | [diff] [blame] | 65 | func TestAfterStress(t *testing.T) { |
| 66 | stop := uint32(0) |
| 67 | go func() { |
| 68 | for atomic.LoadUint32(&stop) == 0 { |
| 69 | runtime.GC() |
Alex Brainman | e0aa26a | 2013-01-18 15:31:01 +1100 | [diff] [blame] | 70 | // Yield so that the OS can wake up the timer thread, |
| 71 | // so that it can generate channel sends for the main goroutine, |
| 72 | // which will eventually set stop = 1 for us. |
| 73 | Sleep(Nanosecond) |
Dmitriy Vyukov | dc6726b | 2011-11-14 21:59:48 +0300 | [diff] [blame] | 74 | } |
| 75 | }() |
Dmitriy Vyukov | 489addd | 2013-04-26 11:08:50 +0400 | [diff] [blame] | 76 | ticker := NewTicker(1) |
Dmitriy Vyukov | dc6726b | 2011-11-14 21:59:48 +0300 | [diff] [blame] | 77 | for i := 0; i < 100; i++ { |
Dmitriy Vyukov | 489addd | 2013-04-26 11:08:50 +0400 | [diff] [blame] | 78 | <-ticker.C |
Dmitriy Vyukov | dc6726b | 2011-11-14 21:59:48 +0300 | [diff] [blame] | 79 | } |
Dmitriy Vyukov | 489addd | 2013-04-26 11:08:50 +0400 | [diff] [blame] | 80 | ticker.Stop() |
Dmitriy Vyukov | dc6726b | 2011-11-14 21:59:48 +0300 | [diff] [blame] | 81 | atomic.StoreUint32(&stop, 1) |
| 82 | } |
| 83 | |
Sokolov Yura | fcf6a7e | 2013-08-21 18:51:37 +0400 | [diff] [blame] | 84 | func benchmark(b *testing.B, bench func(n int)) { |
| 85 | garbage := make([]*Timer, 1<<17) |
| 86 | for i := 0; i < len(garbage); i++ { |
| 87 | garbage[i] = AfterFunc(Hour, nil) |
Roger Peppe | 212e074 | 2011-01-10 11:51:38 -0800 | [diff] [blame] | 88 | } |
Sokolov Yura | fcf6a7e | 2013-08-21 18:51:37 +0400 | [diff] [blame] | 89 | b.ResetTimer() |
| 90 | |
Dmitriy Vyukov | bb9531e | 2014-02-24 20:47:17 +0400 | [diff] [blame] | 91 | b.RunParallel(func(pb *testing.PB) { |
| 92 | for pb.Next() { |
| 93 | bench(1000) |
| 94 | } |
| 95 | }) |
Sokolov Yura | fcf6a7e | 2013-08-21 18:51:37 +0400 | [diff] [blame] | 96 | |
| 97 | b.StopTimer() |
| 98 | for i := 0; i < len(garbage); i++ { |
| 99 | garbage[i].Stop() |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | func BenchmarkAfterFunc(b *testing.B) { |
| 104 | benchmark(b, func(n int) { |
| 105 | c := make(chan bool) |
| 106 | var f func() |
| 107 | f = func() { |
| 108 | n-- |
| 109 | if n >= 0 { |
| 110 | AfterFunc(0, f) |
| 111 | } else { |
| 112 | c <- true |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | AfterFunc(0, f) |
| 117 | <-c |
| 118 | }) |
Roger Peppe | 212e074 | 2011-01-10 11:51:38 -0800 | [diff] [blame] | 119 | } |
| 120 | |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 121 | func BenchmarkAfter(b *testing.B) { |
Sokolov Yura | fcf6a7e | 2013-08-21 18:51:37 +0400 | [diff] [blame] | 122 | benchmark(b, func(n int) { |
| 123 | for i := 0; i < n; i++ { |
| 124 | <-After(1) |
| 125 | } |
| 126 | }) |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | func BenchmarkStop(b *testing.B) { |
Sokolov Yura | fcf6a7e | 2013-08-21 18:51:37 +0400 | [diff] [blame] | 130 | benchmark(b, func(n int) { |
| 131 | for i := 0; i < n; i++ { |
| 132 | NewTimer(1 * Second).Stop() |
| 133 | } |
| 134 | }) |
| 135 | } |
| 136 | |
| 137 | func BenchmarkSimultaneousAfterFunc(b *testing.B) { |
| 138 | benchmark(b, func(n int) { |
| 139 | var wg sync.WaitGroup |
| 140 | wg.Add(n) |
| 141 | for i := 0; i < n; i++ { |
| 142 | AfterFunc(0, wg.Done) |
| 143 | } |
| 144 | wg.Wait() |
| 145 | }) |
| 146 | } |
| 147 | |
| 148 | func BenchmarkStartStop(b *testing.B) { |
| 149 | benchmark(b, func(n int) { |
| 150 | timers := make([]*Timer, n) |
| 151 | for i := 0; i < n; i++ { |
| 152 | timers[i] = AfterFunc(Hour, nil) |
| 153 | } |
| 154 | |
| 155 | for i := 0; i < n; i++ { |
| 156 | timers[i].Stop() |
| 157 | } |
| 158 | }) |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 159 | } |
| 160 | |
Andrew Gerrand | 1e66a21 | 2010-10-11 13:45:26 +1100 | [diff] [blame] | 161 | func TestAfter(t *testing.T) { |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 162 | const delay = 100 * Millisecond |
| 163 | start := Now() |
Andrew Gerrand | 1e66a21 | 2010-10-11 13:45:26 +1100 | [diff] [blame] | 164 | end := <-After(delay) |
Alex Brainman | 74b62b4 | 2014-08-01 11:18:11 +1000 | [diff] [blame] | 165 | delayadj := delay |
| 166 | if runtime.GOOS == "windows" { |
| 167 | delayadj -= windowsInaccuracy |
| 168 | } |
| 169 | if duration := Now().Sub(start); duration < delayadj { |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 170 | t.Fatalf("After(%s) slept for only %d ns", delay, duration) |
Andrew Gerrand | 1e66a21 | 2010-10-11 13:45:26 +1100 | [diff] [blame] | 171 | } |
Alex Brainman | 74b62b4 | 2014-08-01 11:18:11 +1000 | [diff] [blame] | 172 | if min := start.Add(delayadj); end.Before(min) { |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 173 | t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end) |
Andrew Gerrand | 1e66a21 | 2010-10-11 13:45:26 +1100 | [diff] [blame] | 174 | } |
| 175 | } |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 176 | |
| 177 | func TestAfterTick(t *testing.T) { |
Rémy Oudompheng | 2a6e699 | 2012-02-14 22:13:19 +0100 | [diff] [blame] | 178 | const Count = 10 |
| 179 | Delta := 100 * Millisecond |
| 180 | if testing.Short() { |
| 181 | Delta = 10 * Millisecond |
| 182 | } |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 183 | t0 := Now() |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 184 | for i := 0; i < Count; i++ { |
| 185 | <-After(Delta) |
| 186 | } |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 187 | t1 := Now() |
| 188 | d := t1.Sub(t0) |
| 189 | target := Delta * Count |
Brad Fitzpatrick | 8c52905 | 2012-02-29 13:14:05 -0800 | [diff] [blame] | 190 | if d < target*9/10 { |
| 191 | t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target) |
| 192 | } |
| 193 | if !testing.Short() && d > target*30/10 { |
| 194 | t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target) |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 195 | } |
| 196 | } |
| 197 | |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 198 | func TestAfterStop(t *testing.T) { |
David Symonds | 2949f3b | 2011-12-08 15:42:44 +1100 | [diff] [blame] | 199 | AfterFunc(100*Millisecond, func() {}) |
| 200 | t0 := NewTimer(50 * Millisecond) |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 201 | c1 := make(chan bool, 1) |
David Symonds | 2949f3b | 2011-12-08 15:42:44 +1100 | [diff] [blame] | 202 | t1 := AfterFunc(150*Millisecond, func() { c1 <- true }) |
| 203 | c2 := After(200 * Millisecond) |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 204 | if !t0.Stop() { |
| 205 | t.Fatalf("failed to stop event 0") |
| 206 | } |
| 207 | if !t1.Stop() { |
| 208 | t.Fatalf("failed to stop event 1") |
| 209 | } |
| 210 | <-c2 |
Russ Cox | f4e76d8 | 2011-01-31 18:36:28 -0500 | [diff] [blame] | 211 | select { |
| 212 | case <-t0.C: |
| 213 | t.Fatalf("event 0 was not stopped") |
| 214 | case <-c1: |
| 215 | t.Fatalf("event 1 was not stopped") |
| 216 | default: |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 217 | } |
| 218 | if t1.Stop() { |
| 219 | t.Fatalf("Stop returned true twice") |
| 220 | } |
| 221 | } |
| 222 | |
Andrew Gerrand | d54c4ec | 2011-03-30 11:40:00 +1100 | [diff] [blame] | 223 | func TestAfterQueuing(t *testing.T) { |
| 224 | // This test flakes out on some systems, |
| 225 | // so we'll try it a few times before declaring it a failure. |
Brad Fitzpatrick | b4bc7b4 | 2015-05-06 10:54:20 -0700 | [diff] [blame] | 226 | const attempts = 5 |
Russ Cox | eb69292 | 2011-11-01 22:05:34 -0400 | [diff] [blame] | 227 | err := errors.New("!=nil") |
Andrew Gerrand | d54c4ec | 2011-03-30 11:40:00 +1100 | [diff] [blame] | 228 | for i := 0; i < attempts && err != nil; i++ { |
Brad Fitzpatrick | b4bc7b4 | 2015-05-06 10:54:20 -0700 | [diff] [blame] | 229 | delta := Duration(20+i*50) * Millisecond |
Matthew Dempsky | d12b532 | 2015-04-29 13:36:34 -0700 | [diff] [blame] | 230 | if err = testAfterQueuing(t, delta); err != nil { |
Andrew Gerrand | d54c4ec | 2011-03-30 11:40:00 +1100 | [diff] [blame] | 231 | t.Logf("attempt %v failed: %v", i, err) |
| 232 | } |
| 233 | } |
| 234 | if err != nil { |
| 235 | t.Fatal(err) |
| 236 | } |
| 237 | } |
| 238 | |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 239 | var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0} |
| 240 | |
| 241 | type afterResult struct { |
| 242 | slot int |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 243 | t Time |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 244 | } |
| 245 | |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 246 | func await(slot int, result chan<- afterResult, ac <-chan Time) { |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 247 | result <- afterResult{slot, <-ac} |
| 248 | } |
| 249 | |
Matthew Dempsky | d12b532 | 2015-04-29 13:36:34 -0700 | [diff] [blame] | 250 | func testAfterQueuing(t *testing.T, delta Duration) error { |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 251 | // make the result channel buffered because we don't want |
| 252 | // to depend on channel queueing semantics that might |
| 253 | // possibly change in the future. |
| 254 | result := make(chan afterResult, len(slots)) |
| 255 | |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 256 | t0 := Now() |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 257 | for _, slot := range slots { |
Matthew Dempsky | d12b532 | 2015-04-29 13:36:34 -0700 | [diff] [blame] | 258 | go await(slot, result, After(Duration(slot)*delta)) |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 259 | } |
Keith Randall | e2e322d | 2015-05-04 09:17:53 -0700 | [diff] [blame] | 260 | var order []int |
| 261 | var times []Time |
| 262 | for range slots { |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 263 | r := <-result |
Keith Randall | e2e322d | 2015-05-04 09:17:53 -0700 | [diff] [blame] | 264 | order = append(order, r.slot) |
| 265 | times = append(times, r.t) |
| 266 | } |
| 267 | for i := range order { |
| 268 | if i > 0 && order[i] < order[i-1] { |
| 269 | return fmt.Errorf("After calls returned out of order: %v", order) |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 270 | } |
Keith Randall | e2e322d | 2015-05-04 09:17:53 -0700 | [diff] [blame] | 271 | } |
| 272 | for i, t := range times { |
| 273 | dt := t.Sub(t0) |
| 274 | target := Duration(order[i]) * delta |
Matthew Dempsky | d12b532 | 2015-04-29 13:36:34 -0700 | [diff] [blame] | 275 | if dt < target-delta/2 || dt > target+delta*10 { |
| 276 | return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-delta/2, target+delta*10) |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 277 | } |
| 278 | } |
Andrew Gerrand | d54c4ec | 2011-03-30 11:40:00 +1100 | [diff] [blame] | 279 | return nil |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 280 | } |
Dmitriy Vyukov | a899a46 | 2011-11-25 14:13:10 +0300 | [diff] [blame] | 281 | |
| 282 | func TestTimerStopStress(t *testing.T) { |
| 283 | if testing.Short() { |
| 284 | return |
| 285 | } |
| 286 | for i := 0; i < 100; i++ { |
| 287 | go func(i int) { |
David Symonds | 2949f3b | 2011-12-08 15:42:44 +1100 | [diff] [blame] | 288 | timer := AfterFunc(2*Second, func() { |
Dmitriy Vyukov | a899a46 | 2011-11-25 14:13:10 +0300 | [diff] [blame] | 289 | t.Fatalf("timer %d was not stopped", i) |
| 290 | }) |
David Symonds | 2949f3b | 2011-12-08 15:42:44 +1100 | [diff] [blame] | 291 | Sleep(1 * Second) |
Dmitriy Vyukov | a899a46 | 2011-11-25 14:13:10 +0300 | [diff] [blame] | 292 | timer.Stop() |
| 293 | }(i) |
| 294 | } |
David Symonds | 2949f3b | 2011-12-08 15:42:44 +1100 | [diff] [blame] | 295 | Sleep(3 * Second) |
Dmitriy Vyukov | a899a46 | 2011-11-25 14:13:10 +0300 | [diff] [blame] | 296 | } |
Dmitriy Vyukov | a0efca8 | 2012-05-29 22:30:56 +0400 | [diff] [blame] | 297 | |
| 298 | func TestSleepZeroDeadlock(t *testing.T) { |
| 299 | // Sleep(0) used to hang, the sequence of events was as follows. |
| 300 | // Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status. |
| 301 | // Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC. |
| 302 | // After the GC nobody wakes up the goroutine from Gwaiting status. |
| 303 | defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) |
| 304 | c := make(chan bool) |
| 305 | go func() { |
| 306 | for i := 0; i < 100; i++ { |
| 307 | runtime.GC() |
| 308 | } |
| 309 | c <- true |
| 310 | }() |
| 311 | for i := 0; i < 100; i++ { |
| 312 | Sleep(0) |
| 313 | tmp := make(chan bool, 1) |
| 314 | tmp <- true |
| 315 | <-tmp |
| 316 | } |
| 317 | <-c |
| 318 | } |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 319 | |
Brad Fitzpatrick | 86a8d59 | 2013-01-22 17:25:58 -0800 | [diff] [blame] | 320 | func testReset(d Duration) error { |
| 321 | t0 := NewTimer(2 * d) |
| 322 | Sleep(d) |
| 323 | if t0.Reset(3*d) != true { |
| 324 | return errors.New("resetting unfired timer returned false") |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 325 | } |
Brad Fitzpatrick | 86a8d59 | 2013-01-22 17:25:58 -0800 | [diff] [blame] | 326 | Sleep(2 * d) |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 327 | select { |
| 328 | case <-t0.C: |
Brad Fitzpatrick | 86a8d59 | 2013-01-22 17:25:58 -0800 | [diff] [blame] | 329 | return errors.New("timer fired early") |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 330 | default: |
| 331 | } |
Brad Fitzpatrick | 86a8d59 | 2013-01-22 17:25:58 -0800 | [diff] [blame] | 332 | Sleep(2 * d) |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 333 | select { |
| 334 | case <-t0.C: |
| 335 | default: |
Brad Fitzpatrick | 86a8d59 | 2013-01-22 17:25:58 -0800 | [diff] [blame] | 336 | return errors.New("reset timer did not fire") |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 337 | } |
| 338 | |
| 339 | if t0.Reset(50*Millisecond) != false { |
Brad Fitzpatrick | 86a8d59 | 2013-01-22 17:25:58 -0800 | [diff] [blame] | 340 | return errors.New("resetting expired timer returned true") |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 341 | } |
Brad Fitzpatrick | 86a8d59 | 2013-01-22 17:25:58 -0800 | [diff] [blame] | 342 | return nil |
| 343 | } |
| 344 | |
| 345 | func TestReset(t *testing.T) { |
| 346 | // We try to run this test with increasingly larger multiples |
| 347 | // until one works so slow, loaded hardware isn't as flaky, |
| 348 | // but without slowing down fast machines unnecessarily. |
| 349 | const unit = 25 * Millisecond |
| 350 | tries := []Duration{ |
| 351 | 1 * unit, |
| 352 | 3 * unit, |
| 353 | 7 * unit, |
| 354 | 15 * unit, |
| 355 | } |
| 356 | var err error |
| 357 | for _, d := range tries { |
| 358 | err = testReset(d) |
| 359 | if err == nil { |
| 360 | t.Logf("passed using duration %v", d) |
| 361 | return |
| 362 | } |
| 363 | } |
| 364 | t.Error(err) |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 365 | } |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 366 | |
| 367 | // Test that sleeping for an interval so large it overflows does not |
| 368 | // result in a short sleep duration. |
| 369 | func TestOverflowSleep(t *testing.T) { |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 370 | const big = Duration(int64(1<<63 - 1)) |
| 371 | select { |
| 372 | case <-After(big): |
| 373 | t.Fatalf("big timeout fired") |
Andrew Gerrand | 2f3776a | 2014-04-02 08:23:35 +1100 | [diff] [blame] | 374 | case <-After(25 * Millisecond): |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 375 | // OK |
| 376 | } |
| 377 | const neg = Duration(-1 << 63) |
| 378 | select { |
| 379 | case <-After(neg): |
| 380 | // OK |
Andrew Gerrand | 2f3776a | 2014-04-02 08:23:35 +1100 | [diff] [blame] | 381 | case <-After(1 * Second): |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 382 | t.Fatalf("negative timeout didn't fire") |
| 383 | } |
| 384 | } |
Jeff R. Allen | 0286b47 | 2013-07-01 21:42:29 -0400 | [diff] [blame] | 385 | |
| 386 | // Test that a panic while deleting a timer does not leave |
| 387 | // the timers mutex held, deadlocking a ticker.Stop in a defer. |
| 388 | func TestIssue5745(t *testing.T) { |
David Crawshaw | ce1c924 | 2015-03-03 07:45:06 -0500 | [diff] [blame] | 389 | if runtime.GOOS == "darwin" && runtime.GOARCH == "arm" { |
| 390 | t.Skipf("skipping on %s/%s, see issue 10043", runtime.GOOS, runtime.GOARCH) |
| 391 | } |
| 392 | |
Jeff R. Allen | 0286b47 | 2013-07-01 21:42:29 -0400 | [diff] [blame] | 393 | ticker := NewTicker(Hour) |
| 394 | defer func() { |
| 395 | // would deadlock here before the fix due to |
| 396 | // lock taken before the segfault. |
| 397 | ticker.Stop() |
| 398 | |
| 399 | if r := recover(); r == nil { |
| 400 | t.Error("Expected panic, but none happened.") |
| 401 | } |
| 402 | }() |
| 403 | |
| 404 | // cause a panic due to a segfault |
| 405 | var timer *Timer |
| 406 | timer.Stop() |
| 407 | t.Error("Should be unreachable.") |
| 408 | } |
Anthony Martin | 3548ab5 | 2013-09-06 15:47:39 -0400 | [diff] [blame] | 409 | |
| 410 | func TestOverflowRuntimeTimer(t *testing.T) { |
Dave Cheney | d98b3a7 | 2014-02-02 16:05:07 +1100 | [diff] [blame] | 411 | if testing.Short() { |
| 412 | t.Skip("skipping in short mode, see issue 6874") |
| 413 | } |
Rob Pike | 83c8140 | 2014-06-12 11:44:55 -0700 | [diff] [blame] | 414 | // This may hang forever if timers are broken. See comment near |
| 415 | // the end of CheckRuntimeTimerOverflow in internal_test.go. |
| 416 | CheckRuntimeTimerOverflow() |
Anthony Martin | 3548ab5 | 2013-09-06 15:47:39 -0400 | [diff] [blame] | 417 | } |
Brad Fitzpatrick | ab4af52 | 2014-10-21 13:26:40 +0200 | [diff] [blame] | 418 | |
| 419 | func checkZeroPanicString(t *testing.T) { |
| 420 | e := recover() |
| 421 | s, _ := e.(string) |
| 422 | if want := "called on uninitialized Timer"; !strings.Contains(s, want) { |
| 423 | t.Errorf("panic = %v; want substring %q", e, want) |
| 424 | } |
| 425 | } |
| 426 | |
| 427 | func TestZeroTimerResetPanics(t *testing.T) { |
| 428 | defer checkZeroPanicString(t) |
| 429 | var tr Timer |
| 430 | tr.Reset(1) |
| 431 | } |
| 432 | |
| 433 | func TestZeroTimerStopPanics(t *testing.T) { |
| 434 | defer checkZeroPanicString(t) |
| 435 | var tr Timer |
| 436 | tr.Stop() |
| 437 | } |