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