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

Side by Side Diff: mojo/public/cpp/system/tests/wait_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.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/strings/string_piece.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/threading/simple_thread.h"
15 #include "base/time/time.h"
16 #include "mojo/public/c/system/types.h"
17 #include "mojo/public/cpp/system/handle_signals_state.h"
18 #include "mojo/public/cpp/system/message_pipe.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace mojo {
22 namespace {
23
24 using WaitTest = testing::Test;
25 using WaitManyTest = testing::Test;
26
27 void WriteMessage(const ScopedMessagePipeHandle& handle,
28 const base::StringPiece& message) {
29 MojoResult rv = WriteMessageRaw(handle.get(), message.data(),
30 static_cast<uint32_t>(message.size()),
31 nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
32 CHECK_EQ(MOJO_RESULT_OK, rv);
33 }
34
35 std::string ReadMessage(const ScopedMessagePipeHandle& handle) {
36 uint32_t num_bytes = 0;
37 uint32_t num_handles = 0;
38 MojoResult rv = ReadMessageRaw(handle.get(), nullptr, &num_bytes, nullptr,
39 &num_handles, MOJO_READ_MESSAGE_FLAG_NONE);
40 CHECK_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, rv);
41 CHECK_EQ(0u, num_handles);
42
43 std::vector<char> buffer(num_bytes);
44 rv = ReadMessageRaw(handle.get(), buffer.data(), &num_bytes, nullptr,
45 &num_handles, MOJO_READ_MESSAGE_FLAG_NONE);
46 CHECK_EQ(MOJO_RESULT_OK, rv);
47 return std::string(buffer.data(), buffer.size());
48 }
49
50 class ThreadedRunner : public base::SimpleThread {
51 public:
52 explicit ThreadedRunner(const base::Closure& callback)
53 : SimpleThread("ThreadedRunner"), callback_(callback) {}
54 ~ThreadedRunner() override { Join(); }
55
56 void Run() override { callback_.Run(); }
57
58 private:
59 const base::Closure callback_;
60
61 DISALLOW_COPY_AND_ASSIGN(ThreadedRunner);
62 };
63
64 TEST_F(WaitTest, InvalidArguments) {
65 Handle invalid_handle;
66
67 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
68 Wait(invalid_handle, MOJO_HANDLE_SIGNAL_READABLE));
69
70 MessagePipe p;
71 Handle valid_handles[2] = {p.handle0.get(), p.handle1.get()};
72 Handle invalid_handles[2];
73 MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_NONE,
74 MOJO_HANDLE_SIGNAL_NONE};
75 size_t result_index = 0;
76 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
77 WaitMany(invalid_handles, signals, 2, &result_index));
78 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
79 WaitMany(nullptr, signals, 2, &result_index));
80 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
81 WaitMany(valid_handles, nullptr, 2, &result_index));
82 }
83
84 TEST_F(WaitTest, Basic) {
85 MessagePipe p;
86
87 // Write to one end of the pipe and wait on the other.
88 const char kTestMessage1[] = "how about a nice game of chess?";
89 WriteMessage(p.handle0, kTestMessage1);
90 EXPECT_EQ(MOJO_RESULT_OK, Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE));
91
92 // And make sure we can also grab the handle signals state (with both the C
93 // and C++ library structs.)
94
95 MojoHandleSignalsState c_hss = {0, 0};
96 EXPECT_EQ(MOJO_RESULT_OK,
97 Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &c_hss));
98 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
99 c_hss.satisfied_signals);
100 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
101 MOJO_HANDLE_SIGNAL_PEER_CLOSED,
102 c_hss.satisfiable_signals);
103
104 HandleSignalsState hss;
105 EXPECT_EQ(MOJO_RESULT_OK,
106 Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &hss));
107 EXPECT_TRUE(hss.readable() && hss.writable() && !hss.peer_closed());
108 EXPECT_FALSE(hss.never_readable() || hss.never_writable() ||
109 hss.never_peer_closed());
110
111 // Now close the writing end and wait for peer closure.
112
113 p.handle0.reset();
114 EXPECT_EQ(MOJO_RESULT_OK,
115 Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss));
116
117 // Still readable as there's still a message queued. No longer writable as
118 // peer closure has been detected.
119 EXPECT_TRUE(hss.readable() && hss.peer_closed() && !hss.writable());
120 EXPECT_TRUE(hss.never_writable() && !hss.never_readable() &&
121 !hss.never_peer_closed());
122
123 // Read the message and wait for readable again. Waiting should fail since
124 // there are no more messages and the peer is closed.
125 EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1));
126 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
127 Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &hss));
128
129 // Sanity check the signals state again.
130 EXPECT_TRUE(hss.peer_closed() && !hss.readable() && !hss.writable());
131 EXPECT_TRUE(hss.never_readable() && hss.never_writable() &&
132 !hss.never_peer_closed());
133 }
134
135 TEST_F(WaitTest, DelayedWrite) {
136 MessagePipe p;
137
138 ThreadedRunner write_after_delay(base::Bind(
139 [](ScopedMessagePipeHandle* handle) {
140 // Wait a little while, then write a message.
141 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
142 WriteMessage(*handle, "wakey wakey");
143 },
144 &p.handle0));
145 write_after_delay.Start();
146
147 HandleSignalsState hss;
148 EXPECT_EQ(MOJO_RESULT_OK,
149 Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &hss));
150 EXPECT_TRUE(hss.readable() && hss.writable() && !hss.peer_closed());
151 EXPECT_TRUE(!hss.never_readable() && !hss.never_writable() &&
152 !hss.never_peer_closed());
153 }
154
155 TEST_F(WaitTest, DelayedPeerClosure) {
156 MessagePipe p;
157
158 ThreadedRunner close_after_delay(base::Bind(
159 [](ScopedMessagePipeHandle* handle) {
160 // Wait a little while, then close the handle.
161 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
162 handle->reset();
163 },
164 &p.handle0));
165 close_after_delay.Start();
166
167 HandleSignalsState hss;
168 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
169 Wait(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE, &hss));
170 EXPECT_TRUE(!hss.readable() && !hss.writable() && hss.peer_closed());
171 EXPECT_TRUE(hss.never_readable() && hss.never_writable() &&
172 !hss.never_peer_closed());
173 }
174
175 TEST_F(WaitTest, CloseWhileWaiting) {
176 MessagePipe p;
177 ThreadedRunner close_after_delay(base::Bind(
178 [](ScopedMessagePipeHandle* handle) {
179 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
180 handle->reset();
181 },
182 &p.handle0));
183 close_after_delay.Start();
184 EXPECT_EQ(MOJO_RESULT_CANCELLED,
185 Wait(p.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE));
186 }
187
188 TEST_F(WaitManyTest, Basic) {
189 MessagePipe p;
190
191 const char kTestMessage1[] = "hello";
192 WriteMessage(p.handle0, kTestMessage1);
193
194 // Wait for either handle to become readable. Wait twice, just to verify that
195 // we can use either the C or C++ signaling state structure for the last
196 // argument.
197
198 Handle handles[2] = {p.handle0.get(), p.handle1.get()};
199 MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE,
200 MOJO_HANDLE_SIGNAL_READABLE};
201 size_t result_index = 0;
202 MojoHandleSignalsState c_hss[2];
203 HandleSignalsState hss[2];
204
205 EXPECT_EQ(MOJO_RESULT_OK,
206 WaitMany(handles, signals, 2, &result_index, c_hss));
207 EXPECT_EQ(1u, result_index);
208 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, c_hss[0].satisfied_signals);
209 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
210 MOJO_HANDLE_SIGNAL_PEER_CLOSED,
211 c_hss[0].satisfiable_signals);
212 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
213 c_hss[1].satisfied_signals);
214 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
215 MOJO_HANDLE_SIGNAL_PEER_CLOSED,
216 c_hss[1].satisfiable_signals);
217
218 EXPECT_EQ(MOJO_RESULT_OK, WaitMany(handles, signals, 2, &result_index, hss));
219 EXPECT_EQ(1u, result_index);
220 EXPECT_TRUE(!hss[0].readable() && hss[0].writable() && !hss[0].peer_closed());
221 EXPECT_TRUE(!hss[0].never_readable() && !hss[0].never_writable() &&
222 !hss[0].never_peer_closed());
223 EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed());
224 EXPECT_TRUE(!hss[1].never_readable() && !hss[1].never_writable() &&
225 !hss[1].never_peer_closed());
226
227 // Close the writer and read the message. Try to wait again, and it should
228 // fail due to the conditions being unsatisfiable.
229
230 EXPECT_EQ(kTestMessage1, ReadMessage(p.handle1));
231 p.handle0.reset();
232
233 // handles[0] is invalid.
234 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
235 WaitMany(handles, signals, 2, &result_index, hss));
236 handles[0] = handles[1];
237 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
238 WaitMany(handles, signals, 1, &result_index, hss));
239 EXPECT_EQ(0u, result_index);
240 EXPECT_TRUE(!hss[0].readable() && !hss[0].writable() && hss[0].peer_closed());
241 EXPECT_TRUE(hss[0].never_readable() && hss[0].never_writable() &&
242 !hss[0].never_peer_closed());
243 }
244
245 TEST_F(WaitManyTest, CloseWhileWaiting) {
246 MessagePipe p, q;
247
248 Handle handles[3] = {q.handle0.get(), q.handle1.get(), p.handle1.get()};
249 MojoHandleSignals signals[3] = {MOJO_HANDLE_SIGNAL_READABLE,
250 MOJO_HANDLE_SIGNAL_READABLE,
251 MOJO_HANDLE_SIGNAL_READABLE};
252
253 ThreadedRunner close_after_delay(base::Bind(
254 [](ScopedMessagePipeHandle* handle) {
255 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
256 handle->reset();
257 },
258 &p.handle1));
259 close_after_delay.Start();
260
261 size_t result_index = 0;
262 EXPECT_EQ(MOJO_RESULT_CANCELLED,
263 WaitMany(handles, signals, 3, &result_index));
264 EXPECT_EQ(2u, result_index);
265 }
266
267 TEST_F(WaitManyTest, DelayedWrite) {
268 MessagePipe p;
269
270 ThreadedRunner write_after_delay(base::Bind(
271 [](ScopedMessagePipeHandle* handle) {
272 // Wait a little while, then write a message.
273 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
274 WriteMessage(*handle, "wakey wakey");
275 },
276 &p.handle0));
277 write_after_delay.Start();
278
279 Handle handles[2] = {p.handle0.get(), p.handle1.get()};
280 MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE,
281 MOJO_HANDLE_SIGNAL_READABLE};
282 size_t result_index = 0;
283 HandleSignalsState hss[2];
284 EXPECT_EQ(MOJO_RESULT_OK, WaitMany(handles, signals, 2, &result_index, hss));
285 EXPECT_EQ(1u, result_index);
286 EXPECT_TRUE(!hss[0].readable() && hss[0].writable() && !hss[0].peer_closed());
287 EXPECT_TRUE(!hss[0].never_readable() && !hss[0].never_writable() &&
288 !hss[0].never_peer_closed());
289 EXPECT_TRUE(hss[1].readable() && hss[1].writable() && !hss[1].peer_closed());
290 EXPECT_TRUE(!hss[1].never_readable() && !hss[1].never_writable() &&
291 !hss[1].never_peer_closed());
292 }
293
294 TEST_F(WaitManyTest, DelayedPeerClosure) {
295 MessagePipe p, q;
296
297 ThreadedRunner close_after_delay(base::Bind(
298 [](ScopedMessagePipeHandle* handle) {
299 // Wait a little while, then close the handle.
300 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
301 handle->reset();
302 },
303 &p.handle0));
304 close_after_delay.Start();
305
306 Handle handles[3] = {q.handle0.get(), q.handle1.get(), p.handle1.get()};
307 MojoHandleSignals signals[3] = {MOJO_HANDLE_SIGNAL_READABLE,
308 MOJO_HANDLE_SIGNAL_READABLE,
309 MOJO_HANDLE_SIGNAL_READABLE};
310 size_t result_index = 0;
311 HandleSignalsState hss[3];
312 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
313 WaitMany(handles, signals, 3, &result_index, hss));
314 EXPECT_EQ(2u, result_index);
315 EXPECT_TRUE(!hss[2].readable() && !hss[2].writable() && hss[2].peer_closed());
316 EXPECT_TRUE(hss[2].never_readable() && hss[2].never_writable() &&
317 !hss[2].never_peer_closed());
318 }
319
320 } // namespace
321 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698