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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "mojo/public/cpp/system/wait_set.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/threading/platform_thread.h"
10 #include "base/threading/simple_thread.h"
11 #include "mojo/public/cpp/system/message_pipe.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace mojo {
15 namespace {
16
17 using WaitSetTest = testing::Test;
18
19 void WriteMessage(const ScopedMessagePipeHandle& handle,
20 const base::StringPiece& message) {
21 MojoResult rv = WriteMessageRaw(handle.get(), message.data(),
22 static_cast<uint32_t>(message.size()),
23 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
24 CHECK_EQ(MOJO_RESULT_OK, rv);
25 }
26
27 std::string ReadMessage(const ScopedMessagePipeHandle& handle) {
28 uint32_t num_bytes = 0;
29 uint32_t num_handles = 0;
30 MojoResult rv = ReadMessageRaw(handle.get(), nullptr, &num_bytes, nullptr,
31 &num_handles, MOJO_READ_MESSAGE_FLAG_NONE);
32 CHECK_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, rv);
33 CHECK_EQ(0u, num_handles);
34
35 std::vector<char> buffer(num_bytes);
36 rv = ReadMessageRaw(handle.get(), buffer.data(), &num_bytes, nullptr,
37 &num_handles, MOJO_READ_MESSAGE_FLAG_NONE);
38 CHECK_EQ(MOJO_RESULT_OK, rv);
39 return std::string(buffer.data(), buffer.size());
40 }
41
42 class ThreadedRunner : public base::SimpleThread {
43 public:
44 explicit ThreadedRunner(const base::Closure& callback)
45 : SimpleThread("ThreadedRunner"), callback_(callback) {}
46 ~ThreadedRunner() override { Join(); }
47
48 void Run() override { callback_.Run(); }
49
50 private:
51 const base::Closure callback_;
52
53 DISALLOW_COPY_AND_ASSIGN(ThreadedRunner);
54 };
55
56 TEST_F(WaitSetTest, Satisfied) {
57 WaitSet wait_set;
58 MessagePipe p;
59
60 const char kTestMessage1[] = "hello wake up";
61
62 // Watch only one handle and write to the other.
63
64 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
65 WriteMessage(p.handle0, kTestMessage1);
66
67 size_t num_ready_handles = 2;
68 Handle ready_handles[2];
69 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
70 HandleSignalsState hss[2];
71 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
72
73 EXPECT_EQ(1u, num_ready_handles);
74 EXPECT_EQ(p.handle1.get(), ready_handles[0]);
75 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
76 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed());
77
78 wait_set.RemoveHandle(p.handle1.get());
79
80 // Now watch only the other handle and write to the first one.
81
82 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
83 WriteMessage(p.handle1, kTestMessage1);
84
85 num_ready_handles = 2;
86 ready_results[0] = MOJO_RESULT_UNKNOWN;
87 ready_results[1] = MOJO_RESULT_UNKNOWN;
88 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
89
90 EXPECT_EQ(1u, num_ready_handles);
91 EXPECT_EQ(p.handle0.get(), ready_handles[0]);
92 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
93 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed());
94
95 // Now wait on both of them.
96 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
97
98 num_ready_handles = 2;
99 ready_results[0] = MOJO_RESULT_UNKNOWN;
100 ready_results[1] = MOJO_RESULT_UNKNOWN;
101 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
102 EXPECT_EQ(2u, num_ready_handles);
103 EXPECT_TRUE((ready_handles[0] == p.handle0.get() &&
104 ready_handles[1] == p.handle1.get()) ||
105 (ready_handles[0] == p.handle1.get() &&
106 ready_handles[1] == p.handle0.get()));
107 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
108 EXPECT_EQ(MOJO_RESULT_OK, ready_results[1]);
109 EXPECT_TRUE(hss[0].readable() && hss[0].writable() && !hss[0].peer_closed());
110 EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed());
111
112 // Wait on both again, but with only enough output space for one result.
113 num_ready_handles = 1;
114 ready_results[0] = MOJO_RESULT_UNKNOWN;
115 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
116 EXPECT_EQ(1u, num_ready_handles);
117 EXPECT_TRUE(ready_handles[0] == p.handle0.get() ||
118 ready_handles[0] == p.handle1.get());
119 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
120
121 // Remove the ready handle from the set and wait one more time.
122 EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0]));
123
124 num_ready_handles = 1;
125 ready_results[0] = MOJO_RESULT_UNKNOWN;
126 wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
127 EXPECT_EQ(1u, num_ready_handles);
128 EXPECT_TRUE(ready_handles[0] == p.handle0.get() ||
129 ready_handles[0] == p.handle1.get());
130 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
131
132 EXPECT_EQ(MOJO_RESULT_OK, wait_set.RemoveHandle(ready_handles[0]));
133
134 // The wait set should be empty now. Nothing to wait on.
135 num_ready_handles = 2;
136 wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
137 EXPECT_EQ(0u, num_ready_handles);
138 }
139
140 TEST_F(WaitSetTest, Unsatisfiable) {
141 MessagePipe p, q;
142 WaitSet wait_set;
143
144 wait_set.AddHandle(q.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
145 wait_set.AddHandle(q.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
146 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
147
148 size_t num_ready_handles = 2;
149 Handle ready_handles[2];
150 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
151
152 p.handle1.reset();
153 wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
154 EXPECT_EQ(1u, num_ready_handles);
155 EXPECT_EQ(p.handle0.get(), ready_handles[0]);
156 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]);
157 }
158
159 TEST_F(WaitSetTest, CloseWhileWaiting) {
160 MessagePipe p;
161 WaitSet wait_set;
162
163 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
164
165 const Handle handle0_value = p.handle0.get();
166 ThreadedRunner close_after_delay(base::Bind(
167 [](ScopedMessagePipeHandle* handle) {
168 // Wait a little while, then close the handle.
169 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
170 handle->reset();
171 },
172 &p.handle0));
173 close_after_delay.Start();
174
175 size_t num_ready_handles = 2;
176 Handle ready_handles[2];
177 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
178 wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
179 EXPECT_EQ(1u, num_ready_handles);
180 EXPECT_EQ(handle0_value, ready_handles[0]);
181 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_results[0]);
182
183 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value));
184 }
185
186 TEST_F(WaitSetTest, CloseBeforeWaiting) {
187 MessagePipe p;
188 WaitSet wait_set;
189
190 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
191 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
192
193 Handle handle0_value = p.handle0.get();
194 Handle handle1_value = p.handle1.get();
195
196 p.handle0.reset();
197 p.handle1.reset();
198
199 // Ensure that the WaitSet user is always made aware of all cancellations even
200 // if they happen while not waiting, or they have to be returned over the span
201 // of multiple Wait() calls due to insufficient output storage.
202
203 size_t num_ready_handles = 1;
204 Handle ready_handle;
205 MojoResult ready_result = MOJO_RESULT_UNKNOWN;
206 wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
207 EXPECT_EQ(1u, num_ready_handles);
208 EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value);
209 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result);
210 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value));
211
212 wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
213 EXPECT_EQ(1u, num_ready_handles);
214 EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value);
215 EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result);
216 EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value));
217
218 // Nothing more to wait on.
219 wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
220 EXPECT_EQ(0u, num_ready_handles);
221 }
222
223 TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) {
224 MessagePipe p;
225 WaitSet wait_set;
226
227 wait_set.AddHandle(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
228 wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
229
230 const char kTestMessage1[] = "testing testing testing";
231 WriteMessage(p.handle0, kTestMessage1);
232
233 size_t num_ready_handles = 2;
234 Handle ready_handles[2];
235 MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
236 wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
237 EXPECT_EQ(1u, num_ready_handles);
238 EXPECT_EQ(p.handle1.get(), ready_handles[0]);
239 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
240
241 EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1));
242
243 ThreadedRunner write_after_delay(base::Bind(
244 [](ScopedMessagePipeHandle* handle) {
245 // Wait a little while, then write a message.
246 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
247 WriteMessage(*handle, "wakey wakey");
248 },
249 &p.handle1));
250 write_after_delay.Start();
251
252 num_ready_handles = 2;
253 wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
254 EXPECT_EQ(1u, num_ready_handles);
255 EXPECT_EQ(p.handle0.get(), ready_handles[0]);
256 EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
257 }
258
259 } // namespace
260 } // namespace mojo
OLDNEW
« 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