Index: mojo/edk/embedder/embedder_unittest.cc |
diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc |
index 03937489025e2008975704fcc27b0c9089c5a7a7..898362d19f6971840515230177db129ef8469a52 100644 |
--- a/mojo/edk/embedder/embedder_unittest.cc |
+++ b/mojo/edk/embedder/embedder_unittest.cc |
@@ -13,6 +13,7 @@ |
#include "base/message_loop/message_loop.h" |
#include "base/synchronization/waitable_event.h" |
#include "base/test/test_io_thread.h" |
+#include "base/test/test_timeouts.h" |
#include "mojo/edk/embedder/platform_channel_pair.h" |
#include "mojo/edk/embedder/test_embedder.h" |
#include "mojo/edk/system/test_utils.h" |
@@ -160,6 +161,95 @@ TEST_F(EmbedderTest, ChannelsBasic) { |
EXPECT_TRUE(test::Shutdown()); |
} |
+class TestAsyncWaiter { |
+ public: |
+ TestAsyncWaiter() : event_(true, false), wait_result_(MOJO_RESULT_UNKNOWN) {} |
+ |
+ void Awake(MojoResult result) { |
+ base::AutoLock l(wait_result_lock_); |
+ wait_result_ = result; |
+ event_.Signal(); |
+ } |
+ |
+ bool TryWait() { return event_.TimedWait(TestTimeouts::action_timeout()); } |
+ |
+ MojoResult wait_result() const { |
+ base::AutoLock l(wait_result_lock_); |
+ return wait_result_; |
+ } |
+ |
+ private: |
+ base::WaitableEvent event_; |
+ |
+ mutable base::Lock wait_result_lock_; |
+ MojoResult wait_result_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestAsyncWaiter); |
+}; |
+ |
+void WriteHello(MessagePipeHandle pipe) { |
+ static const char kHello[] = "hello"; |
+ CHECK_EQ(MOJO_RESULT_OK, |
+ WriteMessageRaw(pipe, kHello, static_cast<uint32_t>(sizeof(kHello)), |
+ nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
+} |
+ |
+void CloseScopedHandle(ScopedMessagePipeHandle handle) { |
+ // Do nothing and the destructor will close it. |
+} |
+ |
+TEST_F(EmbedderTest, AsyncWait) { |
+ mojo::embedder::test::InitWithSimplePlatformSupport(); |
+ |
+ { |
+ ScopedMessagePipeHandle client_mp; |
+ ScopedMessagePipeHandle server_mp; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ mojo::CreateMessagePipe(nullptr, &client_mp, &server_mp)); |
+ |
+ TestAsyncWaiter waiter; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |
+ base::Bind(&TestAsyncWaiter::Awake, |
+ base::Unretained(&waiter)))); |
+ |
+ test_io_thread()->task_runner()->PostTask( |
+ FROM_HERE, base::Bind(&WriteHello, server_mp.get())); |
+ EXPECT_TRUE(waiter.TryWait()); |
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.wait_result()); |
+ |
+ // If message is in the queue, it does't allow us to wait. |
+ TestAsyncWaiter waiter_that_doesnt_wait; |
+ EXPECT_EQ( |
+ MOJO_RESULT_ALREADY_EXISTS, |
+ AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |
+ base::Bind(&TestAsyncWaiter::Awake, |
+ base::Unretained(&waiter_that_doesnt_wait)))); |
+ |
+ char buffer[1000]; |
+ uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
+ CHECK_EQ(MOJO_RESULT_OK, |
+ ReadMessageRaw(client_mp.get(), buffer, &num_bytes, nullptr, |
+ nullptr, MOJO_READ_MESSAGE_FLAG_NONE)); |
+ |
+ TestAsyncWaiter unsatisfiable_waiter; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ AsyncWait(client_mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, |
+ base::Bind(&TestAsyncWaiter::Awake, |
+ base::Unretained(&unsatisfiable_waiter)))); |
+ |
+ test_io_thread()->task_runner()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&CloseScopedHandle, base::Passed(server_mp.Pass()))); |
+ |
+ EXPECT_TRUE(unsatisfiable_waiter.TryWait()); |
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
+ unsatisfiable_waiter.wait_result()); |
+ } |
+ |
+ EXPECT_TRUE(test::Shutdown()); |
+} |
+ |
TEST_F(EmbedderTest, ChannelsHandlePassing) { |
mojo::embedder::test::InitWithSimplePlatformSupport(); |