github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/time/sleep_test.go (about)

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