github.com/axw/llgo@v0.0.0-20160805011314-95b5fe4dca20/third_party/gofrontend/libgo/go/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 "strings" 12 "sync" 13 "sync/atomic" 14 "testing" 15 . "time" 16 ) 17 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 25 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 37 } 38 duration := Now().Sub(start) 39 if duration < delayadj { 40 t.Fatalf("Sleep(%s) slept for only %s", delay, duration) 41 } 42 } 43 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 58 } 59 } 60 61 AfterFunc(0, f) 62 <-c 63 } 64 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) 74 } 75 }() 76 ticker := NewTicker(1) 77 for i := 0; i < 100; i++ { 78 <-ticker.C 79 } 80 ticker.Stop() 81 atomic.StoreUint32(&stop, 1) 82 } 83 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) 88 } 89 b.ResetTimer() 90 91 b.RunParallel(func(pb *testing.PB) { 92 for pb.Next() { 93 bench(1000) 94 } 95 }) 96 97 b.StopTimer() 98 for i := 0; i < len(garbage); i++ { 99 garbage[i].Stop() 100 } 101 } 102 103 func BenchmarkAfterFunc(b *testing.B) { 104 benchmark(b, func(n int) { 105 c := make(chan bool) 106 var f func() 107 f = func() { 108 n-- 109 if n >= 0 { 110 AfterFunc(0, f) 111 } else { 112 c <- true 113 } 114 } 115 116 AfterFunc(0, f) 117 <-c 118 }) 119 } 120 121 func BenchmarkAfter(b *testing.B) { 122 benchmark(b, func(n int) { 123 for i := 0; i < n; i++ { 124 <-After(1) 125 } 126 }) 127 } 128 129 func BenchmarkStop(b *testing.B) { 130 benchmark(b, func(n int) { 131 for i := 0; i < n; i++ { 132 NewTimer(1 * Second).Stop() 133 } 134 }) 135 } 136 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) 143 } 144 wg.Wait() 145 }) 146 } 147 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) 153 } 154 155 for i := 0; i < n; i++ { 156 timers[i].Stop() 157 } 158 }) 159 } 160 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 168 } 169 if duration := Now().Sub(start); duration < delayadj { 170 t.Fatalf("After(%s) slept for only %d ns", delay, duration) 171 } 172 if min := start.Add(delayadj); end.Before(min) { 173 t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end) 174 } 175 } 176 177 func TestAfterTick(t *testing.T) { 178 const Count = 10 179 Delta := 100 * Millisecond 180 if testing.Short() { 181 Delta = 10 * Millisecond 182 } 183 t0 := Now() 184 for i := 0; i < Count; i++ { 185 <-After(Delta) 186 } 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) 192 } 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) 195 } 196 } 197 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") 206 } 207 if !t1.Stop() { 208 t.Fatalf("failed to stop event 1") 209 } 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: 217 } 218 if t1.Stop() { 219 t.Fatalf("Stop returned true twice") 220 } 221 } 222 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) 232 } 233 } 234 if err != nil { 235 t.Fatal(err) 236 } 237 } 238 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*/} 241 242 type afterResult struct { 243 slot int 244 t Time 245 } 246 247 func await(slot int, result chan<- afterResult, ac <-chan Time) { 248 result <- afterResult{slot, <-ac} 249 } 250 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)) 256 257 t0 := Now() 258 for _, slot := range slots { 259 go await(slot, result, After(Duration(slot)*delta)) 260 } 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) 267 } 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) 271 } 272 } 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) 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 if runtime.GOOS == "darwin" && runtime.GOARCH == "arm" { 391 t.Skipf("skipping on %s/%s, see issue 10043", runtime.GOOS, runtime.GOARCH) 392 } 393 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() 399 400 if r := recover(); r == nil { 401 t.Error("Expected panic, but none happened.") 402 } 403 }() 404 405 // cause a panic due to a segfault 406 var timer *Timer 407 timer.Stop() 408 t.Error("Should be unreachable.") 409 } 410 411 func TestOverflowRuntimeTimer(t *testing.T) { 412 if testing.Short() { 413 t.Skip("skipping in short mode, see issue 6874") 414 } 415 // This may hang forever if timers are broken. See comment near 416 // the end of CheckRuntimeTimerOverflow in internal_test.go. 417 CheckRuntimeTimerOverflow() 418 } 419 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) 425 } 426 } 427 428 func TestZeroTimerResetPanics(t *testing.T) { 429 defer checkZeroPanicString(t) 430 var tr Timer 431 tr.Reset(1) 432 } 433 434 func TestZeroTimerStopPanics(t *testing.T) { 435 defer checkZeroPanicString(t) 436 var tr Timer 437 tr.Stop() 438 }