blob: dd0a820dd6e3fe4ee344ecbaa6bf4a26c3f361a3 [file] [log] [blame]
Christopher Wedgwood1e664282010-02-04 13:09:02 -08001// 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
5package time_test
6
7import (
Russ Coxeb692922011-11-01 22:05:34 -04008 "errors"
Andrew Gerrandd54c4ec2011-03-30 11:40:00 +11009 "fmt"
Dmitriy Vyukovdc6726b2011-11-14 21:59:48 +030010 "runtime"
Brad Fitzpatrickab4af522014-10-21 13:26:40 +020011 "strings"
Sokolov Yurafcf6a7e2013-08-21 18:51:37 +040012 "sync"
Dmitriy Vyukovdc6726b2011-11-14 21:59:48 +030013 "sync/atomic"
Russ Cox965845a2011-11-02 15:54:16 -040014 "testing"
Christopher Wedgwood1e664282010-02-04 13:09:02 -080015 . "time"
16)
17
Alex Brainman74b62b42014-08-01 11:18:11 +100018// 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.
24const windowsInaccuracy = 17 * Millisecond
25
Christopher Wedgwood1e664282010-02-04 13:09:02 -080026func TestSleep(t *testing.T) {
Russ Coxefe3d352011-11-30 11:59:44 -050027 const delay = 100 * Millisecond
Christopher Wedgwood1e664282010-02-04 13:09:02 -080028 go func() {
29 Sleep(delay / 2)
Russ Cox75d337e2011-08-26 15:15:23 -040030 Interrupt()
Christopher Wedgwood1e664282010-02-04 13:09:02 -080031 }()
Russ Coxefe3d352011-11-30 11:59:44 -050032 start := Now()
Christopher Wedgwood1e664282010-02-04 13:09:02 -080033 Sleep(delay)
Alex Brainman74b62b42014-08-01 11:18:11 +100034 delayadj := delay
35 if runtime.GOOS == "windows" {
36 delayadj -= windowsInaccuracy
37 }
Russ Coxefe3d352011-11-30 11:59:44 -050038 duration := Now().Sub(start)
Alex Brainman74b62b42014-08-01 11:18:11 +100039 if duration < delayadj {
Russ Coxefe3d352011-11-30 11:59:44 -050040 t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
Christopher Wedgwood1e664282010-02-04 13:09:02 -080041 }
42}
Andrew Gerrand1e66a212010-10-11 13:45:26 +110043
Roger Peppe212e0742011-01-10 11:51:38 -080044// Test the basic function calling behavior. Correct queueing
45// behavior is tested elsewhere, since After and AfterFunc share
46// the same code.
47func 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 Symonds2949f3b2011-12-08 15:42:44 +110055 Sleep(1 * Second)
Roger Peppe212e0742011-01-10 11:51:38 -080056 } else {
57 c <- true
58 }
59 }
60
61 AfterFunc(0, f)
62 <-c
63}
64
Dmitriy Vyukovdc6726b2011-11-14 21:59:48 +030065func TestAfterStress(t *testing.T) {
66 stop := uint32(0)
67 go func() {
68 for atomic.LoadUint32(&stop) == 0 {
69 runtime.GC()
Alex Brainmane0aa26a2013-01-18 15:31:01 +110070 // 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 Vyukovdc6726b2011-11-14 21:59:48 +030074 }
75 }()
Dmitriy Vyukov489addd2013-04-26 11:08:50 +040076 ticker := NewTicker(1)
Dmitriy Vyukovdc6726b2011-11-14 21:59:48 +030077 for i := 0; i < 100; i++ {
Dmitriy Vyukov489addd2013-04-26 11:08:50 +040078 <-ticker.C
Dmitriy Vyukovdc6726b2011-11-14 21:59:48 +030079 }
Dmitriy Vyukov489addd2013-04-26 11:08:50 +040080 ticker.Stop()
Dmitriy Vyukovdc6726b2011-11-14 21:59:48 +030081 atomic.StoreUint32(&stop, 1)
82}
83
Sokolov Yurafcf6a7e2013-08-21 18:51:37 +040084func 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 Peppe212e0742011-01-10 11:51:38 -080088 }
Sokolov Yurafcf6a7e2013-08-21 18:51:37 +040089 b.ResetTimer()
90
Dmitriy Vyukovbb9531e2014-02-24 20:47:17 +040091 b.RunParallel(func(pb *testing.PB) {
92 for pb.Next() {
93 bench(1000)
94 }
95 })
Sokolov Yurafcf6a7e2013-08-21 18:51:37 +040096
97 b.StopTimer()
98 for i := 0; i < len(garbage); i++ {
99 garbage[i].Stop()
100 }
101}
102
103func 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 Peppe212e0742011-01-10 11:51:38 -0800119}
120
Roger Peppe2ae953b2011-01-25 12:25:48 -0800121func BenchmarkAfter(b *testing.B) {
Sokolov Yurafcf6a7e2013-08-21 18:51:37 +0400122 benchmark(b, func(n int) {
123 for i := 0; i < n; i++ {
124 <-After(1)
125 }
126 })
Roger Peppe2ae953b2011-01-25 12:25:48 -0800127}
128
129func BenchmarkStop(b *testing.B) {
Sokolov Yurafcf6a7e2013-08-21 18:51:37 +0400130 benchmark(b, func(n int) {
131 for i := 0; i < n; i++ {
132 NewTimer(1 * Second).Stop()
133 }
134 })
135}
136
137func 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
148func 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 Peppe2ae953b2011-01-25 12:25:48 -0800159}
160
Andrew Gerrand1e66a212010-10-11 13:45:26 +1100161func TestAfter(t *testing.T) {
Russ Coxefe3d352011-11-30 11:59:44 -0500162 const delay = 100 * Millisecond
163 start := Now()
Andrew Gerrand1e66a212010-10-11 13:45:26 +1100164 end := <-After(delay)
Alex Brainman74b62b42014-08-01 11:18:11 +1000165 delayadj := delay
166 if runtime.GOOS == "windows" {
167 delayadj -= windowsInaccuracy
168 }
169 if duration := Now().Sub(start); duration < delayadj {
Russ Coxefe3d352011-11-30 11:59:44 -0500170 t.Fatalf("After(%s) slept for only %d ns", delay, duration)
Andrew Gerrand1e66a212010-10-11 13:45:26 +1100171 }
Alex Brainman74b62b42014-08-01 11:18:11 +1000172 if min := start.Add(delayadj); end.Before(min) {
Russ Coxefe3d352011-11-30 11:59:44 -0500173 t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
Andrew Gerrand1e66a212010-10-11 13:45:26 +1100174 }
175}
Roger Peppee2d15952010-12-06 14:19:30 -0500176
177func TestAfterTick(t *testing.T) {
Rémy Oudompheng2a6e6992012-02-14 22:13:19 +0100178 const Count = 10
179 Delta := 100 * Millisecond
180 if testing.Short() {
181 Delta = 10 * Millisecond
182 }
Russ Coxefe3d352011-11-30 11:59:44 -0500183 t0 := Now()
Roger Peppee2d15952010-12-06 14:19:30 -0500184 for i := 0; i < Count; i++ {
185 <-After(Delta)
186 }
Russ Coxefe3d352011-11-30 11:59:44 -0500187 t1 := Now()
188 d := t1.Sub(t0)
189 target := Delta * Count
Brad Fitzpatrick8c529052012-02-29 13:14:05 -0800190 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 Peppee2d15952010-12-06 14:19:30 -0500195 }
196}
197
Roger Peppe2ae953b2011-01-25 12:25:48 -0800198func TestAfterStop(t *testing.T) {
David Symonds2949f3b2011-12-08 15:42:44 +1100199 AfterFunc(100*Millisecond, func() {})
200 t0 := NewTimer(50 * Millisecond)
Roger Peppe2ae953b2011-01-25 12:25:48 -0800201 c1 := make(chan bool, 1)
David Symonds2949f3b2011-12-08 15:42:44 +1100202 t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
203 c2 := After(200 * Millisecond)
Roger Peppe2ae953b2011-01-25 12:25:48 -0800204 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 Coxf4e76d82011-01-31 18:36:28 -0500211 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 Peppe2ae953b2011-01-25 12:25:48 -0800217 }
218 if t1.Stop() {
219 t.Fatalf("Stop returned true twice")
220 }
221}
222
Andrew Gerrandd54c4ec2011-03-30 11:40:00 +1100223func 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 Fitzpatrickb4bc7b42015-05-06 10:54:20 -0700226 const attempts = 5
Russ Coxeb692922011-11-01 22:05:34 -0400227 err := errors.New("!=nil")
Andrew Gerrandd54c4ec2011-03-30 11:40:00 +1100228 for i := 0; i < attempts && err != nil; i++ {
Brad Fitzpatrickb4bc7b42015-05-06 10:54:20 -0700229 delta := Duration(20+i*50) * Millisecond
Matthew Dempskyd12b5322015-04-29 13:36:34 -0700230 if err = testAfterQueuing(t, delta); err != nil {
Andrew Gerrandd54c4ec2011-03-30 11:40:00 +1100231 t.Logf("attempt %v failed: %v", i, err)
232 }
233 }
234 if err != nil {
235 t.Fatal(err)
236 }
237}
238
Roger Peppee2d15952010-12-06 14:19:30 -0500239var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}
240
241type afterResult struct {
242 slot int
Russ Coxefe3d352011-11-30 11:59:44 -0500243 t Time
Roger Peppee2d15952010-12-06 14:19:30 -0500244}
245
Russ Coxefe3d352011-11-30 11:59:44 -0500246func await(slot int, result chan<- afterResult, ac <-chan Time) {
Roger Peppee2d15952010-12-06 14:19:30 -0500247 result <- afterResult{slot, <-ac}
248}
249
Matthew Dempskyd12b5322015-04-29 13:36:34 -0700250func testAfterQueuing(t *testing.T, delta Duration) error {
Roger Peppee2d15952010-12-06 14:19:30 -0500251 // 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 Coxefe3d352011-11-30 11:59:44 -0500256 t0 := Now()
Roger Peppee2d15952010-12-06 14:19:30 -0500257 for _, slot := range slots {
Matthew Dempskyd12b5322015-04-29 13:36:34 -0700258 go await(slot, result, After(Duration(slot)*delta))
Roger Peppee2d15952010-12-06 14:19:30 -0500259 }
Keith Randalle2e322d2015-05-04 09:17:53 -0700260 var order []int
261 var times []Time
262 for range slots {
Roger Peppee2d15952010-12-06 14:19:30 -0500263 r := <-result
Keith Randalle2e322d2015-05-04 09:17:53 -0700264 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 Peppee2d15952010-12-06 14:19:30 -0500270 }
Keith Randalle2e322d2015-05-04 09:17:53 -0700271 }
272 for i, t := range times {
273 dt := t.Sub(t0)
274 target := Duration(order[i]) * delta
Matthew Dempskyd12b5322015-04-29 13:36:34 -0700275 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 Peppee2d15952010-12-06 14:19:30 -0500277 }
278 }
Andrew Gerrandd54c4ec2011-03-30 11:40:00 +1100279 return nil
Roger Peppee2d15952010-12-06 14:19:30 -0500280}
Dmitriy Vyukova899a462011-11-25 14:13:10 +0300281
282func TestTimerStopStress(t *testing.T) {
283 if testing.Short() {
284 return
285 }
286 for i := 0; i < 100; i++ {
287 go func(i int) {
David Symonds2949f3b2011-12-08 15:42:44 +1100288 timer := AfterFunc(2*Second, func() {
Dmitriy Vyukova899a462011-11-25 14:13:10 +0300289 t.Fatalf("timer %d was not stopped", i)
290 })
David Symonds2949f3b2011-12-08 15:42:44 +1100291 Sleep(1 * Second)
Dmitriy Vyukova899a462011-11-25 14:13:10 +0300292 timer.Stop()
293 }(i)
294 }
David Symonds2949f3b2011-12-08 15:42:44 +1100295 Sleep(3 * Second)
Dmitriy Vyukova899a462011-11-25 14:13:10 +0300296}
Dmitriy Vyukova0efca82012-05-29 22:30:56 +0400297
298func 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 Dobler44ff17e2013-01-17 14:41:53 +1100319
Brad Fitzpatrick86a8d592013-01-22 17:25:58 -0800320func 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 Dobler44ff17e2013-01-17 14:41:53 +1100325 }
Brad Fitzpatrick86a8d592013-01-22 17:25:58 -0800326 Sleep(2 * d)
Volker Dobler44ff17e2013-01-17 14:41:53 +1100327 select {
328 case <-t0.C:
Brad Fitzpatrick86a8d592013-01-22 17:25:58 -0800329 return errors.New("timer fired early")
Volker Dobler44ff17e2013-01-17 14:41:53 +1100330 default:
331 }
Brad Fitzpatrick86a8d592013-01-22 17:25:58 -0800332 Sleep(2 * d)
Volker Dobler44ff17e2013-01-17 14:41:53 +1100333 select {
334 case <-t0.C:
335 default:
Brad Fitzpatrick86a8d592013-01-22 17:25:58 -0800336 return errors.New("reset timer did not fire")
Volker Dobler44ff17e2013-01-17 14:41:53 +1100337 }
338
339 if t0.Reset(50*Millisecond) != false {
Brad Fitzpatrick86a8d592013-01-22 17:25:58 -0800340 return errors.New("resetting expired timer returned true")
Volker Dobler44ff17e2013-01-17 14:41:53 +1100341 }
Brad Fitzpatrick86a8d592013-01-22 17:25:58 -0800342 return nil
343}
344
345func 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 Dobler44ff17e2013-01-17 14:41:53 +1100365}
Andrew Gerrand89cf67e2013-02-26 09:23:58 +1100366
367// Test that sleeping for an interval so large it overflows does not
368// result in a short sleep duration.
369func TestOverflowSleep(t *testing.T) {
Andrew Gerrand89cf67e2013-02-26 09:23:58 +1100370 const big = Duration(int64(1<<63 - 1))
371 select {
372 case <-After(big):
373 t.Fatalf("big timeout fired")
Andrew Gerrand2f3776a2014-04-02 08:23:35 +1100374 case <-After(25 * Millisecond):
Andrew Gerrand89cf67e2013-02-26 09:23:58 +1100375 // OK
376 }
377 const neg = Duration(-1 << 63)
378 select {
379 case <-After(neg):
380 // OK
Andrew Gerrand2f3776a2014-04-02 08:23:35 +1100381 case <-After(1 * Second):
Andrew Gerrand89cf67e2013-02-26 09:23:58 +1100382 t.Fatalf("negative timeout didn't fire")
383 }
384}
Jeff R. Allen0286b472013-07-01 21:42:29 -0400385
386// Test that a panic while deleting a timer does not leave
387// the timers mutex held, deadlocking a ticker.Stop in a defer.
388func TestIssue5745(t *testing.T) {
David Crawshawce1c9242015-03-03 07:45:06 -0500389 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. Allen0286b472013-07-01 21:42:29 -0400393 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 Martin3548ab52013-09-06 15:47:39 -0400409
410func TestOverflowRuntimeTimer(t *testing.T) {
Dave Cheneyd98b3a72014-02-02 16:05:07 +1100411 if testing.Short() {
412 t.Skip("skipping in short mode, see issue 6874")
413 }
Rob Pike83c81402014-06-12 11:44:55 -0700414 // This may hang forever if timers are broken. See comment near
415 // the end of CheckRuntimeTimerOverflow in internal_test.go.
416 CheckRuntimeTimerOverflow()
Anthony Martin3548ab52013-09-06 15:47:39 -0400417}
Brad Fitzpatrickab4af522014-10-21 13:26:40 +0200418
419func 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
427func TestZeroTimerResetPanics(t *testing.T) {
428 defer checkZeroPanicString(t)
429 var tr Timer
430 tr.Reset(1)
431}
432
433func TestZeroTimerStopPanics(t *testing.T) {
434 defer checkZeroPanicString(t)
435 var tr Timer
436 tr.Stop()
437}