f72f416913
From-SVN: r171732
191 lines
3.9 KiB
Go
191 lines
3.9 KiB
Go
// 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 (
|
|
"fmt"
|
|
"os"
|
|
"syscall"
|
|
"testing"
|
|
"sort"
|
|
. "time"
|
|
)
|
|
|
|
func TestSleep(t *testing.T) {
|
|
const delay = int64(100e6)
|
|
go func() {
|
|
Sleep(delay / 2)
|
|
syscall.Kill(os.Getpid(), syscall.SIGCHLD)
|
|
}()
|
|
start := Nanoseconds()
|
|
Sleep(delay)
|
|
duration := Nanoseconds() - start
|
|
if duration < delay {
|
|
t.Fatalf("Sleep(%d) slept for only %d ns", delay, duration)
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
Sleep(1e9)
|
|
} else {
|
|
c <- true
|
|
}
|
|
}
|
|
|
|
AfterFunc(0, f)
|
|
<-c
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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++ {
|
|
NewTimer(1e9).Stop()
|
|
}
|
|
}
|
|
|
|
func TestAfter(t *testing.T) {
|
|
const delay = int64(100e6)
|
|
start := Nanoseconds()
|
|
end := <-After(delay)
|
|
if duration := Nanoseconds() - start; duration < delay {
|
|
t.Fatalf("After(%d) slept for only %d ns", delay, duration)
|
|
}
|
|
if min := start + delay; end < min {
|
|
t.Fatalf("After(%d) expect >= %d, got %d", delay, min, end)
|
|
}
|
|
}
|
|
|
|
func TestAfterTick(t *testing.T) {
|
|
const (
|
|
Delta = 100 * 1e6
|
|
Count = 10
|
|
)
|
|
t0 := Nanoseconds()
|
|
for i := 0; i < Count; i++ {
|
|
<-After(Delta)
|
|
}
|
|
t1 := Nanoseconds()
|
|
ns := t1 - t0
|
|
target := int64(Delta * Count)
|
|
slop := target * 2 / 10
|
|
if ns < target-slop || ns > target+slop {
|
|
t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target))
|
|
}
|
|
}
|
|
|
|
func TestAfterStop(t *testing.T) {
|
|
const msec = 1e6
|
|
AfterFunc(100*msec, func() {})
|
|
t0 := NewTimer(50 * msec)
|
|
c1 := make(chan bool, 1)
|
|
t1 := AfterFunc(150*msec, func() { c1 <- true })
|
|
c2 := After(200 * msec)
|
|
if !t0.Stop() {
|
|
t.Fatalf("failed to stop event 0")
|
|
}
|
|
if !t1.Stop() {
|
|
t.Fatalf("failed to stop event 1")
|
|
}
|
|
<-c2
|
|
select {
|
|
case <-t0.C:
|
|
t.Fatalf("event 0 was not stopped")
|
|
case <-c1:
|
|
t.Fatalf("event 1 was not stopped")
|
|
default:
|
|
}
|
|
if t1.Stop() {
|
|
t.Fatalf("Stop returned true twice")
|
|
}
|
|
}
|
|
|
|
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
|
|
err := os.NewError("!=nil")
|
|
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)
|
|
}
|
|
}
|
|
|
|
// For gccgo omit 0 for now because it can take too long to start the
|
|
var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, /*0*/}
|
|
|
|
type afterResult struct {
|
|
slot int
|
|
t int64
|
|
}
|
|
|
|
func await(slot int, result chan<- afterResult, ac <-chan int64) {
|
|
result <- afterResult{slot, <-ac}
|
|
}
|
|
|
|
func testAfterQueuing(t *testing.T) os.Error {
|
|
const (
|
|
Delta = 100 * 1e6
|
|
)
|
|
// 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))
|
|
|
|
t0 := Nanoseconds()
|
|
for _, slot := range slots {
|
|
go await(slot, result, After(int64(slot)*Delta))
|
|
}
|
|
sort.SortInts(slots)
|
|
for _, slot := range slots {
|
|
r := <-result
|
|
if r.slot != slot {
|
|
return fmt.Errorf("after queue got slot %d, expected %d", r.slot, slot)
|
|
}
|
|
ns := r.t - t0
|
|
target := int64(slot * Delta)
|
|
slop := int64(Delta) / 4
|
|
if ns < target-slop || ns > target+slop {
|
|
return fmt.Errorf("after queue slot %d arrived at %g, expected [%g,%g]", slot, float64(ns), float64(target-slop), float64(target+slop))
|
|
}
|
|
}
|
|
return nil
|
|
}
|