• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <algorithm>
9 #include <memory>
10 #include <string>
11 #include <vector>
12 
13 #include "base/memory/ptr_util.h"
14 #include "base/memory/ref_counted.h"
15 #include "build/build_config.h"
16 #include "mojo/core/test/mojo_test_base.h"
17 #include "mojo/core/test_utils.h"
18 #include "mojo/public/c/system/core.h"
19 #include "mojo/public/c/system/types.h"
20 #include "mojo/public/cpp/system/message_pipe.h"
21 
22 namespace mojo {
23 namespace core {
24 namespace {
25 
26 const MojoHandleSignals kAllSignals =
27     MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE |
28     MOJO_HANDLE_SIGNAL_PEER_CLOSED | MOJO_HANDLE_SIGNAL_PEER_REMOTE |
29     MOJO_HANDLE_SIGNAL_QUOTA_EXCEEDED;
30 
31 static const char kHelloWorld[] = "hello world";
32 
33 class MessagePipeTest : public test::MojoTestBase {
34  public:
MessagePipeTest()35   MessagePipeTest() {
36     CHECK_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &pipe0_, &pipe1_));
37   }
38 
~MessagePipeTest()39   ~MessagePipeTest() override {
40     if (pipe0_ != MOJO_HANDLE_INVALID)
41       CHECK_EQ(MOJO_RESULT_OK, MojoClose(pipe0_));
42     if (pipe1_ != MOJO_HANDLE_INVALID)
43       CHECK_EQ(MOJO_RESULT_OK, MojoClose(pipe1_));
44   }
45 
WriteMessage(MojoHandle message_pipe_handle,const void * bytes,uint32_t num_bytes)46   MojoResult WriteMessage(MojoHandle message_pipe_handle,
47                           const void* bytes,
48                           uint32_t num_bytes) {
49     return mojo::WriteMessageRaw(MessagePipeHandle(message_pipe_handle), bytes,
50                                  num_bytes, nullptr, 0,
51                                  MOJO_WRITE_MESSAGE_FLAG_NONE);
52   }
53 
ReadMessage(MojoHandle message_pipe_handle,void * bytes,uint32_t * num_bytes,bool may_discard=false)54   MojoResult ReadMessage(MojoHandle message_pipe_handle,
55                          void* bytes,
56                          uint32_t* num_bytes,
57                          bool may_discard = false) {
58     MojoMessageHandle message_handle;
59     MojoResult rv =
60         MojoReadMessage(message_pipe_handle, nullptr, &message_handle);
61     if (rv != MOJO_RESULT_OK)
62       return rv;
63 
64     const uint32_t expected_num_bytes = *num_bytes;
65     void* buffer;
66     rv = MojoGetMessageData(message_handle, nullptr, &buffer, num_bytes,
67                             nullptr, nullptr);
68 
69     if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) {
70       CHECK(may_discard);
71     } else if (*num_bytes) {
72       CHECK_EQ(MOJO_RESULT_OK, rv);
73       CHECK_GE(expected_num_bytes, *num_bytes);
74       CHECK(bytes);
75       memcpy(bytes, buffer, *num_bytes);
76     }
77     CHECK_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
78     return rv;
79   }
80 
81   MojoHandle pipe0_, pipe1_;
82 
83  private:
84   DISALLOW_COPY_AND_ASSIGN(MessagePipeTest);
85 };
86 
87 using FuseMessagePipeTest = test::MojoTestBase;
88 
TEST_F(MessagePipeTest,WriteData)89 TEST_F(MessagePipeTest, WriteData) {
90   ASSERT_EQ(MOJO_RESULT_OK,
91             WriteMessage(pipe0_, kHelloWorld, sizeof(kHelloWorld)));
92 }
93 
94 // Tests:
95 //  - only default flags
96 //  - reading messages from a port
97 //    - when there are no/one/two messages available for that port
98 //    - with buffer size 0 (and null buffer) -- should get size
99 //    - with too-small buffer -- should get size
100 //    - also verify that buffers aren't modified when/where they shouldn't be
101 //  - writing messages to a port
102 //    - in the obvious scenarios (as above)
103 //    - to a port that's been closed
104 //  - writing a message to a port, closing the other (would be the source) port,
105 //    and reading it
TEST_F(MessagePipeTest,Basic)106 TEST_F(MessagePipeTest, Basic) {
107   int32_t buffer[2];
108   const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
109   uint32_t buffer_size;
110 
111   // Nothing to read yet on port 0.
112   buffer[0] = 123;
113   buffer[1] = 456;
114   buffer_size = kBufferSize;
115   ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe0_, buffer, &buffer_size));
116   ASSERT_EQ(kBufferSize, buffer_size);
117   ASSERT_EQ(123, buffer[0]);
118   ASSERT_EQ(456, buffer[1]);
119 
120   // Ditto for port 1.
121   buffer[0] = 123;
122   buffer[1] = 456;
123   buffer_size = kBufferSize;
124   ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe1_, buffer, &buffer_size));
125 
126   // Write from port 1 (to port 0).
127   buffer[0] = 789012345;
128   buffer[1] = 0;
129   ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, sizeof(buffer[0])));
130 
131   MojoHandleSignalsState state;
132   ASSERT_EQ(MOJO_RESULT_OK,
133             WaitForSignals(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, &state));
134 
135   // Read from port 0.
136   buffer[0] = 123;
137   buffer[1] = 456;
138   buffer_size = kBufferSize;
139   ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe0_, buffer, &buffer_size));
140   ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
141   ASSERT_EQ(789012345, buffer[0]);
142   ASSERT_EQ(456, buffer[1]);
143 
144   // Read again from port 0 -- it should be empty.
145   buffer_size = kBufferSize;
146   ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe0_, buffer, &buffer_size));
147 
148   // Write two messages from port 0 (to port 1).
149   buffer[0] = 123456789;
150   buffer[1] = 0;
151   ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0])));
152   buffer[0] = 234567890;
153   buffer[1] = 0;
154   ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0])));
155 
156   ASSERT_EQ(MOJO_RESULT_OK,
157             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &state));
158 
159   // Read from port 1.
160   buffer[0] = 123;
161   buffer[1] = 456;
162   buffer_size = kBufferSize;
163   ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size));
164   ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
165   ASSERT_EQ(123456789, buffer[0]);
166   ASSERT_EQ(456, buffer[1]);
167 
168   ASSERT_EQ(MOJO_RESULT_OK,
169             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &state));
170 
171   // Read again from port 1.
172   buffer[0] = 123;
173   buffer[1] = 456;
174   buffer_size = kBufferSize;
175   ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size));
176   ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
177   ASSERT_EQ(234567890, buffer[0]);
178   ASSERT_EQ(456, buffer[1]);
179 
180   // Read again from port 1 -- it should be empty.
181   buffer_size = kBufferSize;
182   ASSERT_EQ(MOJO_RESULT_SHOULD_WAIT, ReadMessage(pipe1_, buffer, &buffer_size));
183 
184   // Write from port 0 (to port 1).
185   buffer[0] = 345678901;
186   buffer[1] = 0;
187   ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, sizeof(buffer[0])));
188 
189   // Close port 0.
190   MojoClose(pipe0_);
191   pipe0_ = MOJO_HANDLE_INVALID;
192 
193   ASSERT_EQ(MOJO_RESULT_OK,
194             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &state));
195 
196   // Try to write from port 1 (to port 0).
197   buffer[0] = 456789012;
198   buffer[1] = 0;
199   ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
200             WriteMessage(pipe1_, buffer, sizeof(buffer[0])));
201 
202   // Read from port 1; should still get message (even though port 0 was closed).
203   buffer[0] = 123;
204   buffer[1] = 456;
205   buffer_size = kBufferSize;
206   ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size));
207   ASSERT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size);
208   ASSERT_EQ(345678901, buffer[0]);
209   ASSERT_EQ(456, buffer[1]);
210 
211   // Read again from port 1 -- it should be empty (and port 0 is closed).
212   buffer_size = kBufferSize;
213   ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
214             ReadMessage(pipe1_, buffer, &buffer_size));
215 }
216 
TEST_F(MessagePipeTest,CloseWithQueuedIncomingMessages)217 TEST_F(MessagePipeTest, CloseWithQueuedIncomingMessages) {
218   int32_t buffer[1];
219   const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
220   uint32_t buffer_size;
221 
222   // Write some messages from port 1 (to port 0).
223   for (int32_t i = 0; i < 5; i++) {
224     buffer[0] = i;
225     ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe1_, buffer, kBufferSize));
226   }
227 
228   MojoHandleSignalsState state;
229   ASSERT_EQ(MOJO_RESULT_OK,
230             WaitForSignals(pipe0_, MOJO_HANDLE_SIGNAL_READABLE, &state));
231 
232   // Port 0 shouldn't be empty.
233   buffer_size = kBufferSize;
234   ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe0_, buffer, &buffer_size));
235   ASSERT_EQ(kBufferSize, buffer_size);
236 
237   // Close port 0 first, which should have outstanding (incoming) messages.
238   MojoClose(pipe0_);
239   MojoClose(pipe1_);
240   pipe0_ = pipe1_ = MOJO_HANDLE_INVALID;
241 }
242 
TEST_F(MessagePipeTest,BasicWaiting)243 TEST_F(MessagePipeTest, BasicWaiting) {
244   MojoHandleSignalsState hss;
245 
246   int32_t buffer[1];
247   const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
248   uint32_t buffer_size;
249 
250   // Always writable (until the other port is closed). Not yet readable. Peer
251   // not closed.
252   hss = GetSignalsState(pipe0_);
253   ASSERT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
254   ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
255   hss = MojoHandleSignalsState();
256 
257   // Write from port 0 (to port 1), to make port 1 readable.
258   buffer[0] = 123456789;
259   ASSERT_EQ(MOJO_RESULT_OK, WriteMessage(pipe0_, buffer, kBufferSize));
260 
261   // Port 1 should already be readable now.
262   ASSERT_EQ(MOJO_RESULT_OK,
263             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &hss));
264   ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
265             hss.satisfied_signals);
266   ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
267   // ... and still writable.
268   hss = MojoHandleSignalsState();
269   ASSERT_EQ(MOJO_RESULT_OK,
270             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_WRITABLE, &hss));
271   ASSERT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
272             hss.satisfied_signals);
273   ASSERT_EQ(kAllSignals, hss.satisfiable_signals);
274 
275   // Close port 0.
276   MojoClose(pipe0_);
277   pipe0_ = MOJO_HANDLE_INVALID;
278 
279   // Port 1 should be signaled with peer closed.
280   hss = MojoHandleSignalsState();
281   ASSERT_EQ(MOJO_RESULT_OK,
282             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_PEER_CLOSED, &hss));
283   ASSERT_TRUE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_CLOSED);
284   ASSERT_TRUE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_PEER_CLOSED);
285 
286   // Port 1 should not be writable now or ever again.
287   hss = MojoHandleSignalsState();
288 
289   ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
290             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_WRITABLE, &hss));
291   ASSERT_FALSE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
292   ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
293 
294   // But it should still be readable.
295   hss = MojoHandleSignalsState();
296   ASSERT_EQ(MOJO_RESULT_OK,
297             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &hss));
298   ASSERT_TRUE(hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
299   ASSERT_TRUE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
300 
301   // Read from port 1.
302   buffer[0] = 0;
303   buffer_size = kBufferSize;
304   ASSERT_EQ(MOJO_RESULT_OK, ReadMessage(pipe1_, buffer, &buffer_size));
305   ASSERT_EQ(123456789, buffer[0]);
306 
307   // Now port 1 should no longer be readable.
308   hss = MojoHandleSignalsState();
309   ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
310             WaitForSignals(pipe1_, MOJO_HANDLE_SIGNAL_READABLE, &hss));
311   ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
312   ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE);
313   ASSERT_FALSE(hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_WRITABLE);
314 }
315 
316 #if !defined(OS_IOS)
317 
318 const size_t kPingPongHandlesPerIteration = 30;
319 const size_t kPingPongIterations = 500;
320 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(HandlePingPong,MessagePipeTest,h)321 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(HandlePingPong, MessagePipeTest, h) {
322   // Waits for a handle to become readable and writes it back to the sender.
323   for (size_t i = 0; i < kPingPongIterations; i++) {
324     MojoHandle handles[kPingPongHandlesPerIteration];
325     ReadMessageWithHandles(h, handles, kPingPongHandlesPerIteration);
326     WriteMessageWithHandles(h, "", handles, kPingPongHandlesPerIteration);
327   }
328 
329   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE));
330   char msg[4];
331   uint32_t num_bytes = 4;
332   EXPECT_EQ(MOJO_RESULT_OK, ReadMessage(h, msg, &num_bytes));
333 }
334 
335 // This test is flaky: http://crbug.com/585784
TEST_F(MessagePipeTest,DISABLED_DataPipeConsumerHandlePingPong)336 TEST_F(MessagePipeTest, DISABLED_DataPipeConsumerHandlePingPong) {
337   MojoHandle p, c[kPingPongHandlesPerIteration];
338   for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i) {
339     EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p, &c[i]));
340     MojoClose(p);
341   }
342 
343   RunTestClient("HandlePingPong", [&](MojoHandle h) {
344     for (size_t i = 0; i < kPingPongIterations; i++) {
345       WriteMessageWithHandles(h, "", c, kPingPongHandlesPerIteration);
346       ReadMessageWithHandles(h, c, kPingPongHandlesPerIteration);
347     }
348     WriteMessage(h, "quit", 4);
349   });
350   for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i)
351     MojoClose(c[i]);
352 }
353 
354 // This test is flaky: http://crbug.com/585784
TEST_F(MessagePipeTest,DISABLED_DataPipeProducerHandlePingPong)355 TEST_F(MessagePipeTest, DISABLED_DataPipeProducerHandlePingPong) {
356   MojoHandle p[kPingPongHandlesPerIteration], c;
357   for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i) {
358     EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &p[i], &c));
359     MojoClose(c);
360   }
361 
362   RunTestClient("HandlePingPong", [&](MojoHandle h) {
363     for (size_t i = 0; i < kPingPongIterations; i++) {
364       WriteMessageWithHandles(h, "", p, kPingPongHandlesPerIteration);
365       ReadMessageWithHandles(h, p, kPingPongHandlesPerIteration);
366     }
367     WriteMessage(h, "quit", 4);
368   });
369   for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i)
370     MojoClose(p[i]);
371 }
372 
TEST_F(MessagePipeTest,SharedBufferHandlePingPong)373 TEST_F(MessagePipeTest, SharedBufferHandlePingPong) {
374   MojoHandle buffers[kPingPongHandlesPerIteration];
375   for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i)
376     EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(1, nullptr, &buffers[i]));
377 
378   RunTestClient("HandlePingPong", [&](MojoHandle h) {
379     for (size_t i = 0; i < kPingPongIterations; i++) {
380       WriteMessageWithHandles(h, "", buffers, kPingPongHandlesPerIteration);
381       ReadMessageWithHandles(h, buffers, kPingPongHandlesPerIteration);
382     }
383     WriteMessage(h, "quit", 4);
384   });
385   for (size_t i = 0; i < kPingPongHandlesPerIteration; ++i)
386     MojoClose(buffers[i]);
387 }
388 
389 #endif  // !defined(OS_IOS)
390 
TEST_F(FuseMessagePipeTest,Basic)391 TEST_F(FuseMessagePipeTest, Basic) {
392   // Test that we can fuse pipes and they still work.
393 
394   MojoHandle a, b, c, d;
395   CreateMessagePipe(&a, &b);
396   CreateMessagePipe(&c, &d);
397 
398   EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c, nullptr));
399 
400   // Handles b and c should be closed.
401   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
402   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
403 
404   const std::string kTestMessage1 = "Hello, world!";
405   const std::string kTestMessage2 = "Goodbye, world!";
406 
407   WriteMessage(a, kTestMessage1);
408   EXPECT_EQ(kTestMessage1, ReadMessage(d));
409 
410   WriteMessage(d, kTestMessage2);
411   EXPECT_EQ(kTestMessage2, ReadMessage(a));
412 
413   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
414   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
415 }
416 
TEST_F(FuseMessagePipeTest,FuseAfterPeerWrite)417 TEST_F(FuseMessagePipeTest, FuseAfterPeerWrite) {
418   // Test that messages written before fusion are eventually delivered.
419 
420   MojoHandle a, b, c, d;
421   CreateMessagePipe(&a, &b);
422   CreateMessagePipe(&c, &d);
423 
424   const std::string kTestMessage1 = "Hello, world!";
425   const std::string kTestMessage2 = "Goodbye, world!";
426   WriteMessage(a, kTestMessage1);
427   WriteMessage(d, kTestMessage2);
428 
429   EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c, nullptr));
430 
431   // Handles b and c should be closed.
432   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
433   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
434 
435   EXPECT_EQ(kTestMessage1, ReadMessage(d));
436   EXPECT_EQ(kTestMessage2, ReadMessage(a));
437 
438   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
439   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
440 }
441 
TEST_F(FuseMessagePipeTest,NoFuseAfterWrite)442 TEST_F(FuseMessagePipeTest, NoFuseAfterWrite) {
443   // Test that a pipe endpoint which has been written to cannot be fused.
444 
445   MojoHandle a, b, c, d;
446   CreateMessagePipe(&a, &b);
447   CreateMessagePipe(&c, &d);
448 
449   WriteMessage(b, "shouldn't have done that!");
450   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
451             MojoFuseMessagePipes(b, c, nullptr));
452 
453   // Handles b and c should be closed.
454   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
455   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
456 
457   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
458   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
459 }
460 
TEST_F(FuseMessagePipeTest,NoFuseSelf)461 TEST_F(FuseMessagePipeTest, NoFuseSelf) {
462   // Test that a pipe's own endpoints can't be fused together.
463 
464   MojoHandle a, b;
465   CreateMessagePipe(&a, &b);
466 
467   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
468             MojoFuseMessagePipes(a, b, nullptr));
469 
470   // Handles a and b should be closed.
471   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(a));
472   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
473 }
474 
TEST_F(FuseMessagePipeTest,FuseInvalidArguments)475 TEST_F(FuseMessagePipeTest, FuseInvalidArguments) {
476   MojoHandle a, b, c, d;
477   CreateMessagePipe(&a, &b);
478   CreateMessagePipe(&c, &d);
479 
480   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
481 
482   // Can't fuse an invalid handle.
483   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFuseMessagePipes(b, c, nullptr));
484 
485   // Handle c should be closed.
486   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
487 
488   // Can't fuse a non-message pipe handle.
489   MojoHandle e, f;
490   CreateDataPipe(&e, &f, 16);
491 
492   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoFuseMessagePipes(e, d, nullptr));
493 
494   // Handles d and e should be closed.
495   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(d));
496   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(e));
497 
498   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
499   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(f));
500 }
501 
TEST_F(FuseMessagePipeTest,FuseAfterPeerClosure)502 TEST_F(FuseMessagePipeTest, FuseAfterPeerClosure) {
503   // Test that peer closure prior to fusion can still be detected after fusion.
504 
505   MojoHandle a, b, c, d;
506   CreateMessagePipe(&a, &b);
507   CreateMessagePipe(&c, &d);
508 
509   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
510   EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c, nullptr));
511 
512   // Handles b and c should be closed.
513   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
514   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
515 
516   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(d, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
517   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
518 }
519 
TEST_F(FuseMessagePipeTest,FuseAfterPeerWriteAndClosure)520 TEST_F(FuseMessagePipeTest, FuseAfterPeerWriteAndClosure) {
521   // Test that peer write and closure prior to fusion still results in the
522   // both message arrival and awareness of peer closure.
523 
524   MojoHandle a, b, c, d;
525   CreateMessagePipe(&a, &b);
526   CreateMessagePipe(&c, &d);
527 
528   const std::string kTestMessage = "ayyy lmao";
529   WriteMessage(a, kTestMessage);
530   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
531 
532   EXPECT_EQ(MOJO_RESULT_OK, MojoFuseMessagePipes(b, c, nullptr));
533 
534   // Handles b and c should be closed.
535   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(b));
536   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(c));
537 
538   EXPECT_EQ(kTestMessage, ReadMessage(d));
539   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(d, MOJO_HANDLE_SIGNAL_PEER_CLOSED));
540   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(d));
541 }
542 
TEST_F(MessagePipeTest,ClosePipesStressTest)543 TEST_F(MessagePipeTest, ClosePipesStressTest) {
544   // Stress test to exercise https://crbug.com/665869.
545   const size_t kNumPipes = 100000;
546   for (size_t i = 0; i < kNumPipes; ++i) {
547     MojoHandle a, b;
548     CreateMessagePipe(&a, &b);
549     MojoClose(a);
550     MojoClose(b);
551   }
552 }
553 
554 }  // namespace
555 }  // namespace core
556 }  // namespace mojo
557