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.
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
26 func TestSleep(t
*testing
.T
) {
27 const delay
= 100 * Millisecond
35 if runtime
.GOOS
== "windows" {
36 delayadj
-= windowsInaccuracy
38 duration
:= Now().Sub(start
)
39 if duration
< delayadj
{
40 t
.Fatalf("Sleep(%s) slept for only %s", delay
, duration
)
44 // Test the basic function calling behavior. Correct queueing
45 // behavior is tested elsewhere, since After and AfterFunc share
47 func TestAfterFunc(t
*testing
.T
) {
65 func TestAfterStress(t
*testing
.T
) {
68 for atomic
.LoadUint32(&stop
) == 0 {
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.
76 ticker
:= NewTicker(1)
77 for i
:= 0; i
< 100; i
++ {
81 atomic
.StoreUint32(&stop
, 1)
84 func benchmark(b
*testing
.B
, bench
func(n
int)) {
86 // Create equal number of garbage timers on each P before starting
89 garbageAll
:= make([][]*Timer
, runtime
.GOMAXPROCS(0))
90 for i
:= range garbageAll
{
94 garbage
:= make([]*Timer
, 1<<15)
95 for j
:= range garbage
{
96 garbage
[j
] = AfterFunc(Hour
, nil)
98 garbageAll
[i
] = garbage
104 b
.RunParallel(func(pb
*testing
.PB
) {
111 for _
, garbage
:= range garbageAll
{
112 for _
, t
:= range garbage
{
118 func BenchmarkAfterFunc(b
*testing
.B
) {
119 benchmark(b
, func(n
int) {
136 func BenchmarkAfter(b
*testing
.B
) {
137 benchmark(b
, func(n
int) {
138 for i
:= 0; i
< n
; i
++ {
144 func BenchmarkStop(b
*testing
.B
) {
145 benchmark(b
, func(n
int) {
146 for i
:= 0; i
< n
; i
++ {
147 NewTimer(1 * Second
).Stop()
152 func BenchmarkSimultaneousAfterFunc(b
*testing
.B
) {
153 benchmark(b
, func(n
int) {
154 var wg sync
.WaitGroup
156 for i
:= 0; i
< n
; i
++ {
157 AfterFunc(0, wg
.Done
)
163 func BenchmarkStartStop(b
*testing
.B
) {
164 benchmark(b
, func(n
int) {
165 timers
:= make([]*Timer
, n
)
166 for i
:= 0; i
< n
; i
++ {
167 timers
[i
] = AfterFunc(Hour
, nil)
170 for i
:= 0; i
< n
; i
++ {
176 func BenchmarkReset(b
*testing
.B
) {
177 benchmark(b
, func(n
int) {
179 for i
:= 0; i
< n
; i
++ {
186 func BenchmarkSleep(b
*testing
.B
) {
187 benchmark(b
, func(n
int) {
188 var wg sync
.WaitGroup
190 for i
:= 0; i
< n
; i
++ {
200 func TestAfter(t
*testing
.T
) {
201 const delay
= 100 * Millisecond
203 end
:= <-After(delay
)
205 if runtime
.GOOS
== "windows" {
206 delayadj
-= windowsInaccuracy
208 if duration
:= Now().Sub(start
); duration
< delayadj
{
209 t
.Fatalf("After(%s) slept for only %d ns", delay
, duration
)
211 if min
:= start
.Add(delayadj
); end
.Before(min
) {
212 t
.Fatalf("After(%s) expect >= %s, got %s", delay
, min
, end
)
216 func TestAfterTick(t
*testing
.T
) {
218 Delta
:= 100 * Millisecond
220 Delta
= 10 * Millisecond
223 for i
:= 0; i
< Count
; i
++ {
228 target
:= Delta
* Count
230 t
.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count
, Delta
, d
, target
)
232 if !testing
.Short() && d
> target
*30/10 {
233 t
.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count
, Delta
, d
, target
)
237 func TestAfterStop(t
*testing
.T
) {
238 AfterFunc(100*Millisecond
, func() {})
239 t0
:= NewTimer(50 * Millisecond
)
240 c1
:= make(chan bool, 1)
241 t1
:= AfterFunc(150*Millisecond
, func() { c1
<- true })
242 c2
:= After(200 * Millisecond
)
244 t
.Fatalf("failed to stop event 0")
247 t
.Fatalf("failed to stop event 1")
252 t
.Fatalf("event 0 was not stopped")
254 t
.Fatalf("event 1 was not stopped")
258 t
.Fatalf("Stop returned true twice")
262 func TestAfterQueuing(t
*testing
.T
) {
263 // This test flakes out on some systems,
264 // so we'll try it a few times before declaring it a failure.
266 err
:= errors
.New("!=nil")
267 for i
:= 0; i
< attempts
&& err
!= nil; i
++ {
268 delta
:= Duration(20+i
*50) * Millisecond
269 if err
= testAfterQueuing(delta
); err
!= nil {
270 t
.Logf("attempt %v failed: %v", i
, err
)
278 // For gccgo omit 0 for now because it can take too long to start the
279 var slots
= []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8 /*0*/}
281 type afterResult
struct {
286 func await(slot
int, result
chan<- afterResult
, ac
<-chan Time
) {
287 result
<- afterResult
{slot
, <-ac
}
290 func testAfterQueuing(delta Duration
) error
{
291 // make the result channel buffered because we don't want
292 // to depend on channel queueing semantics that might
293 // possibly change in the future.
294 result
:= make(chan afterResult
, len(slots
))
297 for _
, slot
:= range slots
{
298 go await(slot
, result
, After(Duration(slot
)*delta
))
304 order
= append(order
, r
.slot
)
305 times
= append(times
, r
.t
)
307 for i
:= range order
{
308 if i
> 0 && order
[i
] < order
[i
-1] {
309 return fmt
.Errorf("After calls returned out of order: %v", order
)
312 for i
, t
:= range times
{
314 target
:= Duration(order
[i
]) * delta
315 if dt
< target
-delta
/2 || dt
> target
+delta
*10 {
316 return fmt
.Errorf("After(%s) arrived at %s, expected [%s,%s]", target
, dt
, target
-delta
/2, target
+delta
*10)
322 func TestTimerStopStress(t
*testing
.T
) {
326 for i
:= 0; i
< 100; i
++ {
328 timer
:= AfterFunc(2*Second
, func() {
329 t
.Fatalf("timer %d was not stopped", i
)
338 func TestSleepZeroDeadlock(t
*testing
.T
) {
339 // Sleep(0) used to hang, the sequence of events was as follows.
340 // Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
341 // Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
342 // After the GC nobody wakes up the goroutine from Gwaiting status.
343 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(4))
346 for i
:= 0; i
< 100; i
++ {
351 for i
:= 0; i
< 100; i
++ {
353 tmp
:= make(chan bool, 1)
360 func testReset(d Duration
) error
{
361 t0
:= NewTimer(2 * d
)
363 if t0
.Reset(3*d
) != true {
364 return errors
.New("resetting unfired timer returned false")
369 return errors
.New("timer fired early")
376 return errors
.New("reset timer did not fire")
379 if t0
.Reset(50*Millisecond
) != false {
380 return errors
.New("resetting expired timer returned true")
385 func TestReset(t
*testing
.T
) {
386 // We try to run this test with increasingly larger multiples
387 // until one works so slow, loaded hardware isn't as flaky,
388 // but without slowing down fast machines unnecessarily.
389 const unit
= 25 * Millisecond
397 for _
, d
:= range tries
{
400 t
.Logf("passed using duration %v", d
)
407 // Test that sleeping for an interval so large it overflows does not
408 // result in a short sleep duration.
409 func TestOverflowSleep(t
*testing
.T
) {
410 const big
= Duration(int64(1<<63 - 1))
413 t
.Fatalf("big timeout fired")
414 case <-After(25 * Millisecond
):
417 const neg
= Duration(-1 << 63)
421 case <-After(1 * Second
):
422 t
.Fatalf("negative timeout didn't fire")
426 // Test that a panic while deleting a timer does not leave
427 // the timers mutex held, deadlocking a ticker.Stop in a defer.
428 func TestIssue5745(t
*testing
.T
) {
429 if runtime
.GOOS
== "darwin" && runtime
.GOARCH
== "arm" {
430 t
.Skipf("skipping on %s/%s, see issue 10043", runtime
.GOOS
, runtime
.GOARCH
)
433 ticker
:= NewTicker(Hour
)
435 // would deadlock here before the fix due to
436 // lock taken before the segfault.
439 if r
:= recover(); r
== nil {
440 t
.Error("Expected panic, but none happened.")
444 // cause a panic due to a segfault
447 t
.Error("Should be unreachable.")
450 func TestOverflowRuntimeTimer(t
*testing
.T
) {
452 t
.Skip("skipping in short mode, see issue 6874")
454 // This may hang forever if timers are broken. See comment near
455 // the end of CheckRuntimeTimerOverflow in internal_test.go.
456 CheckRuntimeTimerOverflow()
459 func checkZeroPanicString(t
*testing
.T
) {
462 if want
:= "called on uninitialized Timer"; !strings
.Contains(s
, want
) {
463 t
.Errorf("panic = %v; want substring %q", e
, want
)
467 func TestZeroTimerResetPanics(t
*testing
.T
) {
468 defer checkZeroPanicString(t
)
473 func TestZeroTimerStopPanics(t
*testing
.T
) {
474 defer checkZeroPanicString(t
)