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..d7d3b2a0a75032508a2040c30d0fac21be8d7ec5 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,103 @@ 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(); |
+ |
+ // Balanced by OnNotification in the |MOJO_RESULT_CANCELLED| case. |
+ context_->AddRef(); |
+ |
+ MojoResult rv = MojoWatch(watcher, handle, signals, |
+ reinterpret_cast<uintptr_t>(context_.get())); |
+ DCHECK_EQ(MOJO_RESULT_OK, rv); |
+ |
+ uint32_t num_ready_contexts = 1; |
+ uintptr_t ready_context; |
+ MojoResult ready_result; |
+ MojoHandleSignalsState ready_state; |
+ 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_value, |
+ MojoResult result, |
+ MojoHandleSignalsState state, |
+ MojoWatcherNotificationFlags flags) { |
+ auto* context = reinterpret_cast<Context*>(context_value); |
+ context->Notify(result, state); |
+ if (result == MOJO_RESULT_CANCELLED) |
+ context->Release(); |
+ } |
+ |
+ 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 +230,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 +252,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 +287,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 +382,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 +393,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 +405,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 |