github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/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  	"sync/atomic"
    13  	"testing"
    14  	. "time"
    15  )
    16  
    17  func TestSleep(t *testing.T) {
    18  	const delay = 100 * Millisecond
    19  	go func() {
    20  		Sleep(delay / 2)
    21  		Interrupt()
    22  	}()
    23  	start := Now()
    24  	Sleep(delay)
    25  	duration := Now().Sub(start)
    26  	if duration < delay {
    27  		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
    28  	}
    29  }
    30  
    31  // Test the basic function calling behavior. Correct queueing
    32  // behavior is tested elsewhere, since After and AfterFunc share
    33  // the same code.
    34  func TestAfterFunc(t *testing.T) {
    35  	i := 10
    36  	c := make(chan bool)
    37  	var f func()
    38  	f = func() {
    39  		i--
    40  		if i >= 0 {
    41  			AfterFunc(0, f)
    42  			Sleep(1 * Second)
    43  		} else {
    44  			c <- true
    45  		}
    46  	}
    47  
    48  	AfterFunc(0, f)
    49  	<-c
    50  }
    51  
    52  func TestAfterStress(t *testing.T) {
    53  	stop := uint32(0)
    54  	go func() {
    55  		for atomic.LoadUint32(&stop) == 0 {
    56  			runtime.GC()
    57  			// Yield so that the OS can wake up the timer thread,
    58  			// so that it can generate channel sends for the main goroutine,
    59  			// which will eventually set stop = 1 for us.
    60  			Sleep(Nanosecond)
    61  		}
    62  	}()
    63  	ticker := NewTicker(1)
    64  	for i := 0; i < 100; i++ {
    65  		<-ticker.C
    66  	}
    67  	ticker.Stop()
    68  	atomic.StoreUint32(&stop, 1)
    69  }
    70  
    71  func BenchmarkAfterFunc(b *testing.B) {
    72  	i := b.N
    73  	c := make(chan bool)
    74  	var f func()
    75  	f = func() {
    76  		i--
    77  		if i >= 0 {
    78  			AfterFunc(0, f)
    79  		} else {
    80  			c <- true
    81  		}
    82  	}
    83  
    84  	AfterFunc(0, f)
    85  	<-c
    86  }
    87  
    88  func BenchmarkAfter(b *testing.B) {
    89  	for i := 0; i < b.N; i++ {
    90  		<-After(1)
    91  	}
    92  }
    93  
    94  func BenchmarkStop(b *testing.B) {
    95  	for i := 0; i < b.N; i++ {
    96  		NewTimer(1 * Second).Stop()
    97  	}
    98  }
    99  
   100  func TestAfter(t *testing.T) {
   101  	const delay = 100 * Millisecond
   102  	start := Now()
   103  	end := <-After(delay)
   104  	if duration := Now().Sub(start); duration < delay {
   105  		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
   106  	}
   107  	if min := start.Add(delay); end.Before(min) {
   108  		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
   109  	}
   110  }
   111  
   112  func TestAfterTick(t *testing.T) {
   113  	const Count = 10
   114  	Delta := 100 * Millisecond
   115  	if testing.Short() {
   116  		Delta = 10 * Millisecond
   117  	}
   118  	t0 := Now()
   119  	for i := 0; i < Count; i++ {
   120  		<-After(Delta)
   121  	}
   122  	t1 := Now()
   123  	d := t1.Sub(t0)
   124  	target := Delta * Count
   125  	if d < target*9/10 {
   126  		t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target)
   127  	}
   128  	if !testing.Short() && d > target*30/10 {
   129  		t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target)
   130  	}
   131  }
   132  
   133  func TestAfterStop(t *testing.T) {
   134  	AfterFunc(100*Millisecond, func() {})
   135  	t0 := NewTimer(50 * Millisecond)
   136  	c1 := make(chan bool, 1)
   137  	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
   138  	c2 := After(200 * Millisecond)
   139  	if !t0.Stop() {
   140  		t.Fatalf("failed to stop event 0")
   141  	}
   142  	if !t1.Stop() {
   143  		t.Fatalf("failed to stop event 1")
   144  	}
   145  	<-c2
   146  	select {
   147  	case <-t0.C:
   148  		t.Fatalf("event 0 was not stopped")
   149  	case <-c1:
   150  		t.Fatalf("event 1 was not stopped")
   151  	default:
   152  	}
   153  	if t1.Stop() {
   154  		t.Fatalf("Stop returned true twice")
   155  	}
   156  }
   157  
   158  func TestAfterQueuing(t *testing.T) {
   159  	// This test flakes out on some systems,
   160  	// so we'll try it a few times before declaring it a failure.
   161  	const attempts = 3
   162  	err := errors.New("!=nil")
   163  	for i := 0; i < attempts && err != nil; i++ {
   164  		if err = testAfterQueuing(t); err != nil {
   165  			t.Logf("attempt %v failed: %v", i, err)
   166  		}
   167  	}
   168  	if err != nil {
   169  		t.Fatal(err)
   170  	}
   171  }
   172  
   173  var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}
   174  
   175  type afterResult struct {
   176  	slot int
   177  	t    Time
   178  }
   179  
   180  func await(slot int, result chan<- afterResult, ac <-chan Time) {
   181  	result <- afterResult{slot, <-ac}
   182  }
   183  
   184  func testAfterQueuing(t *testing.T) error {
   185  	Delta := 100 * Millisecond
   186  	if testing.Short() {
   187  		Delta = 20 * Millisecond
   188  	}
   189  	// make the result channel buffered because we don't want
   190  	// to depend on channel queueing semantics that might
   191  	// possibly change in the future.
   192  	result := make(chan afterResult, len(slots))
   193  
   194  	t0 := Now()
   195  	for _, slot := range slots {
   196  		go await(slot, result, After(Duration(slot)*Delta))
   197  	}
   198  	sort.Ints(slots)
   199  	for _, slot := range slots {
   200  		r := <-result
   201  		if r.slot != slot {
   202  			return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
   203  		}
   204  		dt := r.t.Sub(t0)
   205  		target := Duration(slot) * Delta
   206  		if dt < target-Delta/2 || dt > target+Delta*10 {
   207  			return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
   208  		}
   209  	}
   210  	return nil
   211  }
   212  
   213  func TestTimerStopStress(t *testing.T) {
   214  	if testing.Short() {
   215  		return
   216  	}
   217  	for i := 0; i < 100; i++ {
   218  		go func(i int) {
   219  			timer := AfterFunc(2*Second, func() {
   220  				t.Fatalf("timer %d was not stopped", i)
   221  			})
   222  			Sleep(1 * Second)
   223  			timer.Stop()
   224  		}(i)
   225  	}
   226  	Sleep(3 * Second)
   227  }
   228  
   229  func TestSleepZeroDeadlock(t *testing.T) {
   230  	// Sleep(0) used to hang, the sequence of events was as follows.
   231  	// Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
   232  	// Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
   233  	// After the GC nobody wakes up the goroutine from Gwaiting status.
   234  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
   235  	c := make(chan bool)
   236  	go func() {
   237  		for i := 0; i < 100; i++ {
   238  			runtime.GC()
   239  		}
   240  		c <- true
   241  	}()
   242  	for i := 0; i < 100; i++ {
   243  		Sleep(0)
   244  		tmp := make(chan bool, 1)
   245  		tmp <- true
   246  		<-tmp
   247  	}
   248  	<-c
   249  }
   250  
   251  func testReset(d Duration) error {
   252  	t0 := NewTimer(2 * d)
   253  	Sleep(d)
   254  	if t0.Reset(3*d) != true {
   255  		return errors.New("resetting unfired timer returned false")
   256  	}
   257  	Sleep(2 * d)
   258  	select {
   259  	case <-t0.C:
   260  		return errors.New("timer fired early")
   261  	default:
   262  	}
   263  	Sleep(2 * d)
   264  	select {
   265  	case <-t0.C:
   266  	default:
   267  		return errors.New("reset timer did not fire")
   268  	}
   269  
   270  	if t0.Reset(50*Millisecond) != false {
   271  		return errors.New("resetting expired timer returned true")
   272  	}
   273  	return nil
   274  }
   275  
   276  func TestReset(t *testing.T) {
   277  	// We try to run this test with increasingly larger multiples
   278  	// until one works so slow, loaded hardware isn't as flaky,
   279  	// but without slowing down fast machines unnecessarily.
   280  	const unit = 25 * Millisecond
   281  	tries := []Duration{
   282  		1 * unit,
   283  		3 * unit,
   284  		7 * unit,
   285  		15 * unit,
   286  	}
   287  	var err error
   288  	for _, d := range tries {
   289  		err = testReset(d)
   290  		if err == nil {
   291  			t.Logf("passed using duration %v", d)
   292  			return
   293  		}
   294  	}
   295  	t.Error(err)
   296  }
   297  
   298  // Test that sleeping for an interval so large it overflows does not
   299  // result in a short sleep duration.
   300  func TestOverflowSleep(t *testing.T) {
   301  	const timeout = 25 * Millisecond
   302  	const big = Duration(int64(1<<63 - 1))
   303  	select {
   304  	case <-After(big):
   305  		t.Fatalf("big timeout fired")
   306  	case <-After(timeout):
   307  		// OK
   308  	}
   309  	const neg = Duration(-1 << 63)
   310  	select {
   311  	case <-After(neg):
   312  		// OK
   313  	case <-After(timeout):
   314  		t.Fatalf("negative timeout didn't fire")
   315  	}
   316  }