Home | History | Annotate | Download | only in time
      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 	"errors"
      9 	"fmt"
     10 	"runtime"
     11 	"strings"
     12 	"sync"
     13 	"sync/atomic"
     14 	"testing"
     15 	. "time"
     16 )
     17 
     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 
     26 func TestSleep(t *testing.T) {
     27 	const delay = 100 * Millisecond
     28 	go func() {
     29 		Sleep(delay / 2)
     30 		Interrupt()
     31 	}()
     32 	start := Now()
     33 	Sleep(delay)
     34 	delayadj := delay
     35 	if runtime.GOOS == "windows" {
     36 		delayadj -= windowsInaccuracy
     37 	}
     38 	duration := Now().Sub(start)
     39 	if duration < delayadj {
     40 		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
     41 	}
     42 }
     43 
     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)
     55 			Sleep(1 * Second)
     56 		} else {
     57 			c <- true
     58 		}
     59 	}
     60 
     61 	AfterFunc(0, f)
     62 	<-c
     63 }
     64 
     65 func TestAfterStress(t *testing.T) {
     66 	stop := uint32(0)
     67 	go func() {
     68 		for atomic.LoadUint32(&stop) == 0 {
     69 			runtime.GC()
     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)
     74 		}
     75 	}()
     76 	ticker := NewTicker(1)
     77 	for i := 0; i < 100; i++ {
     78 		<-ticker.C
     79 	}
     80 	ticker.Stop()
     81 	atomic.StoreUint32(&stop, 1)
     82 }
     83 
     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)
     88 	}
     89 	b.ResetTimer()
     90 
     91 	b.RunParallel(func(pb *testing.PB) {
     92 		for pb.Next() {
     93 			bench(1000)
     94 		}
     95 	})
     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 	})
    119 }
    120 
    121 func BenchmarkAfter(b *testing.B) {
    122 	benchmark(b, func(n int) {
    123 		for i := 0; i < n; i++ {
    124 			<-After(1)
    125 		}
    126 	})
    127 }
    128 
    129 func BenchmarkStop(b *testing.B) {
    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 	})
    159 }
    160 
    161 func TestAfter(t *testing.T) {
    162 	const delay = 100 * Millisecond
    163 	start := Now()
    164 	end := <-After(delay)
    165 	delayadj := delay
    166 	if runtime.GOOS == "windows" {
    167 		delayadj -= windowsInaccuracy
    168 	}
    169 	if duration := Now().Sub(start); duration < delayadj {
    170 		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
    171 	}
    172 	if min := start.Add(delayadj); end.Before(min) {
    173 		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
    174 	}
    175 }
    176 
    177 func TestAfterTick(t *testing.T) {
    178 	const Count = 10
    179 	Delta := 100 * Millisecond
    180 	if testing.Short() {
    181 		Delta = 10 * Millisecond
    182 	}
    183 	t0 := Now()
    184 	for i := 0; i < Count; i++ {
    185 		<-After(Delta)
    186 	}
    187 	t1 := Now()
    188 	d := t1.Sub(t0)
    189 	target := Delta * Count
    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)
    195 	}
    196 }
    197 
    198 func TestAfterStop(t *testing.T) {
    199 	AfterFunc(100*Millisecond, func() {})
    200 	t0 := NewTimer(50 * Millisecond)
    201 	c1 := make(chan bool, 1)
    202 	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
    203 	c2 := After(200 * Millisecond)
    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
    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:
    217 	}
    218 	if t1.Stop() {
    219 		t.Fatalf("Stop returned true twice")
    220 	}
    221 }
    222 
    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.
    226 	const attempts = 5
    227 	err := errors.New("!=nil")
    228 	for i := 0; i < attempts && err != nil; i++ {
    229 		delta := Duration(20+i*50) * Millisecond
    230 		if err = testAfterQueuing(t, delta); err != nil {
    231 			t.Logf("attempt %v failed: %v", i, err)
    232 		}
    233 	}
    234 	if err != nil {
    235 		t.Fatal(err)
    236 	}
    237 }
    238 
    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
    243 	t    Time
    244 }
    245 
    246 func await(slot int, result chan<- afterResult, ac <-chan Time) {
    247 	result <- afterResult{slot, <-ac}
    248 }
    249 
    250 func testAfterQueuing(t *testing.T, delta Duration) error {
    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 
    256 	t0 := Now()
    257 	for _, slot := range slots {
    258 		go await(slot, result, After(Duration(slot)*delta))
    259 	}
    260 	var order []int
    261 	var times []Time
    262 	for range slots {
    263 		r := <-result
    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)
    270 		}
    271 	}
    272 	for i, t := range times {
    273 		dt := t.Sub(t0)
    274 		target := Duration(order[i]) * delta
    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)
    277 		}
    278 	}
    279 	return nil
    280 }
    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) {
    288 			timer := AfterFunc(2*Second, func() {
    289 				t.Fatalf("timer %d was not stopped", i)
    290 			})
    291 			Sleep(1 * Second)
    292 			timer.Stop()
    293 		}(i)
    294 	}
    295 	Sleep(3 * Second)
    296 }
    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 }
    319 
    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")
    325 	}
    326 	Sleep(2 * d)
    327 	select {
    328 	case <-t0.C:
    329 		return errors.New("timer fired early")
    330 	default:
    331 	}
    332 	Sleep(2 * d)
    333 	select {
    334 	case <-t0.C:
    335 	default:
    336 		return errors.New("reset timer did not fire")
    337 	}
    338 
    339 	if t0.Reset(50*Millisecond) != false {
    340 		return errors.New("resetting expired timer returned true")
    341 	}
    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)
    365 }
    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) {
    370 	const big = Duration(int64(1<<63 - 1))
    371 	select {
    372 	case <-After(big):
    373 		t.Fatalf("big timeout fired")
    374 	case <-After(25 * Millisecond):
    375 		// OK
    376 	}
    377 	const neg = Duration(-1 << 63)
    378 	select {
    379 	case <-After(neg):
    380 		// OK
    381 	case <-After(1 * Second):
    382 		t.Fatalf("negative timeout didn't fire")
    383 	}
    384 }
    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) {
    389 	if runtime.GOOS == "darwin" && runtime.GOARCH == "arm" {
    390 		t.Skipf("skipping on %s/%s, see issue 10043", runtime.GOOS, runtime.GOARCH)
    391 	}
    392 
    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 }
    409 
    410 func TestOverflowRuntimeTimer(t *testing.T) {
    411 	if testing.Short() {
    412 		t.Skip("skipping in short mode, see issue 6874")
    413 	}
    414 	// This may hang forever if timers are broken. See comment near
    415 	// the end of CheckRuntimeTimerOverflow in internal_test.go.
    416 	CheckRuntimeTimerOverflow()
    417 }
    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 }
    438