github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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/atomic" 13 "testing" 14 . "time" 15 ) 16 17 func TestSleep(t *testing.T) { 18 const delay = 100 * Millisecond 19 go func() { 20 Sleep(delay / 2) 21 Interrupt() 22 }() 23 start := Now() 24 Sleep(delay) 25 duration := Now().Sub(start) 26 if duration < delay { 27 t.Fatalf("Sleep(%s) slept for only %s", delay, duration) 28 } 29 } 30 31 // Test the basic function calling behavior. Correct queueing 32 // behavior is tested elsewhere, since After and AfterFunc share 33 // the same code. 34 func TestAfterFunc(t *testing.T) { 35 i := 10 36 c := make(chan bool) 37 var f func() 38 f = func() { 39 i-- 40 if i >= 0 { 41 AfterFunc(0, f) 42 Sleep(1 * Second) 43 } else { 44 c <- true 45 } 46 } 47 48 AfterFunc(0, f) 49 <-c 50 } 51 52 func TestAfterStress(t *testing.T) { 53 stop := uint32(0) 54 go func() { 55 for atomic.LoadUint32(&stop) == 0 { 56 runtime.GC() 57 // Yield so that the OS can wake up the timer thread, 58 // so that it can generate channel sends for the main goroutine, 59 // which will eventually set stop = 1 for us. 60 Sleep(Nanosecond) 61 } 62 }() 63 ticker := NewTicker(1) 64 for i := 0; i < 100; i++ { 65 <-ticker.C 66 } 67 ticker.Stop() 68 atomic.StoreUint32(&stop, 1) 69 } 70 71 func BenchmarkAfterFunc(b *testing.B) { 72 i := b.N 73 c := make(chan bool) 74 var f func() 75 f = func() { 76 i-- 77 if i >= 0 { 78 AfterFunc(0, f) 79 } else { 80 c <- true 81 } 82 } 83 84 AfterFunc(0, f) 85 <-c 86 } 87 88 func BenchmarkAfter(b *testing.B) { 89 for i := 0; i < b.N; i++ { 90 <-After(1) 91 } 92 } 93 94 func BenchmarkStop(b *testing.B) { 95 for i := 0; i < b.N; i++ { 96 NewTimer(1 * Second).Stop() 97 } 98 } 99 100 func TestAfter(t *testing.T) { 101 const delay = 100 * Millisecond 102 start := Now() 103 end := <-After(delay) 104 if duration := Now().Sub(start); duration < delay { 105 t.Fatalf("After(%s) slept for only %d ns", delay, duration) 106 } 107 if min := start.Add(delay); end.Before(min) { 108 t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end) 109 } 110 } 111 112 func TestAfterTick(t *testing.T) { 113 const Count = 10 114 Delta := 100 * Millisecond 115 if testing.Short() { 116 Delta = 10 * Millisecond 117 } 118 t0 := Now() 119 for i := 0; i < Count; i++ { 120 <-After(Delta) 121 } 122 t1 := Now() 123 d := t1.Sub(t0) 124 target := Delta * Count 125 if d < target*9/10 { 126 t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target) 127 } 128 if !testing.Short() && d > target*30/10 { 129 t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target) 130 } 131 } 132 133 func TestAfterStop(t *testing.T) { 134 AfterFunc(100*Millisecond, func() {}) 135 t0 := NewTimer(50 * Millisecond) 136 c1 := make(chan bool, 1) 137 t1 := AfterFunc(150*Millisecond, func() { c1 <- true }) 138 c2 := After(200 * Millisecond) 139 if !t0.Stop() { 140 t.Fatalf("failed to stop event 0") 141 } 142 if !t1.Stop() { 143 t.Fatalf("failed to stop event 1") 144 } 145 <-c2 146 select { 147 case <-t0.C: 148 t.Fatalf("event 0 was not stopped") 149 case <-c1: 150 t.Fatalf("event 1 was not stopped") 151 default: 152 } 153 if t1.Stop() { 154 t.Fatalf("Stop returned true twice") 155 } 156 } 157 158 func TestAfterQueuing(t *testing.T) { 159 // This test flakes out on some systems, 160 // so we'll try it a few times before declaring it a failure. 161 const attempts = 3 162 err := errors.New("!=nil") 163 for i := 0; i < attempts && err != nil; i++ { 164 if err = testAfterQueuing(t); err != nil { 165 t.Logf("attempt %v failed: %v", i, err) 166 } 167 } 168 if err != nil { 169 t.Fatal(err) 170 } 171 } 172 173 var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0} 174 175 type afterResult struct { 176 slot int 177 t Time 178 } 179 180 func await(slot int, result chan<- afterResult, ac <-chan Time) { 181 result <- afterResult{slot, <-ac} 182 } 183 184 func testAfterQueuing(t *testing.T) error { 185 Delta := 100 * Millisecond 186 if testing.Short() { 187 Delta = 20 * Millisecond 188 } 189 // make the result channel buffered because we don't want 190 // to depend on channel queueing semantics that might 191 // possibly change in the future. 192 result := make(chan afterResult, len(slots)) 193 194 t0 := Now() 195 for _, slot := range slots { 196 go await(slot, result, After(Duration(slot)*Delta)) 197 } 198 sort.Ints(slots) 199 for _, slot := range slots { 200 r := <-result 201 if r.slot != slot { 202 return fmt.Errorf("after slot %d, expected %d", r.slot, slot) 203 } 204 dt := r.t.Sub(t0) 205 target := Duration(slot) * Delta 206 if dt < target-Delta/2 || dt > target+Delta*10 { 207 return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10) 208 } 209 } 210 return nil 211 } 212 213 func TestTimerStopStress(t *testing.T) { 214 if testing.Short() { 215 return 216 } 217 for i := 0; i < 100; i++ { 218 go func(i int) { 219 timer := AfterFunc(2*Second, func() { 220 t.Fatalf("timer %d was not stopped", i) 221 }) 222 Sleep(1 * Second) 223 timer.Stop() 224 }(i) 225 } 226 Sleep(3 * Second) 227 } 228 229 func TestSleepZeroDeadlock(t *testing.T) { 230 // Sleep(0) used to hang, the sequence of events was as follows. 231 // Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status. 232 // Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC. 233 // After the GC nobody wakes up the goroutine from Gwaiting status. 234 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) 235 c := make(chan bool) 236 go func() { 237 for i := 0; i < 100; i++ { 238 runtime.GC() 239 } 240 c <- true 241 }() 242 for i := 0; i < 100; i++ { 243 Sleep(0) 244 tmp := make(chan bool, 1) 245 tmp <- true 246 <-tmp 247 } 248 <-c 249 } 250 251 func testReset(d Duration) error { 252 t0 := NewTimer(2 * d) 253 Sleep(d) 254 if t0.Reset(3*d) != true { 255 return errors.New("resetting unfired timer returned false") 256 } 257 Sleep(2 * d) 258 select { 259 case <-t0.C: 260 return errors.New("timer fired early") 261 default: 262 } 263 Sleep(2 * d) 264 select { 265 case <-t0.C: 266 default: 267 return errors.New("reset timer did not fire") 268 } 269 270 if t0.Reset(50*Millisecond) != false { 271 return errors.New("resetting expired timer returned true") 272 } 273 return nil 274 } 275 276 func TestReset(t *testing.T) { 277 // We try to run this test with increasingly larger multiples 278 // until one works so slow, loaded hardware isn't as flaky, 279 // but without slowing down fast machines unnecessarily. 280 const unit = 25 * Millisecond 281 tries := []Duration{ 282 1 * unit, 283 3 * unit, 284 7 * unit, 285 15 * unit, 286 } 287 var err error 288 for _, d := range tries { 289 err = testReset(d) 290 if err == nil { 291 t.Logf("passed using duration %v", d) 292 return 293 } 294 } 295 t.Error(err) 296 } 297 298 // Test that sleeping for an interval so large it overflows does not 299 // result in a short sleep duration. 300 func TestOverflowSleep(t *testing.T) { 301 const timeout = 25 * Millisecond 302 const big = Duration(int64(1<<63 - 1)) 303 select { 304 case <-After(big): 305 t.Fatalf("big timeout fired") 306 case <-After(timeout): 307 // OK 308 } 309 const neg = Duration(-1 << 63) 310 select { 311 case <-After(neg): 312 // OK 313 case <-After(timeout): 314 t.Fatalf("negative timeout didn't fire") 315 } 316 }