1 // Copyright 2013 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 <stdint.h>
6 #include <string.h>
7
8 #include "base/memory/ref_counted.h"
9 #include "mojo/edk/system/test_utils.h"
10 #include "mojo/edk/test/mojo_test_base.h"
11 #include "mojo/public/c/system/core.h"
12 #include "mojo/public/c/system/types.h"
13
14 namespace mojo {
15 namespace edk {
16 namespace {
17
18 const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
19 MOJO_HANDLE_SIGNAL_WRITABLE |
20 MOJO_HANDLE_SIGNAL_PEER_CLOSED;
21 static const char kHelloWorld[] = "hello world";
22
23 class MessagePipeTest : public test::MojoTestBase {
24 public:
MessagePipeTest()25 MessagePipeTest() {
26 CHECK_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &pipe0_, &pipe1_));
27 }
28
~MessagePipeTest()29 ~MessagePipeTest() override {
30 if (pipe0_ != MOJO_HANDLE_INVALID)
31 CHECK_EQ(MOJO_RESULT_OK, MojoClose(pipe0_));
32 if (pipe1_ != MOJO_HANDLE_INVALID)
33 CHECK_EQ(MOJO_RESULT_OK, MojoClose(pipe1_));
34 }
35
WriteMessage(MojoHandle message_pipe_handle,const void * bytes,uint32_t num_bytes)36 MojoResult WriteMessage(MojoHandle message_pipe_handle,
37 const void* bytes,
38 uint32_t num_bytes) {
39 return MojoWriteMessage(message_pipe_handle, bytes, num_bytes, nullptr, 0,
40 MOJO_WRITE_MESSAGE_FLAG_NONE);
41 }
42
ReadMessage(MojoHandle message_pipe_handle,void * bytes,uint32_t * num_bytes,bool may_discard=false)43 MojoResult ReadMessage(MojoHandle message_pipe_handle,
44 void* bytes,
45 uint32_t* num_bytes,
46 bool may_discard = false) {
47 return MojoReadMessage(message_pipe_handle, bytes, num_bytes, nullptr, 0,
48 may_discard ? MOJO_READ_MESSAGE_FLAG_MAY_DISCARD :
49 MOJO_READ_MESSAGE_FLAG_NONE);
50 }
51
52 MojoHandle pipe0_, pipe1_;
53
54 private:
55 DISALLOW_COPY_AND_ASSIGN(MessagePipeTest);
56 };
57
58 using FuseMessagePipeTest = test::MojoTestBase;
59
TEST_F(MessagePipeTest,WriteData)60 TEST_F(MessagePipeTest, WriteData) {
61 ASSERT_EQ(MOJO_RESULT_OK,
62 WriteMessage(pipe0_, kHelloWorld, sizeof(kHelloWorld)));
63 }
64
65 // Tests:
66 // - only default flags
67 // - reading messages from a port
68 // - when there are no/one/two messages available for that port
69 // - with buffer size 0 (and null buffer) -- should get size
70 // - with too-small buffer -- should get size
71 // - also verify that buffers aren't modified when/where they shouldn't be
72 // - writing messages to a port
73 // - in the obvious scenarios (as above)
74 // - to a port that's been closed
75 // - writing a message to a port, closing the other (would be the source) port,
76 // and reading it
TEST_F(MessagePipeTest,Basic)77 TEST_F(MessagePipeTest, Basic) {
78 int32_t buffer[2];
79 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
80 uint32_t buffer_size;
81
82 // Nothing to read yet on port 0.
83 buffer[0] = 123;
84 buffer[1] = 456;
85 buffer_size = kBufferSize;
86 ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe0_, buffer, &buffer_size));
87 ASSERT_EQ(kBufferSize, buffer_size);
88 ASSERT_EQ(123, buffer[0]);
89 ASSERT_EQ(456, buffer[1]);
90
91 // Ditto for port 1.
92 buffer[0] = 123;
93 buffer[1] = 456;
94 buffer_size = kBufferSize;
95 ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe1_, buffer, &buffer_size));
96
97 // Write from port 1 (to port 0).
98 buffer[0] = 789012345;
99 buffer[1] = 0;
100 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0])));
101
102 MojoHandleSignalsState state;
103 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_READABLE,
104 MOJO_DEADLINE_INDEFINITE, &state));
105
106 // Read from port 0.
107 buffer[0] = 123;
108 buffer[1] = 456;
109 buffer_size = kBufferSize;
110 ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe0_, buffer, &buffer_size));
111 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
112 ASSERT_EQ(789012345, buffer[0]);
113 ASSERT_EQ(456, buffer[1]);
114
115 // Read again from port 0 -- it should be empty.
116 buffer_size = kBufferSize;
117 ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe0_, buffer, &buffer_size));
118
119 // Write two messages from port 0 (to port 1).
120 buffer[0] = 123456789;
121 buffer[1] = 0;
122 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0])));
123 buffer[0] = 234567890;
124 buffer[1] = 0;
125 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0])));
126
127 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_READABLE,
128 MOJO_DEADLINE_INDEFINITE, &state));
129
130 // Read from port 1 with buffer size 0 (should get the size of next message).
131 // Also test that giving a null buffer is okay when the buffer size is 0.
132 buffer_size = 0;
133 ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
134 ReadMessage(pipe1_, nullptr, &buffer_size));
135 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
136
137 // Read from port 1 with buffer size 1 (too small; should get the size of next
138 // message).
139 buffer[0] = 123;
140 buffer[1] = 456;
141 buffer_size = 1;
142 ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
143 ReadMessage(pipe1_, buffer, &buffer_size));
144 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
145 ASSERT_EQ(123, buffer[0]);
146 ASSERT_EQ(456, buffer[1]);
147
148 // Read from port 1.
149 buffer[0] = 123;
150 buffer[1] = 456;
151 buffer_size = kBufferSize;
152 ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size));
153 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
154 ASSERT_EQ(123456789, buffer[0]);
155 ASSERT_EQ(456, buffer[1]);
156
157 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_READABLE,
158 MOJO_DEADLINE_INDEFINITE, &state));
159
160 // Read again from port 1.
161 buffer[0] = 123;
162 buffer[1] = 456;
163 buffer_size = kBufferSize;
164 ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size));
165 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
166 ASSERT_EQ(234567890, buffer[0]);
167 ASSERT_EQ(456, buffer[1]);
168
169 // Read again from port 1 -- it should be empty.
170 buffer_size = kBufferSize;
171 ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe1_, buffer, &buffer_size));
172
173 // Write from port 0 (to port 1).
174 buffer[0] = 345678901;
175 buffer[1] = 0;
176 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0])));
177
178 // Close port 0.
179 MojoClose(pipe0_);
180 pipe0_ = MOJO_HANDLE_INVALID;
181
182 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
183 MOJO_DEADLINE_INDEFINITE, &state));
184
185 // Try to write from port 1 (to port 0).
186 buffer[0] = 456789012;
187 buffer[1] = 0;
188 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
189 WriteMessage(pipe1_, buffer, sizeof(buffer[0])));
190
191 // Read from port 1; should still get message (even though port 0 was closed).
192 buffer[0] = 123;
193 buffer[1] = 456;
194 buffer_size = kBufferSize;
195 ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size));
196 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
197 ASSERT_EQ(345678901, buffer[0]);
198 ASSERT_EQ(456, buffer[1]);
199
200 // Read again from port 1 -- it should be empty (and port 0 is closed).
201 buffer_size = kBufferSize;
202 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
203 ReadMessage(pipe1_, buffer, &buffer_size));
204 }
205
TEST_F(MessagePipeTest,CloseWithQueuedIncomingMessages)206 TEST_F(MessagePipeTest, CloseWithQueuedIncomingMessages) {
207 int32_t buffer[1];
208 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
209 uint32_t buffer_size;
210
211 // Write some messages from port 1 (to port 0).
212 for (int32_t i = 0; i < 5; i++) {
213 buffer[0] = i;
214 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, kBufferSize));
215 }
216
217 MojoHandleSignalsState state;
218 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_READABLE,
219 MOJO_DEADLINE_INDEFINITE, &state));
220
221 // Port 0 shouldn't be empty.
222 buffer_size = 0;
223 ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
224 ReadMessage(pipe0_, nullptr, &buffer_size));
225 ASSERT_EQ(kBufferSize, buffer_size);
226
227 // Close port 0 first, which should have outstanding (incoming) messages.
228 MojoClose(pipe0_);
229 MojoClose(pipe1_);
230 pipe0_ = pipe1_ = MOJO_HANDLE_INVALID;
231 }
232
TEST_F(MessagePipeTest,DiscardMode)233 TEST_F(MessagePipeTest, DiscardMode) {
234 int32_t buffer[2];
235 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
236 uint32_t buffer_size;
237
238 // Write from port 1 (to port 0).
239 buffer[0] = 789012345;
240 buffer[1] = 0;
241 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0])));
242
243 MojoHandleSignalsState state;
244 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_READABLE,
245 MOJO_DEADLINE_INDEFINITE, &state));
246
247 // Read/discard from port 0 (no buffer); get size.
248 buffer_size = 0;
249 ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
250 ReadMessage(pipe0_, nullptr, &buffer_size, true));
251 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
252
253 // Read again from port 0 -- it should be empty.
254 buffer_size = kBufferSize;
255 ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT,
256 ReadMessage(pipe0_, buffer, &buffer_size, true));
257
258 // Write from port 1 (to port 0).
259 buffer[0] = 890123456;
260 buffer[1] = 0;
261 ASSERT_EQ(MOJO_RESULT_OK,
262 WriteMessage(pipe1_, buffer, sizeof(buffer[0])));
263
264 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_READABLE,
265 MOJO_DEADLINE_INDEFINITE, &state));
266
267 // Read from port 0 (buffer big enough).
268 buffer[0] = 123;
269 buffer[1] = 456;
270 buffer_size = kBufferSize;
271 ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe0_, buffer, &buffer_size, true));
272 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
273 ASSERT_EQ(890123456, buffer[0]);
274 ASSERT_EQ(456, buffer[1]);
275
276 // Read again from port 0 -- it should be empty.
277 buffer_size = kBufferSize;
278 ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT,
279 ReadMessage(pipe0_, buffer, &buffer_size, true));
280
281 // Write from port 1 (to port 0).
282 buffer[0] = 901234567;
283 buffer[1] = 0;
284 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0])));
285
286 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_READABLE,
287 MOJO_DEADLINE_INDEFINITE, &state));
288
289 // Read/discard from port 0 (buffer too small); get size.
290 buffer_size = 1;
291 ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
292 ReadMessage(pipe0_, buffer, &buffer_size, true));
293 ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
294
295 // Read again from port 0 -- it should be empty.
296 buffer_size = kBufferSize;
297 ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT,
298 ReadMessage(pipe0_, buffer, &buffer_size, true));
299
300 // Write from port 1 (to port 0).
301 buffer[0] = 123456789;
302 buffer[1] = 0;
303 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0])));
304
305 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_READABLE,
306 MOJO_DEADLINE_INDEFINITE, &state));
307
308 // Discard from port 0.
309 buffer_size = 1;
310 ASSERT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
311 ReadMessage(pipe0_, nullptr, 0, true));
312
313 // Read again from port 0 -- it should be empty.
314 buffer_size = kBufferSize;
315 ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT,
316 ReadMessage(pipe0_, buffer, &buffer_size, true));
317 }
318
TEST_F(MessagePipeTest,BasicWaiting)319 TEST_F(MessagePipeTest, BasicWaiting) {
320 MojoHandleSignalsState hss;
321
322 int32_t buffer[1];
323 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
324 uint32_t buffer_size;
325
326 // Always writable (until the other port is closed).
327 hss = MojoHandleSignalsState();
328 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_WRITABLE, 0,
329 &hss));
330 ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
331 ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
332 hss = MojoHandleSignalsState();
333
334 // Not yet readable.
335 ASSERT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
336 MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss));
337 ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
338 ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
339
340 // The peer is not closed.
341 hss = MojoHandleSignalsState();
342 ASSERT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
343 MojoWait(pipe0_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 0, &hss));
344 ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
345 ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
346
347 // Write from port 0 (to port 1), to make port 1 readable.
348 buffer[0] = 123456789;
349 ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, kBufferSize));
350
351 // Port 1 should already be readable now.
352 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_READABLE,
353 MOJO_DEADLINE_INDEFINITE, &hss));
354 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
355 hss.satisfied_signals);
356 ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
357 // ... and still writable.
358 hss = MojoHandleSignalsState();
359 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_WRITABLE,
360 MOJO_DEADLINE_INDEFINITE, &hss));
361 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
362 hss.satisfied_signals);
363 ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
364
365 // Close port 0.
366 MojoClose(pipe0_);
367 pipe0_ = MOJO_HANDLE_INVALID;
368
369 // Port 1 should be signaled with peer closed.
370 hss = MojoHandleSignalsState();
371 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
372 MOJO_DEADLINE_INDEFINITE, &hss));
373 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
374 hss.satisfied_signals);
375 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
376 hss.satisfiable_signals);
377
378 // Port 1 should not be writable.
379 hss = MojoHandleSignalsState();
380
381 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
382 MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_WRITABLE,
383 MOJO_DEADLINE_INDEFINITE, &hss));
384 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
385 hss.satisfied_signals);
386 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
387 hss.satisfiable_signals);
388
389 // But it should still be readable.
390 hss = MojoHandleSignalsState();
391 ASSERT_EQ(MOJO_RESULT_OK, MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_READABLE,
392 MOJO_DEADLINE_INDEFINITE, &hss));
393 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
394 hss.satisfied_signals);
395 ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
396 hss.satisfiable_signals);
397
398 // Read from port 1.
399 buffer[0] = 0;
400 buffer_size = kBufferSize;
401 ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size));
402 ASSERT_EQ(123456789, buffer[0]);
403
404 // Now port 1 should no longer be readable.
405 hss = MojoHandleSignalsState();
406 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
407 MojoWait(pipe1_, MOJO_HANDLE_SIGNAL_READABLE,
408 MOJO_DEADLINE_INDEFINITE, &hss));
409 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
410 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
411 }
412
TEST_F(MessagePipeTest,InvalidMessageObjects)413 TEST_F(MessagePipeTest, InvalidMessageObjects) {
414 // null message
415 ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
416 MojoFreeMessage(MOJO_MESSAGE_HANDLE_INVALID));
417
418 // null message
419 ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
420 MojoGetMessageBuffer(MOJO_MESSAGE_HANDLE_INVALID, nullptr));
421
422 // Non-zero num_handles with null handles array.
423 ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
424 MojoAllocMessage(0, nullptr, 1, MOJO_ALLOC_MESSAGE_FLAG_NONE,
425 nullptr));
426 }
427
TEST_F(MessagePipeTest,AllocAndFreeMessage)428 TEST_F(MessagePipeTest, AllocAndFreeMessage) {
429 const std::string kMessage = "Hello, world.";
430 MojoMessageHandle message = MOJO_MESSAGE_HANDLE_INVALID;
431 ASSERT_EQ(MOJO_RESULT_OK,
432 MojoAllocMessage(static_cast<uint32_t>(kMessage.size()), nullptr, 0,
433 MOJO_ALLOC_MESSAGE_FLAG_NONE, &message));
434 ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message);
435 ASSERT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message));
436 }
437
TEST_F(MessagePipeTest,WriteAndReadMessageObject)438 TEST_F(MessagePipeTest, WriteAndReadMessageObject) {
439 const std::string kMessage = "Hello, world.";
440 MojoMessageHandle message = MOJO_MESSAGE_HANDLE_INVALID;
441 EXPECT_EQ(MOJO_RESULT_OK,
442 MojoAllocMessage(static_cast<uint32_t>(kMessage.size()), nullptr, 0,
443 MOJO_ALLOC_MESSAGE_FLAG_NONE, &message));
444 ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message);
445
446 void* buffer = nullptr;
447 EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageBuffer(message, &buffer));
448 ASSERT_TRUE(buffer);
449 memcpy(buffer, kMessage.data(), kMessage.size());
450
451 MojoHandle a, b;
452 CreateMessagePipe(&a, &b);
453 EXPECT_EQ(MOJO_RESULT_OK,
454 MojoWriteMessageNew(a, message, MOJO_WRITE_MESSAGE_FLAG_NONE));
455
456 EXPECT_EQ(MOJO_RESULT_OK,
457 MojoWait(b, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE,
458 nullptr));
459 uint32_t num_bytes = 0;
460 uint32_t num_handles = 0;
461 EXPECT_EQ(MOJO_RESULT_OK,
462 MojoReadMessageNew(b, &message, &num_bytes, nullptr, &num_handles,
463 MOJO_READ_MESSAGE_FLAG_NONE));
464 ASSERT_NE(MOJO_MESSAGE_HANDLE_INVALID, message);
465 EXPECT_EQ(static_cast<uint32_t>(kMessage.size()), num_bytes);
466 EXPECT_EQ(0u, num_handles);
467
468 EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageBuffer(message, &buffer));
469 ASSERT_TRUE(buffer);
470
471 EXPECT_EQ(0, strncmp(static_cast<const char*>(buffer), kMessage.data(),
472 num_bytes));
473
474 EXPECT_EQ(MOJO_RESULT_OK, MojoFreeMessage(message));
475 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
476 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
477 }
478
479 #if !defined(OS_IOS)
480
481 const size_t kPingPongHandlesPerIteration = 50;
482 const size_t kPingPongIterations = 500;
483
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(HandlePingPong,MessagePipeTest,h)484 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(HandlePingPong, MessagePipeTest, h) {
485 // Waits for a handle to become readable and writes it back to the sender.
486 for (size_t i = 0; i < kPingPongIterations; i++) {
487 MojoHandle handles[kPingPongHandlesPerIteration];
488 ReadMessageWithHandles(h, handles, kPingPongHandlesPerIteration);
489 WriteMessageWithHandles(h, "", handles, kPingPongHandlesPerIteration);
490 }
491
492 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE,
493 MOJO_DEADLINE_INDEFINITE, nullptr));
494 char msg[4];
495 uint32_t num_bytes = 4;
496 EXPECT_EQ(MOJO_RESULT_OK, ReadMessage(h, msg, &num_bytes));
497 }
498
499 // This test is flaky: http://crbug.com/585784
TEST_F(MessagePipeTest,DISABLED_DataPipeConsumerHandlePingPong)500 TEST_F(MessagePipeTest, DISABLED_DataPipeConsumerHandlePingPong) {
501 MojoHandle p, c[kPingPongHandlesPerIteration];
502 for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i) {
503 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p, &c[i]));
504 MojoClose(p);
505 }
506
507 RUN_CHILD_ON_PIPE(HandlePingPong, h)
508 for (size_t i = 0; i < kPingPongIterations; i++) {
509 WriteMessageWithHandles(h, "", c, kPingPongHandlesPerIteration);
510 ReadMessageWithHandles(h, c, kPingPongHandlesPerIteration);
511 }
512 WriteMessage(h, "quit", 4);
513 END_CHILD()
514 for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i)
515 MojoClose(c[i]);
516 }
517
518 // This test is flaky: http://crbug.com/585784
TEST_F(MessagePipeTest,DISABLED_DataPipeProducerHandlePingPong)519 TEST_F(MessagePipeTest, DISABLED_DataPipeProducerHandlePingPong) {
520 MojoHandle p[kPingPongHandlesPerIteration], c;
521 for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i) {
522 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p[i], &c));
523 MojoClose(c);
524 }
525
526 RUN_CHILD_ON_PIPE(HandlePingPong, h)
527 for (size_t i = 0; i < kPingPongIterations; i++) {
528 WriteMessageWithHandles(h, "", p, kPingPongHandlesPerIteration);
529 ReadMessageWithHandles(h, p, kPingPongHandlesPerIteration);
530 }
531 WriteMessage(h, "quit", 4);
532 END_CHILD()
533 for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i)
534 MojoClose(p[i]);
535 }
536
TEST_F(MessagePipeTest,SharedBufferHandlePingPong)537 TEST_F(MessagePipeTest, SharedBufferHandlePingPong) {
538 MojoHandle buffers[kPingPongHandlesPerIteration];
539 for (size_t i = 0; i <kPingPongHandlesPerIteration; ++i)
540 EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 1, &buffers[i]));
541
542 RUN_CHILD_ON_PIPE(HandlePingPong, h)
543 for (size_t i = 0; i < kPingPongIterations; i++) {
544 WriteMessageWithHandles(h, "", buffers, kPingPongHandlesPerIteration);
545 ReadMessageWithHandles(h, buffers, kPingPongHandlesPerIteration);
546 }
547 WriteMessage(h, "quit", 4);
548 END_CHILD()
549 for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i)
550 MojoClose(buffers[i]);
551 }
552
553 #endif // !defined(OS_IOS)
554
TEST_F(FuseMessagePipeTest,Basic)555 TEST_F(FuseMessagePipeTest, Basic) {
556 // Test that we can fuse pipes and they still work.
557
558 MojoHandle a, b, c, d;
559 CreateMessagePipe(&a, &b);
560 CreateMessagePipe(&c, &d);
561
562 EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c));
563
564 // Handles b and c should be closed.
565 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
566 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
567
568 const std::string kTestMessage1 = "Hello, world!";
569 const std::string kTestMessage2 = "Goodbye, world!";
570
571 WriteMessage(a, kTestMessage1);
572 EXPECT_EQ(kTestMessage1, ReadMessage(d));
573
574 WriteMessage(d, kTestMessage2);
575 EXPECT_EQ(kTestMessage2, ReadMessage(a));
576
577 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
578 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
579 }
580
TEST_F(FuseMessagePipeTest,FuseAfterPeerWrite)581 TEST_F(FuseMessagePipeTest, FuseAfterPeerWrite) {
582 // Test that messages written before fusion are eventually delivered.
583
584 MojoHandle a, b, c, d;
585 CreateMessagePipe(&a, &b);
586 CreateMessagePipe(&c, &d);
587
588 const std::string kTestMessage1 = "Hello, world!";
589 const std::string kTestMessage2 = "Goodbye, world!";
590 WriteMessage(a, kTestMessage1);
591 WriteMessage(d, kTestMessage2);
592
593 EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c));
594
595 // Handles b and c should be closed.
596 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
597 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
598
599 EXPECT_EQ(kTestMessage1, ReadMessage(d));
600 EXPECT_EQ(kTestMessage2, ReadMessage(a));
601
602 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
603 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
604 }
605
TEST_F(FuseMessagePipeTest,NoFuseAfterWrite)606 TEST_F(FuseMessagePipeTest, NoFuseAfterWrite) {
607 // Test that a pipe endpoint which has been written to cannot be fused.
608
609 MojoHandle a, b, c, d;
610 CreateMessagePipe(&a, &b);
611 CreateMessagePipe(&c, &d);
612
613 WriteMessage(b, "shouldn't have done that!");
614 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, MojoFuseMessagePipes(b, c));
615
616 // Handles b and c should be closed.
617 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
618 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
619
620 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
621 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
622 }
623
TEST_F(FuseMessagePipeTest,NoFuseSelf)624 TEST_F(FuseMessagePipeTest, NoFuseSelf) {
625 // Test that a pipe's own endpoints can't be fused together.
626
627 MojoHandle a, b;
628 CreateMessagePipe(&a, &b);
629
630 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, MojoFuseMessagePipes(a, b));
631
632 // Handles a and b should be closed.
633 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(a));
634 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
635 }
636
TEST_F(FuseMessagePipeTest,FuseInvalidArguments)637 TEST_F(FuseMessagePipeTest, FuseInvalidArguments) {
638 MojoHandle a, b, c, d;
639 CreateMessagePipe(&a, &b);
640 CreateMessagePipe(&c, &d);
641
642 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
643
644 // Can't fuse an invalid handle.
645 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFuseMessagePipes(b, c));
646
647 // Handle c should be closed.
648 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
649
650 // Can't fuse a non-message pipe handle.
651 MojoHandle e, f;
652 CreateDataPipe(&e, &f, 16);
653
654 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFuseMessagePipes(e, d));
655
656 // Handles d and e should be closed.
657 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(d));
658 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(e));
659
660 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
661 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(f));
662 }
663
TEST_F(FuseMessagePipeTest,FuseAfterPeerClosure)664 TEST_F(FuseMessagePipeTest, FuseAfterPeerClosure) {
665 // Test that peer closure prior to fusion can still be detected after fusion.
666
667 MojoHandle a, b, c, d;
668 CreateMessagePipe(&a, &b);
669 CreateMessagePipe(&c, &d);
670
671 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
672 EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c));
673
674 // Handles b and c should be closed.
675 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
676 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
677
678 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(d, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
679 MOJO_DEADLINE_INDEFINITE, nullptr));
680
681 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
682 }
683
TEST_F(FuseMessagePipeTest,FuseAfterPeerWriteAndClosure)684 TEST_F(FuseMessagePipeTest, FuseAfterPeerWriteAndClosure) {
685 // Test that peer write and closure prior to fusion still results in the
686 // both message arrival and awareness of peer closure.
687
688 MojoHandle a, b, c, d;
689 CreateMessagePipe(&a, &b);
690 CreateMessagePipe(&c, &d);
691
692 const std::string kTestMessage = "ayyy lmao";
693 WriteMessage(a, kTestMessage);
694 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
695
696 EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c));
697
698 // Handles b and c should be closed.
699 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
700 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
701
702 EXPECT_EQ(kTestMessage, ReadMessage(d));
703 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(d, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
704 MOJO_DEADLINE_INDEFINITE, nullptr));
705
706 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
707 }
708
TEST_F(MessagePipeTest,ClosePipesStressTest)709 TEST_F(MessagePipeTest, ClosePipesStressTest) {
710 // Stress test to exercise https://crbug.com/665869.
711 const size_t kNumPipes = 100000;
712 for (size_t i = 0; i < kNumPipes; ++i) {
713 MojoHandle a, b;
714 CreateMessagePipe(&a, &b);
715 MojoClose(a);
716 MojoClose(b);
717 }
718 }
719
720 } // namespace
721 } // namespace edk
722 } // namespace mojo
723