Chromium Code Reviews| Index: mojo/edk/test/mojo_test_base.cc |
| diff --git a/mojo/edk/test/mojo_test_base.cc b/mojo/edk/test/mojo_test_base.cc |
| index f1032d7e3f5fe0ef45957dba5c8949cd1cdf5602..5388ede8f245158afde15aa27dc4590e7b83e6b5 100644 |
| --- a/mojo/edk/test/mojo_test_base.cc |
| +++ b/mojo/edk/test/mojo_test_base.cc |
| @@ -5,13 +5,16 @@ |
| #include "mojo/edk/test/mojo_test_base.h" |
| #include "base/memory/ptr_util.h" |
| +#include "base/memory/ref_counted.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| +#include "base/synchronization/waitable_event.h" |
| #include "mojo/edk/embedder/embedder.h" |
| #include "mojo/edk/system/handle_signals_state.h" |
| #include "mojo/public/c/system/buffer.h" |
| #include "mojo/public/c/system/data_pipe.h" |
| #include "mojo/public/c/system/functions.h" |
| +#include "mojo/public/c/system/watcher.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #if defined(OS_MACOSX) && !defined(OS_IOS) |
| @@ -22,6 +25,101 @@ namespace mojo { |
| namespace edk { |
| namespace test { |
| +namespace { |
| + |
| +class Waiter { |
| + public: |
| + Waiter() {} |
| + ~Waiter() {} |
| + |
| + MojoResult Wait(MojoHandle handle, |
| + MojoHandleSignals signals, |
| + MojoHandleSignalsState* state) { |
| + MojoHandle watcher; |
| + MojoCreateWatcher(&Context::OnNotification, &watcher); |
| + |
| + context_ = new Context(); |
| + |
| + DCHECK_EQ(MOJO_RESULT_OK, |
| + MojoWatch(watcher, handle, signals, |
| + reinterpret_cast<uintptr_t>( |
| + new scoped_refptr<Context>(context_)))); |
|
yzshen1
2017/03/14 18:20:44
I feel that it is a little easier to read if we us
Ken Rockot(use gerrit already)
2017/03/14 19:16:18
Done
|
| + |
| + uint32_t num_ready_contexts = 1; |
| + uintptr_t ready_context; |
| + MojoResult ready_result; |
| + MojoHandleSignalsState ready_state; |
| + MojoResult rv = MojoArmWatcher(watcher, &num_ready_contexts, &ready_context, |
| + &ready_result, &ready_state); |
| + if (rv == MOJO_RESULT_FAILED_PRECONDITION) { |
| + MojoClose(watcher); |
| + DCHECK_EQ(1u, num_ready_contexts); |
| + if (state) |
| + *state = ready_state; |
| + return ready_result; |
| + } |
| + |
| + // Wait for the first notification. |
| + context_->event().Wait(); |
| + |
| + ready_result = context_->wait_result(); |
| + DCHECK_NE(MOJO_RESULT_UNKNOWN, ready_result); |
| + |
| + if (state) |
| + *state = context_->wait_state(); |
| + |
| + MojoClose(watcher); |
| + |
| + return ready_result; |
| + } |
| + |
| + private: |
| + class Context : public base::RefCountedThreadSafe<Context> { |
| + public: |
| + Context() |
| + : event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| + base::WaitableEvent::InitialState::NOT_SIGNALED) {} |
| + |
| + base::WaitableEvent& event() { return event_; } |
| + MojoResult wait_result() const { return wait_result_; } |
| + MojoHandleSignalsState wait_state() const { return wait_state_; } |
| + |
| + static void OnNotification(uintptr_t context, |
| + MojoResult result, |
| + MojoHandleSignalsState state, |
| + MojoWatcherNotificationFlags flags) { |
| + auto* context_ref = reinterpret_cast<scoped_refptr<Context>*>(context); |
| + (*context_ref)->Notify(result, state); |
| + if (result == MOJO_RESULT_CANCELLED) |
| + delete context_ref; |
| + } |
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<Context>; |
| + |
| + ~Context() {} |
| + |
| + void Notify(MojoResult result, MojoHandleSignalsState state) { |
| + if (wait_result_ == MOJO_RESULT_UNKNOWN) { |
| + wait_result_ = result; |
| + wait_state_ = state; |
| + } |
| + event_.Signal(); |
| + } |
| + |
| + base::WaitableEvent event_; |
| + MojoResult wait_result_ = MOJO_RESULT_UNKNOWN; |
| + MojoHandleSignalsState wait_state_ = {0, 0}; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Context); |
| + }; |
| + |
| + scoped_refptr<Context> context_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Waiter); |
| +}; |
| + |
| +} // namespace |
| #if defined(OS_MACOSX) && !defined(OS_IOS) |
| namespace { |
| @@ -130,9 +228,7 @@ std::string MojoTestBase::ReadMessageWithHandles( |
| MojoHandle mp, |
| MojoHandle* handles, |
| uint32_t expected_num_handles) { |
| - CHECK_EQ(MojoWait(mp, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, |
| - nullptr), |
| - MOJO_RESULT_OK); |
| + CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK); |
| uint32_t message_size = 0; |
| uint32_t num_handles = 0; |
| @@ -154,9 +250,7 @@ std::string MojoTestBase::ReadMessageWithHandles( |
| // static |
| std::string MojoTestBase::ReadMessageWithOptionalHandle(MojoHandle mp, |
| MojoHandle* handle) { |
| - CHECK_EQ(MojoWait(mp, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, |
| - nullptr), |
| - MOJO_RESULT_OK); |
| + CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK); |
| uint32_t message_size = 0; |
| uint32_t num_handles = 0; |
| @@ -191,9 +285,7 @@ std::string MojoTestBase::ReadMessage(MojoHandle mp) { |
| void MojoTestBase::ReadMessage(MojoHandle mp, |
| char* data, |
| size_t num_bytes) { |
| - CHECK_EQ(MojoWait(mp, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, |
| - nullptr), |
| - MOJO_RESULT_OK); |
| + CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK); |
| uint32_t message_size = 0; |
| uint32_t num_handles = 0; |
| @@ -288,8 +380,7 @@ void MojoTestBase::CreateDataPipe(MojoHandle *p0, |
| // static |
| void MojoTestBase::WriteData(MojoHandle producer, const std::string& data) { |
| - CHECK_EQ(MojoWait(producer, MOJO_HANDLE_SIGNAL_WRITABLE, |
| - MOJO_DEADLINE_INDEFINITE, nullptr), |
| + CHECK_EQ(WaitForSignals(producer, MOJO_HANDLE_SIGNAL_WRITABLE), |
| MOJO_RESULT_OK); |
| uint32_t num_bytes = static_cast<uint32_t>(data.size()); |
| CHECK_EQ(MojoWriteData(producer, data.data(), &num_bytes, |
| @@ -300,8 +391,7 @@ void MojoTestBase::WriteData(MojoHandle producer, const std::string& data) { |
| // static |
| std::string MojoTestBase::ReadData(MojoHandle consumer, size_t size) { |
| - CHECK_EQ(MojoWait(consumer, MOJO_HANDLE_SIGNAL_READABLE, |
| - MOJO_DEADLINE_INDEFINITE, nullptr), |
| + CHECK_EQ(WaitForSignals(consumer, MOJO_HANDLE_SIGNAL_READABLE), |
| MOJO_RESULT_OK); |
| std::vector<char> buffer(size); |
| uint32_t num_bytes = static_cast<uint32_t>(size); |
| @@ -313,6 +403,21 @@ std::string MojoTestBase::ReadData(MojoHandle consumer, size_t size) { |
| return std::string(buffer.data(), buffer.size()); |
| } |
| +// static |
| +MojoHandleSignalsState MojoTestBase::GetSignalsState(MojoHandle handle) { |
| + MojoHandleSignalsState signals_state; |
| + CHECK_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(handle, &signals_state)); |
| + return signals_state; |
| +} |
| + |
| +// static |
| +MojoResult MojoTestBase::WaitForSignals(MojoHandle handle, |
| + MojoHandleSignals signals, |
| + MojoHandleSignalsState* state) { |
| + Waiter waiter; |
| + return waiter.Wait(handle, signals, state); |
| +} |
| + |
| } // namespace test |
| } // namespace edk |
| } // namespace mojo |