github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/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 // TestRaceInOrder tests that multiple wakers can continuously send wake requests to 380 // the sleeper and that the wakers are retrieved in the order asserted. 381 func TestRaceInOrder(t *testing.T) { 382 w := make([]Waker, 10000) 383 s := Sleeper{} 384 385 // Associate each waker and start goroutines that will assert them. 386 for i := range w { 387 s.AddWaker(&w[i], i) 388 } 389 go func() { 390 for i := range w { 391 w[i].Assert() 392 } 393 }() 394 395 // Wait for all wake up notifications from all wakers. 396 for want := range w { 397 got, _ := s.Fetch(true) 398 if got != want { 399 t.Fatalf("got %d want %d", got, want) 400 } 401 } 402 } 403 404 // BenchmarkSleeperMultiSelect measures how long it takes to fetch a wake up 405 // from 4 wakers when at least one is already asserted. 406 func BenchmarkSleeperMultiSelect(b *testing.B) { 407 const count = 4 408 s := Sleeper{} 409 w := make([]Waker, count) 410 for i := range w { 411 s.AddWaker(&w[i], i) 412 } 413 414 b.ResetTimer() 415 for i := 0; i < b.N; i++ { 416 w[count-1].Assert() 417 s.Fetch(true) 418 } 419 } 420 421 // BenchmarkGoMultiSelect measures how long it takes to fetch a zero-length 422 // struct from one of 4 channels when at least one is ready. 423 func BenchmarkGoMultiSelect(b *testing.B) { 424 const count = 4 425 ch := make([]chan struct{}, count) 426 for i := range ch { 427 ch[i] = make(chan struct{}, 1) 428 } 429 430 b.ResetTimer() 431 for i := 0; i < b.N; i++ { 432 ch[count-1] <- struct{}{} 433 select { 434 case <-ch[0]: 435 case <-ch[1]: 436 case <-ch[2]: 437 case <-ch[3]: 438 } 439 } 440 } 441 442 // BenchmarkSleeperSingleSelect measures how long it takes to fetch a wake up 443 // from one waker that is already asserted. 444 func BenchmarkSleeperSingleSelect(b *testing.B) { 445 s := Sleeper{} 446 w := Waker{} 447 s.AddWaker(&w, 0) 448 449 b.ResetTimer() 450 for i := 0; i < b.N; i++ { 451 w.Assert() 452 s.Fetch(true) 453 } 454 } 455 456 // BenchmarkGoSingleSelect measures how long it takes to fetch a zero-length 457 // struct from a channel that already has it buffered. 458 func BenchmarkGoSingleSelect(b *testing.B) { 459 ch := make(chan struct{}, 1) 460 461 b.ResetTimer() 462 for i := 0; i < b.N; i++ { 463 ch <- struct{}{} 464 <-ch 465 } 466 } 467 468 // BenchmarkSleeperAssertNonWaiting measures how long it takes to assert a 469 // channel that is already asserted. 470 func BenchmarkSleeperAssertNonWaiting(b *testing.B) { 471 w := Waker{} 472 w.Assert() 473 for i := 0; i < b.N; i++ { 474 w.Assert() 475 } 476 477 } 478 479 // BenchmarkGoAssertNonWaiting measures how long it takes to write to a channel 480 // that has already something written to it. 481 func BenchmarkGoAssertNonWaiting(b *testing.B) { 482 ch := make(chan struct{}, 1) 483 ch <- struct{}{} 484 for i := 0; i < b.N; i++ { 485 select { 486 case ch <- struct{}{}: 487 default: 488 } 489 } 490 } 491 492 // BenchmarkSleeperWaitOnSingleSelect measures how long it takes to wait on one 493 // waker channel while another goroutine wakes up the sleeper. This assumes that 494 // a new goroutine doesn't run immediately (i.e., the creator of a new goroutine 495 // is allowed to go to sleep before the new goroutine has a chance to run). 496 func BenchmarkSleeperWaitOnSingleSelect(b *testing.B) { 497 s := Sleeper{} 498 w := Waker{} 499 s.AddWaker(&w, 0) 500 for i := 0; i < b.N; i++ { 501 go func() { 502 w.Assert() 503 }() 504 s.Fetch(true) 505 } 506 507 } 508 509 // BenchmarkGoWaitOnSingleSelect measures how long it takes to wait on one 510 // channel while another goroutine wakes up the sleeper. This assumes that a new 511 // goroutine doesn't run immediately (i.e., the creator of a new goroutine is 512 // allowed to go to sleep before the new goroutine has a chance to run). 513 func BenchmarkGoWaitOnSingleSelect(b *testing.B) { 514 ch := make(chan struct{}, 1) 515 for i := 0; i < b.N; i++ { 516 go func() { 517 ch <- struct{}{} 518 }() 519 <-ch 520 } 521 } 522 523 // BenchmarkSleeperWaitOnMultiSelect measures how long it takes to wait on 4 524 // wakers while another goroutine wakes up the sleeper. This assumes that a new 525 // goroutine doesn't run immediately (i.e., the creator of a new goroutine is 526 // allowed to go to sleep before the new goroutine has a chance to run). 527 func BenchmarkSleeperWaitOnMultiSelect(b *testing.B) { 528 const count = 4 529 s := Sleeper{} 530 w := make([]Waker, count) 531 for i := range w { 532 s.AddWaker(&w[i], i) 533 } 534 535 b.ResetTimer() 536 for i := 0; i < b.N; i++ { 537 go func() { 538 w[count-1].Assert() 539 }() 540 s.Fetch(true) 541 } 542 } 543 544 // BenchmarkGoWaitOnMultiSelect measures how long it takes to wait on 4 channels 545 // while another goroutine wakes up the sleeper. This assumes that a new 546 // goroutine doesn't run immediately (i.e., the creator of a new goroutine is 547 // allowed to go to sleep before the new goroutine has a chance to run). 548 func BenchmarkGoWaitOnMultiSelect(b *testing.B) { 549 const count = 4 550 ch := make([]chan struct{}, count) 551 for i := range ch { 552 ch[i] = make(chan struct{}, 1) 553 } 554 555 b.ResetTimer() 556 for i := 0; i < b.N; i++ { 557 go func() { 558 ch[count-1] <- struct{}{} 559 }() 560 select { 561 case <-ch[0]: 562 case <-ch[1]: 563 case <-ch[2]: 564 case <-ch[3]: 565 } 566 } 567 }