Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(707)

Unified Diff: mojo/public/cpp/system/tests/wait_set_unittest.cc

Issue 2744943002: Mojo: Move waiting APIs to public library (Closed)
Patch Set: . Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/public/cpp/system/tests/core_unittest.cc ('k') | mojo/public/cpp/system/tests/wait_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
new file mode 100644
index 0000000000000000000000000000000000000000..2a6d9b88256b32e9857971e6d2037454d3c6077f
--- /dev/null
+++ b/mojo/public/cpp/system/tests/wait_set_unittest.cc
@@ -0,0 +1,260 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/system/wait_set.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/threading/platform_thread.h"
+#include "base/threading/simple_thread.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+using WaitSetTest = testing::Test;
+
+void WriteMessage(const ScopedMessagePipeHandle& handle,
+ const base::StringPiece& message) {
+ MojoResult rv = WriteMessageRaw(handle.get(), message.data(),
+ static_cast<uint32_t>(message.size()),
+ nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
+ CHECK_EQ(MOJO_RESULT_OK, rv);
+}
+
+std::string ReadMessage(const ScopedMessagePipeHandle& handle) {
+ uint32_t num_bytes = 0;
+ uint32_t num_handles = 0;
+ MojoResult rv = ReadMessageRaw(handle.get(), nullptr, &num_bytes, nullptr,
+ &num_handles, MOJO_READ_MESSAGE_FLAG_NONE);
+ CHECK_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, rv);
+ CHECK_EQ(0u, num_handles);
+
+ std::vector<char> buffer(num_bytes);
+ rv = ReadMessageRaw(handle.get(), buffer.data(), &num_bytes, nullptr,
+ &num_handles, MOJO_READ_MESSAGE_FLAG_NONE);
+ CHECK_EQ(MOJO_RESULT_OK, rv);
+ return std::string(buffer.data(), buffer.size());
+}
+
+class ThreadedRunner : public base::SimpleThread {
+ public:
+ explicit ThreadedRunner(const base::Closure& callback)
+ : SimpleThread("ThreadedRunner"), callback_(callback) {}
+ ~ThreadedRunner() override { Join(); }
+
+ void Run() override { callback_.Run(); }
+
+ private:
+ const base::Closure callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadedRunner);
+};
+
+TEST_F(WaitSetTest, Satisfied) {
+ WaitSet wait_set;
+ MessagePipe p;
+
+ const char kTestMessage1[] = "hello wake up";
+
+ // Watch only one handle and write to the other.
+
+ wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ WriteMessage(p.handle0, kTestMessage1);
+
+ size_t num_ready_handles = 2;
+ 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);
+
+ EXPECT_EQ(1u, num_ready_handles);
+ EXPECT_EQ(p.handle1.get(), ready_handles[0]);
+ EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
+ EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed());
+
+ wait_set.RemoveHandle(p.handle1.get());
+
+ // Now watch only the other handle and write to the first one.
+
+ wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ WriteMessage(p.handle1, kTestMessage1);
+
+ 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);
+
+ EXPECT_EQ(1u, num_ready_handles);
+ EXPECT_EQ(p.handle0.get(), ready_handles[0]);
+ EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
+ EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed());
+
+ // Now wait on both of them.
+ wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
+
+ 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);
+ EXPECT_EQ(2u, num_ready_handles);
+ EXPECT_TRUE((ready_handles[0] == p.handle0.get() &&
+ ready_handles[1] == p.handle1.get()) ||
+ (ready_handles[0] == p.handle1.get() &&
+ ready_handles[1] == p.handle0.get()));
+ EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
+ EXPECT_EQ(MOJO_RESULT_OK, ready_results[1]);
+ EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed());
+ EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed());
+
+ // 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);
+ EXPECT_EQ(1u, num_ready_handles);
+ EXPECT_TRUE(ready_handles[0] == p.handle0.get() ||
+ ready_handles[0] == p.handle1.get());
+ EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
+
+ // Remove the ready handle from the set and wait one more time.
+ EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0]));
+
+ num_ready_handles = 1;
+ ready_results[0] = MOJO_RESULT_UNKNOWN;
+ wait_set.Wait(&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());
+ EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
+
+ EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0]));
+
+ // 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);
+ EXPECT_EQ(0u, num_ready_handles);
+}
+
+TEST_F(WaitSetTest, Unsatisfiable) {
+ MessagePipe p, q;
+ WaitSet wait_set;
+
+ wait_set.AddHandle(q.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ wait_set.AddHandle(q.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
+
+ size_t num_ready_handles = 2;
+ Handle ready_handles[2];
+ MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
+
+ p.handle1.reset();
+ wait_set.Wait(&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]);
+}
+
+TEST_F(WaitSetTest, CloseWhileWaiting) {
+ MessagePipe p;
+ WaitSet wait_set;
+
+ wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
+
+ const Handle handle0_value = p.handle0.get();
+ ThreadedRunner close_after_delay(base::Bind(
+ [](ScopedMessagePipeHandle* handle) {
+ // Wait a little while, then close the handle.
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
+ handle->reset();
+ },
+ &p.handle0));
+ close_after_delay.Start();
+
+ 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);
+ EXPECT_EQ(1u, num_ready_handles);
+ EXPECT_EQ(handle0_value, ready_handles[0]);
+ EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_results[0]);
+
+ EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value));
+}
+
+TEST_F(WaitSetTest, CloseBeforeWaiting) {
+ MessagePipe p;
+ WaitSet wait_set;
+
+ wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
+
+ Handle handle0_value = p.handle0.get();
+ Handle handle1_value = p.handle1.get();
+
+ p.handle0.reset();
+ p.handle1.reset();
+
+ // Ensure that the WaitSet user is always made aware of all cancellations even
+ // if they happen while not waiting, or they have to be returned over the span
+ // of multiple Wait() calls due to insufficient output storage.
+
+ 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);
+ 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);
+ 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);
+ EXPECT_EQ(0u, num_ready_handles);
+}
+
+TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) {
+ MessagePipe p;
+ WaitSet wait_set;
+
+ wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
+
+ const char kTestMessage1[] = "testing testing testing";
+ WriteMessage(p.handle0, kTestMessage1);
+
+ 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);
+ EXPECT_EQ(1u, num_ready_handles);
+ EXPECT_EQ(p.handle1.get(), ready_handles[0]);
+ EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
+
+ EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1));
+
+ ThreadedRunner write_after_delay(base::Bind(
+ [](ScopedMessagePipeHandle* handle) {
+ // Wait a little while, then write a message.
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
+ WriteMessage(*handle, "wakey wakey");
+ },
+ &p.handle1));
+ write_after_delay.Start();
+
+ num_ready_handles = 2;
+ wait_set.Wait(&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]);
+}
+
+} // namespace
+} // namespace mojo
« no previous file with comments | « mojo/public/cpp/system/tests/core_unittest.cc ('k') | mojo/public/cpp/system/tests/wait_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698