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