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