github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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"
    13  	"sync/atomic"
    14  	"testing"
    15  	. "time"
    16  )
    17  
    18  func TestSleep(t *testing.T) {
    19  	const delay = 100 * Millisecond
    20  	go func() {
    21  		Sleep(delay / 2)
    22  		Interrupt()
    23  	}()
    24  	start := Now()
    25  	Sleep(delay)
    26  	duration := Now().Sub(start)
    27  	if duration < delay {
    28  		t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
    29  	}
    30  }
    31  
    32  // Test the basic function calling behavior. Correct queueing
    33  // behavior is tested elsewhere, since After and AfterFunc share
    34  // the same code.
    35  func TestAfterFunc(t *testing.T) {
    36  	i := 10
    37  	c := make(chan bool)
    38  	var f func()
    39  	f = func() {
    40  		i--
    41  		if i >= 0 {
    42  			AfterFunc(0, f)
    43  			Sleep(1 * Second)
    44  		} else {
    45  			c <- true
    46  		}
    47  	}
    48  
    49  	AfterFunc(0, f)
    50  	<-c
    51  }
    52  
    53  func TestAfterStress(t *testing.T) {
    54  	stop := uint32(0)
    55  	go func() {
    56  		for atomic.LoadUint32(&stop) == 0 {
    57  			runtime.GC()
    58  			// Yield so that the OS can wake up the timer thread,
    59  			// so that it can generate channel sends for the main goroutine,
    60  			// which will eventually set stop = 1 for us.
    61  			Sleep(Nanosecond)
    62  		}
    63  	}()
    64  	ticker := NewTicker(1)
    65  	for i := 0; i < 100; i++ {
    66  		<-ticker.C
    67  	}
    68  	ticker.Stop()
    69  	atomic.StoreUint32(&stop, 1)
    70  }
    71  
    72  func benchmark(b *testing.B, bench func(n int)) {
    73  	garbage := make([]*Timer, 1<<17)
    74  	for i := 0; i < len(garbage); i++ {
    75  		garbage[i] = AfterFunc(Hour, nil)
    76  	}
    77  
    78  	const batch = 1000
    79  	P := runtime.GOMAXPROCS(-1)
    80  	N := int32(b.N / batch)
    81  
    82  	b.ResetTimer()
    83  
    84  	var wg sync.WaitGroup
    85  	wg.Add(P)
    86  
    87  	for p := 0; p < P; p++ {
    88  		go func() {
    89  			for atomic.AddInt32(&N, -1) >= 0 {
    90  				bench(batch)
    91  			}
    92  			wg.Done()
    93  		}()
    94  	}
    95  
    96  	wg.Wait()
    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  	if duration := Now().Sub(start); duration < delay {
   167  		t.Fatalf("After(%s) slept for only %d ns", delay, duration)
   168  	}
   169  	if min := start.Add(delay); end.Before(min) {
   170  		t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
   171  	}
   172  }
   173  
   174  func TestAfterTick(t *testing.T) {
   175  	const Count = 10
   176  	Delta := 100 * Millisecond
   177  	if testing.Short() {
   178  		Delta = 10 * Millisecond
   179  	}
   180  	t0 := Now()
   181  	for i := 0; i < Count; i++ {
   182  		<-After(Delta)
   183  	}
   184  	t1 := Now()
   185  	d := t1.Sub(t0)
   186  	target := Delta * Count
   187  	if d < target*9/10 {
   188  		t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target)
   189  	}
   190  	if !testing.Short() && d > target*30/10 {
   191  		t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target)
   192  	}
   193  }
   194  
   195  func TestAfterStop(t *testing.T) {
   196  	AfterFunc(100*Millisecond, func() {})
   197  	t0 := NewTimer(50 * Millisecond)
   198  	c1 := make(chan bool, 1)
   199  	t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
   200  	c2 := After(200 * Millisecond)
   201  	if !t0.Stop() {
   202  		t.Fatalf("failed to stop event 0")
   203  	}
   204  	if !t1.Stop() {
   205  		t.Fatalf("failed to stop event 1")
   206  	}
   207  	<-c2
   208  	select {
   209  	case <-t0.C:
   210  		t.Fatalf("event 0 was not stopped")
   211  	case <-c1:
   212  		t.Fatalf("event 1 was not stopped")
   213  	default:
   214  	}
   215  	if t1.Stop() {
   216  		t.Fatalf("Stop returned true twice")
   217  	}
   218  }
   219  
   220  func TestAfterQueuing(t *testing.T) {
   221  	// This test flakes out on some systems,
   222  	// so we'll try it a few times before declaring it a failure.
   223  	const attempts = 3
   224  	err := errors.New("!=nil")
   225  	for i := 0; i < attempts && err != nil; i++ {
   226  		if err = testAfterQueuing(t); err != nil {
   227  			t.Logf("attempt %v failed: %v", i, err)
   228  		}
   229  	}
   230  	if err != nil {
   231  		t.Fatal(err)
   232  	}
   233  }
   234  
   235  var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}
   236  
   237  type afterResult struct {
   238  	slot int
   239  	t    Time
   240  }
   241  
   242  func await(slot int, result chan<- afterResult, ac <-chan Time) {
   243  	result <- afterResult{slot, <-ac}
   244  }
   245  
   246  func testAfterQueuing(t *testing.T) error {
   247  	Delta := 100 * Millisecond
   248  	if testing.Short() {
   249  		Delta = 20 * Millisecond
   250  	}
   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  	sort.Ints(slots)
   261  	for _, slot := range slots {
   262  		r := <-result
   263  		if r.slot != slot {
   264  			return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
   265  		}
   266  		dt := r.t.Sub(t0)
   267  		target := Duration(slot) * Delta
   268  		if dt < target-Delta/2 || dt > target+Delta*10 {
   269  			return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
   270  		}
   271  	}
   272  	return nil
   273  }
   274  
   275  func TestTimerStopStress(t *testing.T) {
   276  	if testing.Short() {
   277  		return
   278  	}
   279  	for i := 0; i < 100; i++ {
   280  		go func(i int) {
   281  			timer := AfterFunc(2*Second, func() {
   282  				t.Fatalf("timer %d was not stopped", i)
   283  			})
   284  			Sleep(1 * Second)
   285  			timer.Stop()
   286  		}(i)
   287  	}
   288  	Sleep(3 * Second)
   289  }
   290  
   291  func TestSleepZeroDeadlock(t *testing.T) {
   292  	// Sleep(0) used to hang, the sequence of events was as follows.
   293  	// Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
   294  	// Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
   295  	// After the GC nobody wakes up the goroutine from Gwaiting status.
   296  	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
   297  	c := make(chan bool)
   298  	go func() {
   299  		for i := 0; i < 100; i++ {
   300  			runtime.GC()
   301  		}
   302  		c <- true
   303  	}()
   304  	for i := 0; i < 100; i++ {
   305  		Sleep(0)
   306  		tmp := make(chan bool, 1)
   307  		tmp <- true
   308  		<-tmp
   309  	}
   310  	<-c
   311  }
   312  
   313  func testReset(d Duration) error {
   314  	t0 := NewTimer(2 * d)
   315  	Sleep(d)
   316  	if t0.Reset(3*d) != true {
   317  		return errors.New("resetting unfired timer returned false")
   318  	}
   319  	Sleep(2 * d)
   320  	select {
   321  	case <-t0.C:
   322  		return errors.New("timer fired early")
   323  	default:
   324  	}
   325  	Sleep(2 * d)
   326  	select {
   327  	case <-t0.C:
   328  	default:
   329  		return errors.New("reset timer did not fire")
   330  	}
   331  
   332  	if t0.Reset(50*Millisecond) != false {
   333  		return errors.New("resetting expired timer returned true")
   334  	}
   335  	return nil
   336  }
   337  
   338  func TestReset(t *testing.T) {
   339  	// We try to run this test with increasingly larger multiples
   340  	// until one works so slow, loaded hardware isn't as flaky,
   341  	// but without slowing down fast machines unnecessarily.
   342  	const unit = 25 * Millisecond
   343  	tries := []Duration{
   344  		1 * unit,
   345  		3 * unit,
   346  		7 * unit,
   347  		15 * unit,
   348  	}
   349  	var err error
   350  	for _, d := range tries {
   351  		err = testReset(d)
   352  		if err == nil {
   353  			t.Logf("passed using duration %v", d)
   354  			return
   355  		}
   356  	}
   357  	t.Error(err)
   358  }
   359  
   360  // Test that sleeping for an interval so large it overflows does not
   361  // result in a short sleep duration.
   362  func TestOverflowSleep(t *testing.T) {
   363  	const timeout = 25 * Millisecond
   364  	const big = Duration(int64(1<<63 - 1))
   365  	select {
   366  	case <-After(big):
   367  		t.Fatalf("big timeout fired")
   368  	case <-After(timeout):
   369  		// OK
   370  	}
   371  	const neg = Duration(-1 << 63)
   372  	select {
   373  	case <-After(neg):
   374  		// OK
   375  	case <-After(timeout):
   376  		t.Fatalf("negative timeout didn't fire")
   377  	}
   378  }
   379  
   380  // Test that a panic while deleting a timer does not leave
   381  // the timers mutex held, deadlocking a ticker.Stop in a defer.
   382  func TestIssue5745(t *testing.T) {
   383  	ticker := NewTicker(Hour)
   384  	defer func() {
   385  		// would deadlock here before the fix due to
   386  		// lock taken before the segfault.
   387  		ticker.Stop()
   388  
   389  		if r := recover(); r == nil {
   390  			t.Error("Expected panic, but none happened.")
   391  		}
   392  	}()
   393  
   394  	// cause a panic due to a segfault
   395  	var timer *Timer
   396  	timer.Stop()
   397  	t.Error("Should be unreachable.")
   398  }
   399  
   400  func TestOverflowRuntimeTimer(t *testing.T) {
   401  	if err := CheckRuntimeTimerOverflow(); err != nil {
   402  		t.Fatalf(err.Error())
   403  	}
   404  }