| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a | 5 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a |
| 6 // heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to | 6 // heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to |
| 7 // increase tolerance and reduce observed flakiness (though doing so reduces the | 7 // increase tolerance and reduce observed flakiness (though doing so reduces the |
| 8 // meaningfulness of the test). | 8 // meaningfulness of the test). |
| 9 | 9 |
| 10 #include "mojo/edk/system/wait_set_dispatcher.h" | 10 #include "mojo/edk/system/wait_set_dispatcher.h" |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 // The inputs should be untouched. | 302 // The inputs should be untouched. |
| 303 EXPECT_EQ(1u, num_results); | 303 EXPECT_EQ(1u, num_results); |
| 304 EXPECT_EQ(456u, results[0].cookie); | 304 EXPECT_EQ(456u, results[0].cookie); |
| 305 EXPECT_EQ(789u, max_results); | 305 EXPECT_EQ(789u, max_results); |
| 306 } | 306 } |
| 307 | 307 |
| 308 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | 308 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); |
| 309 EXPECT_EQ(MOJO_RESULT_OK, d_member->Close()); | 309 EXPECT_EQ(MOJO_RESULT_OK, d_member->Close()); |
| 310 } | 310 } |
| 311 | 311 |
| 312 TEST(WaitSetDispatcherTest, BasicThreaded) { | 312 TEST(WaitSetDispatcherTest, BasicThreaded1) { |
| 313 static constexpr auto kNone = MOJO_HANDLE_SIGNAL_NONE; | 313 static constexpr auto kNone = MOJO_HANDLE_SIGNAL_NONE; |
| 314 static constexpr auto kR = MOJO_HANDLE_SIGNAL_READABLE; | 314 static constexpr auto kR = MOJO_HANDLE_SIGNAL_READABLE; |
| 315 static constexpr auto kW = MOJO_HANDLE_SIGNAL_WRITABLE; | 315 static constexpr auto kW = MOJO_HANDLE_SIGNAL_WRITABLE; |
| 316 | 316 |
| 317 const auto epsilon = test::EpsilonTimeout(); | 317 const auto epsilon = test::EpsilonTimeout(); |
| 318 | 318 |
| 319 auto d = WaitSetDispatcher::Create(WaitSetDispatcher::kDefaultCreateOptions); | 319 auto d = WaitSetDispatcher::Create(WaitSetDispatcher::kDefaultCreateOptions); |
| 320 | 320 |
| 321 // These will be members of our wait set. | 321 // These will be members of our wait set. |
| 322 auto d_member0 = MakeRefCounted<test::MockSimpleDispatcher>(kNone, kR | kW); | 322 auto d_member0 = MakeRefCounted<test::MockSimpleDispatcher>(kNone, kR | kW); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 MOJO_RESULT_CANCELLED, | 444 MOJO_RESULT_CANCELLED, |
| 445 MojoHandleSignalsState())); | 445 MojoHandleSignalsState())); |
| 446 | 446 |
| 447 t.join(); | 447 t.join(); |
| 448 } | 448 } |
| 449 | 449 |
| 450 EXPECT_EQ(MOJO_RESULT_OK, d_member1->Close()); | 450 EXPECT_EQ(MOJO_RESULT_OK, d_member1->Close()); |
| 451 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | 451 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); |
| 452 } | 452 } |
| 453 | 453 |
| 454 // TODO(vtl): Test adding/removing on another thread. | 454 TEST(WaitSetDispatcherTest, BasicThreaded2) { |
| 455 static constexpr auto kNone = MOJO_HANDLE_SIGNAL_NONE; |
| 456 static constexpr auto kR = MOJO_HANDLE_SIGNAL_READABLE; |
| 457 static constexpr auto kW = MOJO_HANDLE_SIGNAL_WRITABLE; |
| 458 |
| 459 const auto epsilon = test::EpsilonTimeout(); |
| 460 |
| 461 Stopwatch stopwatch; |
| 462 |
| 463 auto d = WaitSetDispatcher::Create(WaitSetDispatcher::kDefaultCreateOptions); |
| 464 auto d_member = MakeRefCounted<test::MockSimpleDispatcher>(kNone, kR | kW); |
| 465 |
| 466 static constexpr uint64_t kCookie0 = 123u; |
| 467 static constexpr auto kSignals0 = kR; |
| 468 static constexpr uint64_t kCookie1 = 456u; |
| 469 static constexpr auto kSignals1 = kW; |
| 470 static constexpr uint64_t kCookie2 = 789u; |
| 471 static constexpr auto kSignals2 = kR | kW; |
| 472 |
| 473 // We'll wait on the main thread, and do stuff on another thread. |
| 474 |
| 475 { |
| 476 // Add |kCookie0|. |
| 477 std::thread t0([epsilon, d, d_member]() { |
| 478 // Sleep to try to ensure that waiting has started. |
| 479 ThreadSleep(epsilon); |
| 480 EXPECT_EQ(MOJO_RESULT_OK, |
| 481 d->WaitSetAdd(NullUserPointer(), d_member.Clone(), kSignals0, |
| 482 kCookie0)); |
| 483 }); |
| 484 // Trigger |kCookie0| after |2 * epsilon| on another thread. |
| 485 stopwatch.Start(); |
| 486 std::thread t1([epsilon, d_member]() { |
| 487 ThreadSleep(2 * epsilon); |
| 488 d_member->SetSatisfiedSignals(kR); |
| 489 }); |
| 490 |
| 491 uint32_t num_results = 10u; |
| 492 MojoWaitSetResult results[10] = {}; |
| 493 uint32_t max_results = static_cast<uint32_t>(-1); |
| 494 EXPECT_EQ(MOJO_RESULT_OK, |
| 495 d->WaitSetWait(3 * epsilon, MakeUserPointer(&num_results), |
| 496 MakeUserPointer(results), |
| 497 MakeUserPointer(&max_results))); |
| 498 MojoDeadline elapsed = stopwatch.Elapsed(); |
| 499 EXPECT_GT(elapsed, epsilon); |
| 500 EXPECT_LT(elapsed, 3 * epsilon); |
| 501 EXPECT_EQ(1u, num_results); |
| 502 EXPECT_EQ(1u, max_results); |
| 503 EXPECT_TRUE(CheckHasResult(num_results, results, kCookie0, kSignals0, |
| 504 MOJO_RESULT_OK, |
| 505 d_member->GetHandleSignalsState())); |
| 506 |
| 507 t1.join(); |
| 508 t0.join(); |
| 509 } |
| 510 |
| 511 // Untrigger |kCookie0|. |
| 512 d_member->SetSatisfiedSignals(kNone); |
| 513 |
| 514 { |
| 515 // Remove |kCookie0|. |
| 516 std::thread t0([epsilon, d]() { |
| 517 // Sleep to try to ensure that waiting has started. |
| 518 ThreadSleep(epsilon); |
| 519 EXPECT_EQ(MOJO_RESULT_OK, d->WaitSetRemove(kCookie0)); |
| 520 }); |
| 521 // Add |kCookie1|. |
| 522 std::thread t1([epsilon, d, d_member]() { |
| 523 // Sleep to try to ensure that waiting has started. |
| 524 ThreadSleep(epsilon); |
| 525 EXPECT_EQ(MOJO_RESULT_OK, |
| 526 d->WaitSetAdd(NullUserPointer(), d_member.Clone(), kSignals1, |
| 527 kCookie1)); |
| 528 }); |
| 529 // Add |kCookie2|. |
| 530 std::thread t2([epsilon, d, d_member]() { |
| 531 // Sleep to try to ensure that waiting has started. |
| 532 ThreadSleep(epsilon); |
| 533 EXPECT_EQ(MOJO_RESULT_OK, |
| 534 d->WaitSetAdd(NullUserPointer(), d_member.Clone(), kSignals2, |
| 535 kCookie2)); |
| 536 }); |
| 537 // Trigger |kCookie1| and |kCookie2| after |2 * epsilon| on another thread. |
| 538 stopwatch.Start(); |
| 539 std::thread t3([epsilon, d_member]() { |
| 540 ThreadSleep(2 * epsilon); |
| 541 d_member->SetSatisfiedSignals(kW); |
| 542 }); |
| 543 |
| 544 uint32_t num_results = 10u; |
| 545 MojoWaitSetResult results[10] = {}; |
| 546 EXPECT_EQ(MOJO_RESULT_OK, |
| 547 d->WaitSetWait(3 * epsilon, MakeUserPointer(&num_results), |
| 548 MakeUserPointer(results), NullUserPointer())); |
| 549 MojoDeadline elapsed = stopwatch.Elapsed(); |
| 550 EXPECT_GT(elapsed, epsilon); |
| 551 EXPECT_LT(elapsed, 3 * epsilon); |
| 552 EXPECT_EQ(2u, num_results); |
| 553 EXPECT_TRUE(CheckHasResult(num_results, results, kCookie1, kSignals1, |
| 554 MOJO_RESULT_OK, |
| 555 d_member->GetHandleSignalsState())); |
| 556 EXPECT_TRUE(CheckHasResult(num_results, results, kCookie2, kSignals2, |
| 557 MOJO_RESULT_OK, |
| 558 d_member->GetHandleSignalsState())); |
| 559 |
| 560 t3.join(); |
| 561 t2.join(); |
| 562 t1.join(); |
| 563 t0.join(); |
| 564 } |
| 565 |
| 566 // Untrigger |kCookie1| and |kCookie2|. |
| 567 d_member->SetSatisfiedSignals(kNone); |
| 568 |
| 569 { |
| 570 // Make |kCookie1| unsatisfiable (|kCookie2| remains satisfiable but not |
| 571 // satisfied). |
| 572 std::thread t([epsilon, d_member]() { |
| 573 // Sleep to try to ensure that waiting has started. |
| 574 ThreadSleep(epsilon); |
| 575 d_member->SetSatisfiableSignals(kR); |
| 576 }); |
| 577 |
| 578 uint32_t num_results = 10u; |
| 579 MojoWaitSetResult results[10] = {}; |
| 580 EXPECT_EQ(MOJO_RESULT_OK, |
| 581 d->WaitSetWait(3 * epsilon, MakeUserPointer(&num_results), |
| 582 MakeUserPointer(results), NullUserPointer())); |
| 583 EXPECT_EQ(1u, num_results); |
| 584 EXPECT_TRUE(CheckHasResult(num_results, results, kCookie1, kSignals1, |
| 585 MOJO_RESULT_FAILED_PRECONDITION, |
| 586 d_member->GetHandleSignalsState())); |
| 587 |
| 588 t.join(); |
| 589 } |
| 590 |
| 591 EXPECT_EQ(MOJO_RESULT_OK, d_member->Close()); |
| 592 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); |
| 593 } |
| 594 |
| 455 // TODO(vtl): Test waiting on multiple threads. | 595 // TODO(vtl): Test waiting on multiple threads. |
| 456 // TODO(vtl): Stress tests. | 596 // TODO(vtl): Stress tests. |
| 457 | 597 |
| 458 // TODO(vtl): Test options validation for "create" and "add" (not that there's | 598 // TODO(vtl): Test options validation for "create" and "add" (not that there's |
| 459 // much to test). | 599 // much to test). |
| 460 | 600 |
| 461 } // namespace | 601 } // namespace |
| 462 } // namespace system | 602 } // namespace system |
| 463 } // namespace mojo | 603 } // namespace mojo |
| OLD | NEW |