github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/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  	"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(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(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  }