| Index: mojo/public/cpp/system/tests/wait_set_unittest.cc
|
| diff --git a/mojo/public/cpp/system/tests/wait_set_unittest.cc b/mojo/public/cpp/system/tests/wait_set_unittest.cc
|
| index 2a6d9b88256b32e9857971e6d2037454d3c6077f..d60cb45924df33c88dff54a70bd8708e01024dbd 100644
|
| --- a/mojo/public/cpp/system/tests/wait_set_unittest.cc
|
| +++ b/mojo/public/cpp/system/tests/wait_set_unittest.cc
|
| @@ -4,11 +4,17 @@
|
|
|
| #include "mojo/public/cpp/system/wait_set.h"
|
|
|
| +#include <set>
|
| +#include <vector>
|
| +
|
| #include "base/bind.h"
|
| #include "base/callback.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| #include "base/threading/platform_thread.h"
|
| #include "base/threading/simple_thread.h"
|
| #include "mojo/public/cpp/system/message_pipe.h"
|
| +#include "mojo/public/cpp/system/wait.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| namespace mojo {
|
| @@ -68,7 +74,7 @@ TEST_F(WaitSetTest, Satisfied) {
|
| Handle ready_handles[2];
|
| MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
|
| HandleSignalsState hss[2];
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
|
|
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_EQ(p.handle1.get(), ready_handles[0]);
|
| @@ -85,7 +91,7 @@ TEST_F(WaitSetTest, Satisfied) {
|
| num_ready_handles = 2;
|
| ready_results[0] = MOJO_RESULT_UNKNOWN;
|
| ready_results[1] = MOJO_RESULT_UNKNOWN;
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
|
|
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_EQ(p.handle0.get(), ready_handles[0]);
|
| @@ -98,7 +104,7 @@ TEST_F(WaitSetTest, Satisfied) {
|
| num_ready_handles = 2;
|
| ready_results[0] = MOJO_RESULT_UNKNOWN;
|
| ready_results[1] = MOJO_RESULT_UNKNOWN;
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
|
| EXPECT_EQ(2u, num_ready_handles);
|
| EXPECT_TRUE((ready_handles[0] == p.handle0.get() &&
|
| ready_handles[1] == p.handle1.get()) ||
|
| @@ -112,7 +118,7 @@ TEST_F(WaitSetTest, Satisfied) {
|
| // Wait on both again, but with only enough output space for one result.
|
| num_ready_handles = 1;
|
| ready_results[0] = MOJO_RESULT_UNKNOWN;
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_TRUE(ready_handles[0] == p.handle0.get() ||
|
| ready_handles[0] == p.handle1.get());
|
| @@ -123,7 +129,7 @@ TEST_F(WaitSetTest, Satisfied) {
|
|
|
| num_ready_handles = 1;
|
| ready_results[0] = MOJO_RESULT_UNKNOWN;
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_TRUE(ready_handles[0] == p.handle0.get() ||
|
| ready_handles[0] == p.handle1.get());
|
| @@ -133,7 +139,7 @@ TEST_F(WaitSetTest, Satisfied) {
|
|
|
| // The wait set should be empty now. Nothing to wait on.
|
| num_ready_handles = 2;
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
|
| EXPECT_EQ(0u, num_ready_handles);
|
| }
|
|
|
| @@ -150,7 +156,7 @@ TEST_F(WaitSetTest, Unsatisfiable) {
|
| MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
|
|
|
| p.handle1.reset();
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_EQ(p.handle0.get(), ready_handles[0]);
|
| EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]);
|
| @@ -175,7 +181,7 @@ TEST_F(WaitSetTest, CloseWhileWaiting) {
|
| size_t num_ready_handles = 2;
|
| Handle ready_handles[2];
|
| MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_EQ(handle0_value, ready_handles[0]);
|
| EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_results[0]);
|
| @@ -203,20 +209,20 @@ TEST_F(WaitSetTest, CloseBeforeWaiting) {
|
| size_t num_ready_handles = 1;
|
| Handle ready_handle;
|
| MojoResult ready_result = MOJO_RESULT_UNKNOWN;
|
| - wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
|
| + wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result);
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value);
|
| EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result);
|
| EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value));
|
|
|
| - wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
|
| + wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result);
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value);
|
| EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result);
|
| EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value));
|
|
|
| // Nothing more to wait on.
|
| - wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
|
| + wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result);
|
| EXPECT_EQ(0u, num_ready_handles);
|
| }
|
|
|
| @@ -233,7 +239,7 @@ TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) {
|
| size_t num_ready_handles = 2;
|
| Handle ready_handles[2];
|
| MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_EQ(p.handle1.get(), ready_handles[0]);
|
| EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
|
| @@ -250,11 +256,121 @@ TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) {
|
| write_after_delay.Start();
|
|
|
| num_ready_handles = 2;
|
| - wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
|
| + wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
|
| EXPECT_EQ(1u, num_ready_handles);
|
| EXPECT_EQ(p.handle0.get(), ready_handles[0]);
|
| EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
|
| }
|
|
|
| +TEST_F(WaitSetTest, EventOnly) {
|
| + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
|
| + base::WaitableEvent::InitialState::SIGNALED);
|
| + WaitSet wait_set;
|
| + wait_set.AddEvent(&event);
|
| +
|
| + base::WaitableEvent* ready_event = nullptr;
|
| + size_t num_ready_handles = 1;
|
| + Handle ready_handle;
|
| + MojoResult ready_result = MOJO_RESULT_UNKNOWN;
|
| + wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result);
|
| + EXPECT_EQ(0u, num_ready_handles);
|
| + EXPECT_EQ(&event, ready_event);
|
| +}
|
| +
|
| +TEST_F(WaitSetTest, EventAndHandle) {
|
| + const char kTestMessage[] = "hello hello";
|
| +
|
| + MessagePipe p;
|
| + WriteMessage(p.handle0, kTestMessage);
|
| +
|
| + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| +
|
| + WaitSet wait_set;
|
| + wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
|
| + wait_set.AddEvent(&event);
|
| +
|
| + base::WaitableEvent* ready_event = nullptr;
|
| + size_t num_ready_handles = 1;
|
| + Handle ready_handle;
|
| + MojoResult ready_result = MOJO_RESULT_UNKNOWN;
|
| + wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result);
|
| + EXPECT_EQ(1u, num_ready_handles);
|
| + EXPECT_EQ(nullptr, ready_event);
|
| + EXPECT_EQ(p.handle1.get(), ready_handle);
|
| + EXPECT_EQ(MOJO_RESULT_OK, ready_result);
|
| +
|
| + EXPECT_EQ(kTestMessage, ReadMessage(p.handle1));
|
| +
|
| + ThreadedRunner signal_after_delay(base::Bind(
|
| + [](base::WaitableEvent* event) {
|
| + // Wait a little while, then close the handle.
|
| + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
|
| + event->Signal();
|
| + },
|
| + &event));
|
| + signal_after_delay.Start();
|
| +
|
| + wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result);
|
| + EXPECT_EQ(0u, num_ready_handles);
|
| + EXPECT_EQ(&event, ready_event);
|
| +}
|
| +
|
| +TEST_F(WaitSetTest, NoStarvation) {
|
| + const char kTestMessage[] = "wait for it";
|
| + const size_t kNumTestPipes = 50;
|
| + const size_t kNumTestEvents = 10;
|
| +
|
| + // Create a bunch of handles and events which are always ready and add them
|
| + // to a shared WaitSet.
|
| +
|
| + WaitSet wait_set;
|
| +
|
| + MessagePipe pipes[kNumTestPipes];
|
| + for (size_t i = 0; i < kNumTestPipes; ++i) {
|
| + WriteMessage(pipes[i].handle0, kTestMessage);
|
| + Wait(pipes[i].handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
|
| +
|
| + WriteMessage(pipes[i].handle1, kTestMessage);
|
| + Wait(pipes[i].handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
|
| +
|
| + wait_set.AddHandle(pipes[i].handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
|
| + wait_set.AddHandle(pipes[i].handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
|
| + }
|
| +
|
| + std::vector<std::unique_ptr<base::WaitableEvent>> events(kNumTestEvents);
|
| + for (auto& event_ptr : events) {
|
| + event_ptr = base::MakeUnique<base::WaitableEvent>(
|
| + base::WaitableEvent::ResetPolicy::MANUAL,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + event_ptr->Signal();
|
| + wait_set.AddEvent(event_ptr.get());
|
| + }
|
| +
|
| + // Now verify that all handle and event signals are deteceted within a finite
|
| + // number of consecutive Wait() calls. Do it a few times for good measure.
|
| + for (size_t i = 0; i < 3; ++i) {
|
| + std::set<base::WaitableEvent*> ready_events;
|
| + std::set<Handle> ready_handles;
|
| + while (ready_events.size() < kNumTestEvents ||
|
| + ready_handles.size() < kNumTestPipes * 2) {
|
| + base::WaitableEvent* ready_event = nullptr;
|
| + size_t num_ready_handles = 1;
|
| + Handle ready_handle;
|
| + MojoResult ready_result = MOJO_RESULT_UNKNOWN;
|
| + wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle,
|
| + &ready_result);
|
| + if (ready_event)
|
| + ready_events.insert(ready_event);
|
| +
|
| + if (num_ready_handles) {
|
| + EXPECT_EQ(1u, num_ready_handles);
|
| + EXPECT_EQ(MOJO_RESULT_OK, ready_result);
|
| + ready_handles.insert(ready_handle);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| } // namespace
|
| } // namespace mojo
|
|
|