PR middle-end/81768
[official-gcc.git] / libgo / go / time / sleep_test.go
blobc286bd0027371c2f00d2746a32101da1f214983e
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.
5 package time_test
7 import (
8 "errors"
9 "fmt"
10 "runtime"
11 "strings"
12 "sync"
13 "sync/atomic"
14 "testing"
15 . "time"
18 // Go runtime uses different Windows timers for time.Now and sleeping.
19 // These can tick at different frequencies and can arrive out of sync.
20 // The effect can be seen, for example, as time.Sleep(100ms) is actually
21 // shorter then 100ms when measured as difference between time.Now before and
22 // after time.Sleep call. This was observed on Windows XP SP3 (windows/386).
23 // windowsInaccuracy is to ignore such errors.
24 const windowsInaccuracy = 17 * Millisecond
26 func TestSleep(t *testing.T) {
27 const delay = 100 * Millisecond
28 go func() {
29 Sleep(delay / 2)
30 Interrupt()
31 }()
32 start := Now()
33 Sleep(delay)
34 delayadj := delay
35 if runtime.GOOS == "windows" {
36 delayadj -= windowsInaccuracy
38 duration := Now().Sub(start)
39 if duration < delayadj {
40 t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
44 // Test the basic function calling behavior. Correct queueing
45 // behavior is tested elsewhere, since After and AfterFunc share
46 // the same code.
47 func TestAfterFunc(t *testing.T) {
48 i := 10
49 c := make(chan bool)
50 var f func()
51 f = func() {
52 i--
53 if i >= 0 {
54 AfterFunc(0, f)
55 Sleep(1 * Second)
56 } else {
57 c <- true
61 AfterFunc(0, f)
62 <-c
65 func TestAfterStress(t *testing.T) {
66 stop := uint32(0)
67 go func() {
68 for atomic.LoadUint32(&stop) == 0 {
69 runtime.GC()
70 // Yield so that the OS can wake up the timer thread,
71 // so that it can generate channel sends for the main goroutine,
72 // which will eventually set stop = 1 for us.
73 Sleep(Nanosecond)
75 }()
76 ticker := NewTicker(1)
77 for i := 0; i < 100; i++ {
78 <-ticker.C
80 ticker.Stop()
81 atomic.StoreUint32(&stop, 1)
84 func benchmark(b *testing.B, bench func(n int)) {
85 garbage := make([]*Timer, 1<<17)
86 for i := 0; i < len(garbage); i++ {
87 garbage[i] = AfterFunc(Hour, nil)
89 b.ResetTimer()
91 b.RunParallel(func(pb *testing.PB) {
92 for pb.Next() {
93 bench(1000)
97 b.StopTimer()
98 for i := 0; i < len(garbage); i++ {
99 garbage[i].Stop()
103 func BenchmarkAfterFunc(b *testing.B) {
104 benchmark(b, func(n int) {
105 c := make(chan bool)
106 var f func()
107 f = func() {
109 if n >= 0 {
110 AfterFunc(0, f)
111 } else {
112 c <- true
116 AfterFunc(0, f)
121 func BenchmarkAfter(b *testing.B) {
122 benchmark(b, func(n int) {
123 for i := 0; i < n; i++ {
124 <-After(1)
129 func BenchmarkStop(b *testing.B) {
130 benchmark(b, func(n int) {
131 for i := 0; i < n; i++ {
132 NewTimer(1 * Second).Stop()
137 func BenchmarkSimultaneousAfterFunc(b *testing.B) {
138 benchmark(b, func(n int) {
139 var wg sync.WaitGroup
140 wg.Add(n)
141 for i := 0; i < n; i++ {
142 AfterFunc(0, wg.Done)
144 wg.Wait()
148 func BenchmarkStartStop(b *testing.B) {
149 benchmark(b, func(n int) {
150 timers := make([]*Timer, n)
151 for i := 0; i < n; i++ {
152 timers[i] = AfterFunc(Hour, nil)
155 for i := 0; i < n; i++ {
156 timers[i].Stop()
161 func TestAfter(t *testing.T) {
162 const delay = 100 * Millisecond
163 start := Now()
164 end := <-After(delay)
165 delayadj := delay
166 if runtime.GOOS == "windows" {
167 delayadj -= windowsInaccuracy
169 if duration := Now().Sub(start); duration < delayadj {
170 t.Fatalf("After(%s) slept for only %d ns", delay, duration)
172 if min := start.Add(delayadj); end.Before(min) {
173 t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
177 func TestAfterTick(t *testing.T) {
178 const Count = 10
179 Delta := 100 * Millisecond
180 if testing.Short() {
181 Delta = 10 * Millisecond
183 t0 := Now()
184 for i := 0; i < Count; i++ {
185 <-After(Delta)
187 t1 := Now()
188 d := t1.Sub(t0)
189 target := Delta * Count
190 if d < target*9/10 {
191 t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target)
193 if !testing.Short() && d > target*30/10 {
194 t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target)
198 func TestAfterStop(t *testing.T) {
199 AfterFunc(100*Millisecond, func() {})
200 t0 := NewTimer(50 * Millisecond)
201 c1 := make(chan bool, 1)
202 t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
203 c2 := After(200 * Millisecond)
204 if !t0.Stop() {
205 t.Fatalf("failed to stop event 0")
207 if !t1.Stop() {
208 t.Fatalf("failed to stop event 1")
210 <-c2
211 select {
212 case <-t0.C:
213 t.Fatalf("event 0 was not stopped")
214 case <-c1:
215 t.Fatalf("event 1 was not stopped")
216 default:
218 if t1.Stop() {
219 t.Fatalf("Stop returned true twice")
223 func TestAfterQueuing(t *testing.T) {
224 // This test flakes out on some systems,
225 // so we'll try it a few times before declaring it a failure.
226 const attempts = 5
227 err := errors.New("!=nil")
228 for i := 0; i < attempts && err != nil; i++ {
229 delta := Duration(20+i*50) * Millisecond
230 if err = testAfterQueuing(t, delta); err != nil {
231 t.Logf("attempt %v failed: %v", i, err)
234 if err != nil {
235 t.Fatal(err)
239 // For gccgo omit 0 for now because it can take too long to start the
240 var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8 /*0*/}
242 type afterResult struct {
243 slot int
244 t Time
247 func await(slot int, result chan<- afterResult, ac <-chan Time) {
248 result <- afterResult{slot, <-ac}
251 func testAfterQueuing(t *testing.T, delta Duration) error {
252 // make the result channel buffered because we don't want
253 // to depend on channel queueing semantics that might
254 // possibly change in the future.
255 result := make(chan afterResult, len(slots))
257 t0 := Now()
258 for _, slot := range slots {
259 go await(slot, result, After(Duration(slot)*delta))
261 var order []int
262 var times []Time
263 for range slots {
264 r := <-result
265 order = append(order, r.slot)
266 times = append(times, r.t)
268 for i := range order {
269 if i > 0 && order[i] < order[i-1] {
270 return fmt.Errorf("After calls returned out of order: %v", order)
273 for i, t := range times {
274 dt := t.Sub(t0)
275 target := Duration(order[i]) * delta
276 if dt < target-delta/2 || dt > target+delta*10 {
277 return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-delta/2, target+delta*10)
280 return nil
283 func TestTimerStopStress(t *testing.T) {
284 if testing.Short() {
285 return
287 for i := 0; i < 100; i++ {
288 go func(i int) {
289 timer := AfterFunc(2*Second, func() {
290 t.Fatalf("timer %d was not stopped", i)
292 Sleep(1 * Second)
293 timer.Stop()
294 }(i)
296 Sleep(3 * Second)
299 func TestSleepZeroDeadlock(t *testing.T) {
300 // Sleep(0) used to hang, the sequence of events was as follows.
301 // Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
302 // Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
303 // After the GC nobody wakes up the goroutine from Gwaiting status.
304 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
305 c := make(chan bool)
306 go func() {
307 for i := 0; i < 100; i++ {
308 runtime.GC()
310 c <- true
312 for i := 0; i < 100; i++ {
313 Sleep(0)
314 tmp := make(chan bool, 1)
315 tmp <- true
316 <-tmp
321 func testReset(d Duration) error {
322 t0 := NewTimer(2 * d)
323 Sleep(d)
324 if t0.Reset(3*d) != true {
325 return errors.New("resetting unfired timer returned false")
327 Sleep(2 * d)
328 select {
329 case <-t0.C:
330 return errors.New("timer fired early")
331 default:
333 Sleep(2 * d)
334 select {
335 case <-t0.C:
336 default:
337 return errors.New("reset timer did not fire")
340 if t0.Reset(50*Millisecond) != false {
341 return errors.New("resetting expired timer returned true")
343 return nil
346 func TestReset(t *testing.T) {
347 // We try to run this test with increasingly larger multiples
348 // until one works so slow, loaded hardware isn't as flaky,
349 // but without slowing down fast machines unnecessarily.
350 const unit = 25 * Millisecond
351 tries := []Duration{
352 1 * unit,
353 3 * unit,
354 7 * unit,
355 15 * unit,
357 var err error
358 for _, d := range tries {
359 err = testReset(d)
360 if err == nil {
361 t.Logf("passed using duration %v", d)
362 return
365 t.Error(err)
368 // Test that sleeping for an interval so large it overflows does not
369 // result in a short sleep duration.
370 func TestOverflowSleep(t *testing.T) {
371 const big = Duration(int64(1<<63 - 1))
372 select {
373 case <-After(big):
374 t.Fatalf("big timeout fired")
375 case <-After(25 * Millisecond):
376 // OK
378 const neg = Duration(-1 << 63)
379 select {
380 case <-After(neg):
381 // OK
382 case <-After(1 * Second):
383 t.Fatalf("negative timeout didn't fire")
387 // Test that a panic while deleting a timer does not leave
388 // the timers mutex held, deadlocking a ticker.Stop in a defer.
389 func TestIssue5745(t *testing.T) {
390 if runtime.GOOS == "darwin" && runtime.GOARCH == "arm" {
391 t.Skipf("skipping on %s/%s, see issue 10043", runtime.GOOS, runtime.GOARCH)
394 ticker := NewTicker(Hour)
395 defer func() {
396 // would deadlock here before the fix due to
397 // lock taken before the segfault.
398 ticker.Stop()
400 if r := recover(); r == nil {
401 t.Error("Expected panic, but none happened.")
405 // cause a panic due to a segfault
406 var timer *Timer
407 timer.Stop()
408 t.Error("Should be unreachable.")
411 func TestOverflowRuntimeTimer(t *testing.T) {
412 if testing.Short() {
413 t.Skip("skipping in short mode, see issue 6874")
415 // This may hang forever if timers are broken. See comment near
416 // the end of CheckRuntimeTimerOverflow in internal_test.go.
417 CheckRuntimeTimerOverflow()
420 func checkZeroPanicString(t *testing.T) {
421 e := recover()
422 s, _ := e.(string)
423 if want := "called on uninitialized Timer"; !strings.Contains(s, want) {
424 t.Errorf("panic = %v; want substring %q", e, want)
428 func TestZeroTimerResetPanics(t *testing.T) {
429 defer checkZeroPanicString(t)
430 var tr Timer
431 tr.Reset(1)
434 func TestZeroTimerStopPanics(t *testing.T) {
435 defer checkZeroPanicString(t)
436 var tr Timer
437 tr.Stop()