| // 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) | |
| } | |
| } | |
| 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 | |
| } |