github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/sleep/sleep_test.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package sleep 16 17 import ( 18 "math/rand" 19 "runtime" 20 "testing" 21 "time" 22 ) 23 24 // ZeroWakerNotAsserted tests that a zero-value waker is in non-asserted state. 25 func ZeroWakerNotAsserted(t *testing.T) { 26 var w Waker 27 if w.IsAsserted() { 28 t.Fatalf("Zero waker is asserted") 29 } 30 31 if w.Clear() { 32 t.Fatalf("Zero waker is asserted") 33 } 34 } 35 36 // AssertedWakerAfterAssert tests that a waker properly reports its state as 37 // asserted once its Assert() method is called. 38 func AssertedWakerAfterAssert(t *testing.T) { 39 var w Waker 40 w.Assert() 41 if !w.IsAsserted() { 42 t.Fatalf("Asserted waker is not reported as such") 43 } 44 45 if !w.Clear() { 46 t.Fatalf("Asserted waker is not reported as such") 47 } 48 } 49 50 // AssertedWakerAfterTwoAsserts tests that a waker properly reports its state as 51 // asserted once its Assert() method is called twice. 52 func AssertedWakerAfterTwoAsserts(t *testing.T) { 53 var w Waker 54 w.Assert() 55 w.Assert() 56 if !w.IsAsserted() { 57 t.Fatalf("Asserted waker is not reported as such") 58 } 59 60 if !w.Clear() { 61 t.Fatalf("Asserted waker is not reported as such") 62 } 63 } 64 65 // NotAssertedWakerWithSleeper tests that a waker properly reports its state as 66 // not asserted after a sleeper is associated with it. 67 func NotAssertedWakerWithSleeper(t *testing.T) { 68 var w Waker 69 var s Sleeper 70 s.AddWaker(&w, 0) 71 if w.IsAsserted() { 72 t.Fatalf("Non-asserted waker is reported as asserted") 73 } 74 75 if w.Clear() { 76 t.Fatalf("Non-asserted waker is reported as asserted") 77 } 78 } 79 80 // NotAssertedWakerAfterWake tests that a waker properly reports its state as 81 // not asserted after a previous assert is consumed by a sleeper. That is, tests 82 // the "edge-triggered" behavior. 83 func NotAssertedWakerAfterWake(t *testing.T) { 84 var w Waker 85 var s Sleeper 86 s.AddWaker(&w, 0) 87 w.Assert() 88 s.Fetch(true) 89 if w.IsAsserted() { 90 t.Fatalf("Consumed waker is reported as asserted") 91 } 92 93 if w.Clear() { 94 t.Fatalf("Consumed waker is reported as asserted") 95 } 96 } 97 98 // AssertedWakerBeforeAdd tests that a waker causes a sleeper to not sleep if 99 // it's already asserted before being added. 100 func AssertedWakerBeforeAdd(t *testing.T) { 101 var w Waker 102 var s Sleeper 103 w.Assert() 104 s.AddWaker(&w, 0) 105 106 if _, ok := s.Fetch(false); !ok { 107 t.Fatalf("Fetch failed even though asserted waker was added") 108 } 109 } 110 111 // ClearedWaker tests that a waker properly reports its state as not asserted 112 // after it is cleared. 113 func ClearedWaker(t *testing.T) { 114 var w Waker 115 w.Assert() 116 w.Clear() 117 if w.IsAsserted() { 118 t.Fatalf("Cleared waker is reported as asserted") 119 } 120 121 if w.Clear() { 122 t.Fatalf("Cleared waker is reported as asserted") 123 } 124 } 125 126 // ClearedWakerWithSleeper tests that a waker properly reports its state as 127 // not asserted when it is cleared while it has a sleeper associated with it. 128 func ClearedWakerWithSleeper(t *testing.T) { 129 var w Waker 130 var s Sleeper 131 s.AddWaker(&w, 0) 132 w.Clear() 133 if w.IsAsserted() { 134 t.Fatalf("Cleared waker is reported as asserted") 135 } 136 137 if w.Clear() { 138 t.Fatalf("Cleared waker is reported as asserted") 139 } 140 } 141 142 // ClearedWakerAssertedWithSleeper tests that a waker properly reports its state 143 // as not asserted when it is cleared while it has a sleeper associated with it 144 // and has been asserted. 145 func ClearedWakerAssertedWithSleeper(t *testing.T) { 146 var w Waker 147 var s Sleeper 148 s.AddWaker(&w, 0) 149 w.Assert() 150 w.Clear() 151 if w.IsAsserted() { 152 t.Fatalf("Cleared waker is reported as asserted") 153 } 154 155 if w.Clear() { 156 t.Fatalf("Cleared waker is reported as asserted") 157 } 158 } 159 160 // TestBlock tests that a sleeper actually blocks waiting for the waker to 161 // assert its state. 162 func TestBlock(t *testing.T) { 163 var w Waker 164 var s Sleeper 165 166 s.AddWaker(&w, 0) 167 168 // Assert waker after one second. 169 before := time.Now() 170 go func() { 171 time.Sleep(1 * time.Second) 172 w.Assert() 173 }() 174 175 // Fetch the result and make sure it took at least 500ms. 176 if _, ok := s.Fetch(true); !ok { 177 t.Fatalf("Fetch failed unexpectedly") 178 } 179 if d := time.Now().Sub(before); d < 500*time.Millisecond { 180 t.Fatalf("Duration was too short: %v", d) 181 } 182 183 // Check that already-asserted waker completes inline. 184 w.Assert() 185 if _, ok := s.Fetch(true); !ok { 186 t.Fatalf("Fetch failed unexpectedly") 187 } 188 189 // Check that fetch sleeps if waker had been asserted but was reset 190 // before Fetch is called. 191 w.Assert() 192 w.Clear() 193 before = time.Now() 194 go func() { 195 time.Sleep(1 * time.Second) 196 w.Assert() 197 }() 198 if _, ok := s.Fetch(true); !ok { 199 t.Fatalf("Fetch failed unexpectedly") 200 } 201 if d := time.Now().Sub(before); d < 500*time.Millisecond { 202 t.Fatalf("Duration was too short: %v", d) 203 } 204 } 205 206 // TestNonBlock checks that a sleeper won't block if waker isn't asserted. 207 func TestNonBlock(t *testing.T) { 208 var w Waker 209 var s Sleeper 210 211 // Don't block when there's no waker. 212 if _, ok := s.Fetch(false); ok { 213 t.Fatalf("Fetch succeeded when there is no waker") 214 } 215 216 // Don't block when waker isn't asserted. 217 s.AddWaker(&w, 0) 218 if _, ok := s.Fetch(false); ok { 219 t.Fatalf("Fetch succeeded when waker was not asserted") 220 } 221 222 // Don't block when waker was asserted, but isn't anymore. 223 w.Assert() 224 w.Clear() 225 if _, ok := s.Fetch(false); ok { 226 t.Fatalf("Fetch succeeded when waker was not asserted anymore") 227 } 228 229 // Don't block when waker was consumed by previous Fetch(). 230 w.Assert() 231 if _, ok := s.Fetch(false); !ok { 232 t.Fatalf("Fetch failed even though waker was asserted") 233 } 234 235 if _, ok := s.Fetch(false); ok { 236 t.Fatalf("Fetch succeeded when waker had been consumed") 237 } 238 } 239 240 // TestMultiple checks that a sleeper can wait for and receives notifications 241 // from multiple wakers. 242 func TestMultiple(t *testing.T) { 243 s := Sleeper{} 244 w1 := Waker{} 245 w2 := Waker{} 246 247 s.AddWaker(&w1, 0) 248 s.AddWaker(&w2, 1) 249 250 w1.Assert() 251 w2.Assert() 252 253 v, ok := s.Fetch(false) 254 if !ok { 255 t.Fatalf("Fetch failed when there are asserted wakers") 256 } 257 258 if v != 0 && v != 1 { 259 t.Fatalf("Unexpected waker id: %v", v) 260 } 261 262 want := 1 - v 263 v, ok = s.Fetch(false) 264 if !ok { 265 t.Fatalf("Fetch failed when there is an asserted waker") 266 } 267 268 if v != want { 269 t.Fatalf("Unexpected waker id, got %v, want %v", v, want) 270 } 271 } 272 273 // TestDoneFunction tests if calling Done() on a sleeper works properly. 274 func TestDoneFunction(t *testing.T) { 275 // Trivial case of no waker. 276 s := Sleeper{} 277 s.Done() 278 279 // Cases when the sleeper has n wakers, but none are asserted. 280 for n := 1; n < 20; n++ { 281 s := Sleeper{} 282 w := make([]Waker, n) 283 for j := 0; j < n; j++ { 284 s.AddWaker(&w[j], j) 285 } 286 s.Done() 287 } 288 289 // Cases when the sleeper has n wakers, and only the i-th one is 290 // asserted. 291 for n := 1; n < 20; n++ { 292 for i := 0; i < n; i++ { 293 s := Sleeper{} 294 w := make([]Waker, n) 295 for j := 0; j < n; j++ { 296 s.AddWaker(&w[j], j) 297 } 298 w[i].Assert() 299 s.Done() 300 } 301 } 302 303 // Cases when the sleeper has n wakers, and the i-th one is asserted 304 // and cleared. 305 for n := 1; n < 20; n++ { 306 for i := 0; i < n; i++ { 307 s := Sleeper{} 308 w := make([]Waker, n) 309 for j := 0; j < n; j++ { 310 s.AddWaker(&w[j], j) 311 } 312 w[i].Assert() 313 w[i].Clear() 314 s.Done() 315 } 316 } 317 318 // Cases when the sleeper has n wakers, with a random number of them 319 // asserted. 320 for n := 1; n < 20; n++ { 321 for iters := 0; iters < 1000; iters++ { 322 s := Sleeper{} 323 w := make([]Waker, n) 324 for j := 0; j < n; j++ { 325 s.AddWaker(&w[j], j) 326 } 327 328 // Pick the number of asserted elements, then assert 329 // random wakers. 330 asserted := rand.Int() % (n + 1) 331 for j := 0; j < asserted; j++ { 332 w[rand.Int()%n].Assert() 333 } 334 s.Done() 335 } 336 } 337 } 338 339 // TestRace tests that multiple wakers can continuously send wake requests to 340 // the sleeper. 341 func TestRace(t *testing.T) { 342 const wakers = 100 343 const wakeRequests = 10000 344 345 counts := make([]int, wakers) 346 w := make([]Waker, wakers) 347 s := Sleeper{} 348 349 // Associate each waker and start goroutines that will assert them. 350 for i := range w { 351 s.AddWaker(&w[i], i) 352 go func(w *Waker) { 353 n := 0 354 for n < wakeRequests { 355 if !w.IsAsserted() { 356 w.Assert() 357 n++ 358 } else { 359 runtime.Gosched() 360 } 361 } 362 }(&w[i]) 363 } 364 365 // Wait for all wake up notifications from all wakers. 366 for i := 0; i < wakers*wakeRequests; i++ { 367 v, _ := s.Fetch(true) 368 counts[v]++ 369 } 370 371 // Check that we got the right number for each. 372 for i, v := range counts { 373 if v != wakeRequests { 374 t.Errorf("Waker %v only got %v wakes", i, v) 375 } 376 } 377 } 378 379 // BenchmarkSleeperMultiSelect measures how long it takes to fetch a wake up 380 // from 4 wakers when at least one is already asserted. 381 func BenchmarkSleeperMultiSelect(b *testing.B) { 382 const count = 4 383 s := Sleeper{} 384 w := make([]Waker, count) 385 for i := range w { 386 s.AddWaker(&w[i], i) 387 } 388 389 b.ResetTimer() 390 for i := 0; i < b.N; i++ { 391 w[count-1].Assert() 392 s.Fetch(true) 393 } 394 } 395 396 // BenchmarkGoMultiSelect measures how long it takes to fetch a zero-length 397 // struct from one of 4 channels when at least one is ready. 398 func BenchmarkGoMultiSelect(b *testing.B) { 399 const count = 4 400 ch := make([]chan struct{}, count) 401 for i := range ch { 402 ch[i] = make(chan struct{}, 1) 403 } 404 405 b.ResetTimer() 406 for i := 0; i < b.N; i++ { 407 ch[count-1] <- struct{}{} 408 select { 409 case <-ch[0]: 410 case <-ch[1]: 411 case <-ch[2]: 412 case <-ch[3]: 413 } 414 } 415 } 416 417 // BenchmarkSleeperSingleSelect measures how long it takes to fetch a wake up 418 // from one waker that is already asserted. 419 func BenchmarkSleeperSingleSelect(b *testing.B) { 420 s := Sleeper{} 421 w := Waker{} 422 s.AddWaker(&w, 0) 423 424 b.ResetTimer() 425 for i := 0; i < b.N; i++ { 426 w.Assert() 427 s.Fetch(true) 428 } 429 } 430 431 // BenchmarkGoSingleSelect measures how long it takes to fetch a zero-length 432 // struct from a channel that already has it buffered. 433 func BenchmarkGoSingleSelect(b *testing.B) { 434 ch := make(chan struct{}, 1) 435 436 b.ResetTimer() 437 for i := 0; i < b.N; i++ { 438 ch <- struct{}{} 439 <-ch 440 } 441 } 442 443 // BenchmarkSleeperAssertNonWaiting measures how long it takes to assert a 444 // channel that is already asserted. 445 func BenchmarkSleeperAssertNonWaiting(b *testing.B) { 446 w := Waker{} 447 w.Assert() 448 for i := 0; i < b.N; i++ { 449 w.Assert() 450 } 451 452 } 453 454 // BenchmarkGoAssertNonWaiting measures how long it takes to write to a channel 455 // that has already something written to it. 456 func BenchmarkGoAssertNonWaiting(b *testing.B) { 457 ch := make(chan struct{}, 1) 458 ch <- struct{}{} 459 for i := 0; i < b.N; i++ { 460 select { 461 case ch <- struct{}{}: 462 default: 463 } 464 } 465 } 466 467 // BenchmarkSleeperWaitOnSingleSelect measures how long it takes to wait on one 468 // waker channel while another goroutine wakes up the sleeper. This assumes that 469 // a new goroutine doesn't run immediately (i.e., the creator of a new goroutine 470 // is allowed to go to sleep before the new goroutine has a chance to run). 471 func BenchmarkSleeperWaitOnSingleSelect(b *testing.B) { 472 s := Sleeper{} 473 w := Waker{} 474 s.AddWaker(&w, 0) 475 for i := 0; i < b.N; i++ { 476 go func() { 477 w.Assert() 478 }() 479 s.Fetch(true) 480 } 481 482 } 483 484 // BenchmarkGoWaitOnSingleSelect measures how long it takes to wait on one 485 // channel while another goroutine wakes up the sleeper. This assumes that a new 486 // goroutine doesn't run immediately (i.e., the creator of a new goroutine is 487 // allowed to go to sleep before the new goroutine has a chance to run). 488 func BenchmarkGoWaitOnSingleSelect(b *testing.B) { 489 ch := make(chan struct{}, 1) 490 for i := 0; i < b.N; i++ { 491 go func() { 492 ch <- struct{}{} 493 }() 494 <-ch 495 } 496 } 497 498 // BenchmarkSleeperWaitOnMultiSelect measures how long it takes to wait on 4 499 // wakers while another goroutine wakes up the sleeper. This assumes that a new 500 // goroutine doesn't run immediately (i.e., the creator of a new goroutine is 501 // allowed to go to sleep before the new goroutine has a chance to run). 502 func BenchmarkSleeperWaitOnMultiSelect(b *testing.B) { 503 const count = 4 504 s := Sleeper{} 505 w := make([]Waker, count) 506 for i := range w { 507 s.AddWaker(&w[i], i) 508 } 509 510 b.ResetTimer() 511 for i := 0; i < b.N; i++ { 512 go func() { 513 w[count-1].Assert() 514 }() 515 s.Fetch(true) 516 } 517 } 518 519 // BenchmarkGoWaitOnMultiSelect measures how long it takes to wait on 4 channels 520 // while another goroutine wakes up the sleeper. This assumes that a new 521 // goroutine doesn't run immediately (i.e., the creator of a new goroutine is 522 // allowed to go to sleep before the new goroutine has a chance to run). 523 func BenchmarkGoWaitOnMultiSelect(b *testing.B) { 524 const count = 4 525 ch := make([]chan struct{}, count) 526 for i := range ch { 527 ch[i] = make(chan struct{}, 1) 528 } 529 530 b.ResetTimer() 531 for i := 0; i < b.N; i++ { 532 go func() { 533 ch[count-1] <- struct{}{} 534 }() 535 select { 536 case <-ch[0]: 537 case <-ch[1]: 538 case <-ch[2]: 539 case <-ch[3]: 540 } 541 } 542 }