github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/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 const akarosInaccuracy = 10 * Millisecond 27 28 func TestSleep(t *testing.T) { 29 const delay = 100 * Millisecond 30 go func() { 31 Sleep(delay / 2) 32 Interrupt() 33 }() 34 start := Now() 35 Sleep(delay) 36 delayadj := delay 37 if runtime.GOOS == "windows" { 38 delayadj -= windowsInaccuracy 39 } 40 if runtime.GOOS == "akaros" { 41 delayadj -= akarosInaccuracy 42 } 43 duration := Now().Sub(start) 44 if duration < delayadj { 45 t.Fatalf("Sleep(%s) slept for only %s", delay, duration) 46 } 47 } 48 49 // Test the basic function calling behavior. Correct queueing 50 // behavior is tested elsewhere, since After and AfterFunc share 51 // the same code. 52 func TestAfterFunc(t *testing.T) { 53 i := 10 54 c := make(chan bool) 55 var f func() 56 f = func() { 57 i-- 58 if i >= 0 { 59 AfterFunc(0, f) 60 Sleep(1 * Second) 61 } else { 62 c <- true 63 } 64 } 65 66 AfterFunc(0, f) 67 <-c 68 } 69 70 func TestAfterStress(t *testing.T) { 71 stop := uint32(0) 72 go func() { 73 for atomic.LoadUint32(&stop) == 0 { 74 runtime.GC() 75 // Yield so that the OS can wake up the timer thread, 76 // so that it can generate channel sends for the main goroutine, 77 // which will eventually set stop = 1 for us. 78 Sleep(Nanosecond) 79 } 80 }() 81 ticker := NewTicker(1) 82 for i := 0; i < 100; i++ { 83 <-ticker.C 84 } 85 ticker.Stop() 86 atomic.StoreUint32(&stop, 1) 87 } 88 89 func benchmark(b *testing.B, bench func(n int)) { 90 garbage := make([]*Timer, 1<<17) 91 for i := 0; i < len(garbage); i++ { 92 garbage[i] = AfterFunc(Hour, nil) 93 } 94 b.ResetTimer() 95 96 b.RunParallel(func(pb *testing.PB) { 97 for pb.Next() { 98 bench(1000) 99 } 100 }) 101 102 b.StopTimer() 103 for i := 0; i < len(garbage); i++ { 104 garbage[i].Stop() 105 } 106 } 107 108 func BenchmarkAfterFunc(b *testing.B) { 109 benchmark(b, func(n int) { 110 c := make(chan bool) 111 var f func() 112 f = func() { 113 n-- 114 if n >= 0 { 115 AfterFunc(0, f) 116 } else { 117 c <- true 118 } 119 } 120 121 AfterFunc(0, f) 122 <-c 123 }) 124 } 125 126 func BenchmarkAfter(b *testing.B) { 127 benchmark(b, func(n int) { 128 for i := 0; i < n; i++ { 129 <-After(1) 130 } 131 }) 132 } 133 134 func BenchmarkStop(b *testing.B) { 135 benchmark(b, func(n int) { 136 for i := 0; i < n; i++ { 137 NewTimer(1 * Second).Stop() 138 } 139 }) 140 } 141 142 func BenchmarkSimultaneousAfterFunc(b *testing.B) { 143 benchmark(b, func(n int) { 144 var wg sync.WaitGroup 145 wg.Add(n) 146 for i := 0; i < n; i++ { 147 AfterFunc(0, wg.Done) 148 } 149 wg.Wait() 150 }) 151 } 152 153 func BenchmarkStartStop(b *testing.B) { 154 benchmark(b, func(n int) { 155 timers := make([]*Timer, n) 156 for i := 0; i < n; i++ { 157 timers[i] = AfterFunc(Hour, nil) 158 } 159 160 for i := 0; i < n; i++ { 161 timers[i].Stop() 162 } 163 }) 164 } 165 166 func TestAfter(t *testing.T) { 167 const delay = 100 * Millisecond 168 start := Now() 169 end := <-After(delay) 170 delayadj := delay 171 if runtime.GOOS == "windows" { 172 delayadj -= windowsInaccuracy 173 } 174 if duration := Now().Sub(start); duration < delayadj { 175 t.Fatalf("After(%s) slept for only %d ns", delay, duration) 176 } 177 if min := start.Add(delayadj); end.Before(min) { 178 t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end) 179 } 180 } 181 182 func TestAfterTick(t *testing.T) { 183 const Count = 10 184 Delta := 100 * Millisecond 185 if testing.Short() { 186 Delta = 10 * Millisecond 187 } 188 t0 := Now() 189 for i := 0; i < Count; i++ { 190 <-After(Delta) 191 } 192 t1 := Now() 193 d := t1.Sub(t0) 194 target := Delta * Count 195 if d < target*9/10 { 196 t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target) 197 } 198 if !testing.Short() && d > target*30/10 { 199 t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target) 200 } 201 } 202 203 func TestAfterStop(t *testing.T) { 204 AfterFunc(100*Millisecond, func() {}) 205 t0 := NewTimer(50 * Millisecond) 206 c1 := make(chan bool, 1) 207 t1 := AfterFunc(150*Millisecond, func() { c1 <- true }) 208 c2 := After(200 * Millisecond) 209 if !t0.Stop() { 210 t.Fatalf("failed to stop event 0") 211 } 212 if !t1.Stop() { 213 t.Fatalf("failed to stop event 1") 214 } 215 <-c2 216 select { 217 case <-t0.C: 218 t.Fatalf("event 0 was not stopped") 219 case <-c1: 220 t.Fatalf("event 1 was not stopped") 221 default: 222 } 223 if t1.Stop() { 224 t.Fatalf("Stop returned true twice") 225 } 226 } 227 228 func TestAfterQueuing(t *testing.T) { 229 // This test flakes out on some systems, 230 // so we'll try it a few times before declaring it a failure. 231 const attempts = 3 232 err := errors.New("!=nil") 233 for i := 0; i < attempts && err != nil; i++ { 234 if err = testAfterQueuing(t); err != nil { 235 t.Logf("attempt %v failed: %v", i, err) 236 } 237 } 238 if err != nil { 239 t.Fatal(err) 240 } 241 } 242 243 var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0} 244 245 type afterResult struct { 246 slot int 247 t Time 248 } 249 250 func await(slot int, result chan<- afterResult, ac <-chan Time) { 251 result <- afterResult{slot, <-ac} 252 } 253 254 func testAfterQueuing(t *testing.T) error { 255 Delta := 100 * Millisecond 256 if testing.Short() { 257 Delta = 20 * Millisecond 258 } 259 // make the result channel buffered because we don't want 260 // to depend on channel queueing semantics that might 261 // possibly change in the future. 262 result := make(chan afterResult, len(slots)) 263 264 t0 := Now() 265 for _, slot := range slots { 266 go await(slot, result, After(Duration(slot)*Delta)) 267 } 268 sort.Ints(slots) 269 for _, slot := range slots { 270 r := <-result 271 if r.slot != slot { 272 return fmt.Errorf("after slot %d, expected %d", r.slot, slot) 273 } 274 dt := r.t.Sub(t0) 275 target := Duration(slot) * 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) 278 } 279 } 280 return nil 281 } 282 283 func TestTimerStopStress(t *testing.T) { 284 if testing.Short() { 285 return 286 } 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) 291 }) 292 Sleep(1 * Second) 293 timer.Stop() 294 }(i) 295 } 296 Sleep(3 * Second) 297 } 298 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() 309 } 310 c <- true 311 }() 312 for i := 0; i < 100; i++ { 313 Sleep(0) 314 tmp := make(chan bool, 1) 315 tmp <- true 316 <-tmp 317 } 318 <-c 319 } 320 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") 326 } 327 Sleep(2 * d) 328 select { 329 case <-t0.C: 330 return errors.New("timer fired early") 331 default: 332 } 333 Sleep(2 * d) 334 select { 335 case <-t0.C: 336 default: 337 return errors.New("reset timer did not fire") 338 } 339 340 if t0.Reset(50*Millisecond) != false { 341 return errors.New("resetting expired timer returned true") 342 } 343 return nil 344 } 345 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, 356 } 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 363 } 364 } 365 t.Error(err) 366 } 367 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 377 } 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") 384 } 385 } 386 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 ticker := NewTicker(Hour) 391 defer func() { 392 // would deadlock here before the fix due to 393 // lock taken before the segfault. 394 ticker.Stop() 395 396 if r := recover(); r == nil { 397 t.Error("Expected panic, but none happened.") 398 } 399 }() 400 401 // cause a panic due to a segfault 402 var timer *Timer 403 timer.Stop() 404 t.Error("Should be unreachable.") 405 } 406 407 func TestOverflowRuntimeTimer(t *testing.T) { 408 if testing.Short() { 409 t.Skip("skipping in short mode, see issue 6874") 410 } 411 // This may hang forever if timers are broken. See comment near 412 // the end of CheckRuntimeTimerOverflow in internal_test.go. 413 CheckRuntimeTimerOverflow() 414 } 415 416 func checkZeroPanicString(t *testing.T) { 417 e := recover() 418 s, _ := e.(string) 419 if want := "called on uninitialized Timer"; !strings.Contains(s, want) { 420 t.Errorf("panic = %v; want substring %q", e, want) 421 } 422 } 423 424 func TestZeroTimerResetPanics(t *testing.T) { 425 defer checkZeroPanicString(t) 426 var tr Timer 427 tr.Reset(1) 428 } 429 430 func TestZeroTimerStopPanics(t *testing.T) { 431 defer checkZeroPanicString(t) 432 var tr Timer 433 tr.Stop() 434 }