2010-02-04 14:09:02 -07:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package time_test
|
|
|
|
|
|
|
|
import (
|
2011-11-01 20:05:34 -06:00
|
|
|
"errors"
|
2011-03-29 18:40:00 -06:00
|
|
|
"fmt"
|
2011-11-14 11:59:48 -07:00
|
|
|
"runtime"
|
2010-12-06 12:19:30 -07:00
|
|
|
"sort"
|
2011-11-14 11:59:48 -07:00
|
|
|
"sync/atomic"
|
2011-11-02 13:54:16 -06:00
|
|
|
"testing"
|
2010-02-04 14:09:02 -07:00
|
|
|
. "time"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestSleep(t *testing.T) {
|
2011-11-30 09:59:44 -07:00
|
|
|
const delay = 100 * Millisecond
|
2010-02-04 14:09:02 -07:00
|
|
|
go func() {
|
|
|
|
Sleep(delay / 2)
|
2011-08-26 13:15:23 -06:00
|
|
|
Interrupt()
|
2010-02-04 14:09:02 -07:00
|
|
|
}()
|
2011-11-30 09:59:44 -07:00
|
|
|
start := Now()
|
2010-02-04 14:09:02 -07:00
|
|
|
Sleep(delay)
|
2011-11-30 09:59:44 -07:00
|
|
|
duration := Now().Sub(start)
|
2010-02-04 14:09:02 -07:00
|
|
|
if duration < delay {
|
2011-11-30 09:59:44 -07:00
|
|
|
t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
|
2010-02-04 14:09:02 -07:00
|
|
|
}
|
|
|
|
}
|
2010-10-10 20:45:26 -06:00
|
|
|
|
2011-01-10 12:51:38 -07:00
|
|
|
// Test the basic function calling behavior. Correct queueing
|
|
|
|
// behavior is tested elsewhere, since After and AfterFunc share
|
|
|
|
// the same code.
|
|
|
|
func TestAfterFunc(t *testing.T) {
|
|
|
|
i := 10
|
|
|
|
c := make(chan bool)
|
|
|
|
var f func()
|
|
|
|
f = func() {
|
|
|
|
i--
|
|
|
|
if i >= 0 {
|
|
|
|
AfterFunc(0, f)
|
2011-12-07 21:42:44 -07:00
|
|
|
Sleep(1 * Second)
|
2011-01-10 12:51:38 -07:00
|
|
|
} else {
|
|
|
|
c <- true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AfterFunc(0, f)
|
|
|
|
<-c
|
|
|
|
}
|
|
|
|
|
2011-11-14 11:59:48 -07:00
|
|
|
func TestAfterStress(t *testing.T) {
|
|
|
|
stop := uint32(0)
|
|
|
|
go func() {
|
|
|
|
for atomic.LoadUint32(&stop) == 0 {
|
|
|
|
runtime.GC()
|
2013-01-17 21:31:01 -07:00
|
|
|
// Yield so that the OS can wake up the timer thread,
|
|
|
|
// so that it can generate channel sends for the main goroutine,
|
|
|
|
// which will eventually set stop = 1 for us.
|
|
|
|
Sleep(Nanosecond)
|
2011-11-14 11:59:48 -07:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
c := Tick(1)
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
<-c
|
|
|
|
}
|
|
|
|
atomic.StoreUint32(&stop, 1)
|
|
|
|
}
|
|
|
|
|
2011-01-10 12:51:38 -07:00
|
|
|
func BenchmarkAfterFunc(b *testing.B) {
|
|
|
|
i := b.N
|
|
|
|
c := make(chan bool)
|
|
|
|
var f func()
|
|
|
|
f = func() {
|
|
|
|
i--
|
|
|
|
if i >= 0 {
|
|
|
|
AfterFunc(0, f)
|
|
|
|
} else {
|
|
|
|
c <- true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AfterFunc(0, f)
|
|
|
|
<-c
|
|
|
|
}
|
|
|
|
|
2011-01-25 13:25:48 -07:00
|
|
|
func BenchmarkAfter(b *testing.B) {
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
<-After(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkStop(b *testing.B) {
|
|
|
|
for i := 0; i < b.N; i++ {
|
2011-12-07 21:42:44 -07:00
|
|
|
NewTimer(1 * Second).Stop()
|
2011-01-25 13:25:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-10 20:45:26 -06:00
|
|
|
func TestAfter(t *testing.T) {
|
2011-11-30 09:59:44 -07:00
|
|
|
const delay = 100 * Millisecond
|
|
|
|
start := Now()
|
2010-10-10 20:45:26 -06:00
|
|
|
end := <-After(delay)
|
2011-11-30 09:59:44 -07:00
|
|
|
if duration := Now().Sub(start); duration < delay {
|
|
|
|
t.Fatalf("After(%s) slept for only %d ns", delay, duration)
|
2010-10-10 20:45:26 -06:00
|
|
|
}
|
2011-11-30 09:59:44 -07:00
|
|
|
if min := start.Add(delay); end.Before(min) {
|
|
|
|
t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
|
2010-10-10 20:45:26 -06:00
|
|
|
}
|
|
|
|
}
|
2010-12-06 12:19:30 -07:00
|
|
|
|
|
|
|
func TestAfterTick(t *testing.T) {
|
2012-02-14 14:13:19 -07:00
|
|
|
const Count = 10
|
|
|
|
Delta := 100 * Millisecond
|
|
|
|
if testing.Short() {
|
|
|
|
Delta = 10 * Millisecond
|
|
|
|
}
|
2011-11-30 09:59:44 -07:00
|
|
|
t0 := Now()
|
2010-12-06 12:19:30 -07:00
|
|
|
for i := 0; i < Count; i++ {
|
|
|
|
<-After(Delta)
|
|
|
|
}
|
2011-11-30 09:59:44 -07:00
|
|
|
t1 := Now()
|
|
|
|
d := t1.Sub(t0)
|
|
|
|
target := Delta * Count
|
2012-02-29 14:14:05 -07:00
|
|
|
if d < target*9/10 {
|
|
|
|
t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target)
|
|
|
|
}
|
|
|
|
if !testing.Short() && d > target*30/10 {
|
|
|
|
t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target)
|
2010-12-06 12:19:30 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-25 13:25:48 -07:00
|
|
|
func TestAfterStop(t *testing.T) {
|
2011-12-07 21:42:44 -07:00
|
|
|
AfterFunc(100*Millisecond, func() {})
|
|
|
|
t0 := NewTimer(50 * Millisecond)
|
2011-01-25 13:25:48 -07:00
|
|
|
c1 := make(chan bool, 1)
|
2011-12-07 21:42:44 -07:00
|
|
|
t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
|
|
|
|
c2 := After(200 * Millisecond)
|
2011-01-25 13:25:48 -07:00
|
|
|
if !t0.Stop() {
|
|
|
|
t.Fatalf("failed to stop event 0")
|
|
|
|
}
|
|
|
|
if !t1.Stop() {
|
|
|
|
t.Fatalf("failed to stop event 1")
|
|
|
|
}
|
|
|
|
<-c2
|
2011-01-31 16:36:28 -07:00
|
|
|
select {
|
|
|
|
case <-t0.C:
|
|
|
|
t.Fatalf("event 0 was not stopped")
|
|
|
|
case <-c1:
|
|
|
|
t.Fatalf("event 1 was not stopped")
|
|
|
|
default:
|
2011-01-25 13:25:48 -07:00
|
|
|
}
|
|
|
|
if t1.Stop() {
|
|
|
|
t.Fatalf("Stop returned true twice")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-29 18:40:00 -06:00
|
|
|
func TestAfterQueuing(t *testing.T) {
|
|
|
|
// This test flakes out on some systems,
|
|
|
|
// so we'll try it a few times before declaring it a failure.
|
|
|
|
const attempts = 3
|
2011-11-01 20:05:34 -06:00
|
|
|
err := errors.New("!=nil")
|
2011-03-29 18:40:00 -06:00
|
|
|
for i := 0; i < attempts && err != nil; i++ {
|
|
|
|
if err = testAfterQueuing(t); err != nil {
|
|
|
|
t.Logf("attempt %v failed: %v", i, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-06 12:19:30 -07:00
|
|
|
var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}
|
|
|
|
|
|
|
|
type afterResult struct {
|
|
|
|
slot int
|
2011-11-30 09:59:44 -07:00
|
|
|
t Time
|
2010-12-06 12:19:30 -07:00
|
|
|
}
|
|
|
|
|
2011-11-30 09:59:44 -07:00
|
|
|
func await(slot int, result chan<- afterResult, ac <-chan Time) {
|
2010-12-06 12:19:30 -07:00
|
|
|
result <- afterResult{slot, <-ac}
|
|
|
|
}
|
|
|
|
|
2011-11-01 20:05:34 -06:00
|
|
|
func testAfterQueuing(t *testing.T) error {
|
2012-02-14 14:13:19 -07:00
|
|
|
Delta := 100 * Millisecond
|
|
|
|
if testing.Short() {
|
|
|
|
Delta = 20 * Millisecond
|
|
|
|
}
|
2010-12-06 12:19:30 -07:00
|
|
|
// make the result channel buffered because we don't want
|
|
|
|
// to depend on channel queueing semantics that might
|
|
|
|
// possibly change in the future.
|
|
|
|
result := make(chan afterResult, len(slots))
|
|
|
|
|
2011-11-30 09:59:44 -07:00
|
|
|
t0 := Now()
|
2010-12-06 12:19:30 -07:00
|
|
|
for _, slot := range slots {
|
2011-11-30 09:59:44 -07:00
|
|
|
go await(slot, result, After(Duration(slot)*Delta))
|
2010-12-06 12:19:30 -07:00
|
|
|
}
|
2011-07-07 18:52:50 -06:00
|
|
|
sort.Ints(slots)
|
2010-12-06 12:19:30 -07:00
|
|
|
for _, slot := range slots {
|
|
|
|
r := <-result
|
|
|
|
if r.slot != slot {
|
2011-11-30 09:59:44 -07:00
|
|
|
return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
|
2010-12-06 12:19:30 -07:00
|
|
|
}
|
2011-11-30 09:59:44 -07:00
|
|
|
dt := r.t.Sub(t0)
|
|
|
|
target := Duration(slot) * Delta
|
2011-12-12 16:33:47 -07:00
|
|
|
if dt < target-Delta/2 || dt > target+Delta*10 {
|
|
|
|
return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
|
2010-12-06 12:19:30 -07:00
|
|
|
}
|
|
|
|
}
|
2011-03-29 18:40:00 -06:00
|
|
|
return nil
|
2010-12-06 12:19:30 -07:00
|
|
|
}
|
2011-11-25 04:13:10 -07:00
|
|
|
|
|
|
|
func TestTimerStopStress(t *testing.T) {
|
|
|
|
if testing.Short() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
go func(i int) {
|
2011-12-07 21:42:44 -07:00
|
|
|
timer := AfterFunc(2*Second, func() {
|
2011-11-25 04:13:10 -07:00
|
|
|
t.Fatalf("timer %d was not stopped", i)
|
|
|
|
})
|
2011-12-07 21:42:44 -07:00
|
|
|
Sleep(1 * Second)
|
2011-11-25 04:13:10 -07:00
|
|
|
timer.Stop()
|
|
|
|
}(i)
|
|
|
|
}
|
2011-12-07 21:42:44 -07:00
|
|
|
Sleep(3 * Second)
|
2011-11-25 04:13:10 -07:00
|
|
|
}
|
2012-05-29 12:30:56 -06:00
|
|
|
|
|
|
|
func TestSleepZeroDeadlock(t *testing.T) {
|
|
|
|
// Sleep(0) used to hang, the sequence of events was as follows.
|
|
|
|
// Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
|
|
|
|
// Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
|
|
|
|
// After the GC nobody wakes up the goroutine from Gwaiting status.
|
|
|
|
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
|
|
|
|
c := make(chan bool)
|
|
|
|
go func() {
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
runtime.GC()
|
|
|
|
}
|
|
|
|
c <- true
|
|
|
|
}()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
Sleep(0)
|
|
|
|
tmp := make(chan bool, 1)
|
|
|
|
tmp <- true
|
|
|
|
<-tmp
|
|
|
|
}
|
|
|
|
<-c
|
|
|
|
}
|
2013-01-16 20:41:53 -07:00
|
|
|
|
|
|
|
func TestReset(t *testing.T) {
|
|
|
|
t0 := NewTimer(100 * Millisecond)
|
|
|
|
Sleep(50 * Millisecond)
|
|
|
|
if t0.Reset(150*Millisecond) != true {
|
|
|
|
t.Fatalf("resetting unfired timer returned false")
|
|
|
|
}
|
|
|
|
Sleep(100 * Millisecond)
|
|
|
|
select {
|
|
|
|
case <-t0.C:
|
|
|
|
t.Fatalf("timer fired early")
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
Sleep(100 * Millisecond)
|
|
|
|
select {
|
|
|
|
case <-t0.C:
|
|
|
|
default:
|
|
|
|
t.Fatalf("reset timer did not fire")
|
|
|
|
}
|
|
|
|
|
|
|
|
if t0.Reset(50*Millisecond) != false {
|
|
|
|
t.Fatalf("resetting expired timer returned true")
|
|
|
|
}
|
|
|
|
}
|