xref: /aosp_15_r20/external/libchrome/mojo/core/message_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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 <algorithm>
6 #include <memory>
7 #include <utility>
8 #include <vector>
9 
10 #include "base/memory/ptr_util.h"
11 #include "base/numerics/safe_math.h"
12 #include "base/rand_util.h"
13 #include "build/build_config.h"
14 #include "mojo/core/test/mojo_test_base.h"
15 #include "mojo/core/user_message_impl.h"
16 #include "mojo/public/cpp/platform/platform_channel.h"
17 #include "mojo/public/cpp/system/buffer.h"
18 #include "mojo/public/cpp/system/message_pipe.h"
19 #include "mojo/public/cpp/system/platform_handle.h"
20 
21 namespace mojo {
22 namespace core {
23 namespace {
24 
25 using MessageTest = test::MojoTestBase;
26 
27 // Helper class which provides a base implementation for an unserialized user
28 // message context and helpers to go between these objects and opaque message
29 // handles.
30 class TestMessageBase {
31  public:
~TestMessageBase()32   virtual ~TestMessageBase() {}
33 
MakeMessageHandle(std::unique_ptr<TestMessageBase> message)34   static MojoMessageHandle MakeMessageHandle(
35       std::unique_ptr<TestMessageBase> message) {
36     MojoMessageHandle handle;
37     MojoResult rv = MojoCreateMessage(nullptr, &handle);
38     DCHECK_EQ(MOJO_RESULT_OK, rv);
39 
40     rv = MojoSetMessageContext(
41         handle, reinterpret_cast<uintptr_t>(message.release()),
42         &TestMessageBase::SerializeMessageContext,
43         &TestMessageBase::DestroyMessageContext, nullptr);
44     DCHECK_EQ(MOJO_RESULT_OK, rv);
45 
46     return handle;
47   }
48 
49   template <typename T>
UnwrapMessageHandle(MojoMessageHandle * message_handle)50   static std::unique_ptr<T> UnwrapMessageHandle(
51       MojoMessageHandle* message_handle) {
52     MojoMessageHandle handle = MOJO_HANDLE_INVALID;
53     std::swap(handle, *message_handle);
54     uintptr_t context;
55     MojoResult rv = MojoGetMessageContext(handle, nullptr, &context);
56     DCHECK_EQ(MOJO_RESULT_OK, rv);
57     rv = MojoSetMessageContext(handle, 0, nullptr, nullptr, nullptr);
58     DCHECK_EQ(MOJO_RESULT_OK, rv);
59     MojoDestroyMessage(handle);
60     return base::WrapUnique(reinterpret_cast<T*>(context));
61   }
62 
63  protected:
64   virtual void GetSerializedSize(size_t* num_bytes, size_t* num_handles) = 0;
65   virtual void SerializeHandles(MojoHandle* handles) = 0;
66   virtual void SerializePayload(void* buffer) = 0;
67 
68  private:
SerializeMessageContext(MojoMessageHandle message_handle,uintptr_t context)69   static void SerializeMessageContext(MojoMessageHandle message_handle,
70                                       uintptr_t context) {
71     auto* message = reinterpret_cast<TestMessageBase*>(context);
72     size_t num_bytes = 0;
73     size_t num_handles = 0;
74     message->GetSerializedSize(&num_bytes, &num_handles);
75     std::vector<MojoHandle> handles(num_handles);
76     if (num_handles)
77       message->SerializeHandles(handles.data());
78 
79     MojoAppendMessageDataOptions options;
80     options.struct_size = sizeof(options);
81     options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
82     void* buffer;
83     uint32_t buffer_size;
84     MojoResult rv = MojoAppendMessageData(
85         message_handle, base::checked_cast<uint32_t>(num_bytes), handles.data(),
86         base::checked_cast<uint32_t>(num_handles), &options, &buffer,
87         &buffer_size);
88     DCHECK_EQ(MOJO_RESULT_OK, rv);
89     DCHECK_GE(buffer_size, base::checked_cast<uint32_t>(num_bytes));
90     if (num_bytes)
91       message->SerializePayload(buffer);
92   }
93 
DestroyMessageContext(uintptr_t context)94   static void DestroyMessageContext(uintptr_t context) {
95     delete reinterpret_cast<TestMessageBase*>(context);
96   }
97 };
98 
99 class NeverSerializedMessage : public TestMessageBase {
100  public:
NeverSerializedMessage(const base::Closure & destruction_callback=base::Closure ())101   NeverSerializedMessage(
102       const base::Closure& destruction_callback = base::Closure())
103       : destruction_callback_(destruction_callback) {}
~NeverSerializedMessage()104   ~NeverSerializedMessage() override {
105     if (destruction_callback_)
106       destruction_callback_.Run();
107   }
108 
109  private:
110   // TestMessageBase:
GetSerializedSize(size_t * num_bytes,size_t * num_handles)111   void GetSerializedSize(size_t* num_bytes, size_t* num_handles) override {
112     NOTREACHED();
113   }
SerializeHandles(MojoHandle * handles)114   void SerializeHandles(MojoHandle* handles) override { NOTREACHED(); }
SerializePayload(void * buffer)115   void SerializePayload(void* buffer) override { NOTREACHED(); }
116 
117   const base::Closure destruction_callback_;
118 
119   DISALLOW_COPY_AND_ASSIGN(NeverSerializedMessage);
120 };
121 
122 class SimpleMessage : public TestMessageBase {
123  public:
SimpleMessage(const std::string & contents,const base::Closure & destruction_callback=base::Closure ())124   SimpleMessage(const std::string& contents,
125                 const base::Closure& destruction_callback = base::Closure())
126       : contents_(contents), destruction_callback_(destruction_callback) {}
127 
~SimpleMessage()128   ~SimpleMessage() override {
129     if (destruction_callback_)
130       destruction_callback_.Run();
131   }
132 
AddMessagePipe(mojo::ScopedMessagePipeHandle handle)133   void AddMessagePipe(mojo::ScopedMessagePipeHandle handle) {
134     handles_.emplace_back(std::move(handle));
135   }
136 
handles()137   std::vector<mojo::ScopedMessagePipeHandle>& handles() { return handles_; }
138 
139  private:
140   // TestMessageBase:
GetSerializedSize(size_t * num_bytes,size_t * num_handles)141   void GetSerializedSize(size_t* num_bytes, size_t* num_handles) override {
142     *num_bytes = contents_.size();
143     *num_handles = handles_.size();
144   }
145 
SerializeHandles(MojoHandle * handles)146   void SerializeHandles(MojoHandle* handles) override {
147     ASSERT_TRUE(!handles_.empty());
148     for (size_t i = 0; i < handles_.size(); ++i)
149       handles[i] = handles_[i].release().value();
150     handles_.clear();
151   }
152 
SerializePayload(void * buffer)153   void SerializePayload(void* buffer) override {
154     std::copy(contents_.begin(), contents_.end(), static_cast<char*>(buffer));
155   }
156 
157   const std::string contents_;
158   const base::Closure destruction_callback_;
159   std::vector<mojo::ScopedMessagePipeHandle> handles_;
160 
161   DISALLOW_COPY_AND_ASSIGN(SimpleMessage);
162 };
163 
TEST_F(MessageTest,InvalidMessageObjects)164 TEST_F(MessageTest, InvalidMessageObjects) {
165   ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
166             MojoDestroyMessage(MOJO_MESSAGE_HANDLE_INVALID));
167 
168   ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
169             MojoAppendMessageData(MOJO_MESSAGE_HANDLE_INVALID, 0, nullptr, 0,
170                                   nullptr, nullptr, nullptr));
171 
172   ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
173             MojoGetMessageData(MOJO_MESSAGE_HANDLE_INVALID, nullptr, nullptr,
174                                nullptr, nullptr, nullptr));
175 
176   ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
177             MojoSerializeMessage(MOJO_MESSAGE_HANDLE_INVALID, nullptr));
178 
179   MojoMessageHandle message_handle;
180   ASSERT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoCreateMessage(nullptr, nullptr));
181   ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message_handle));
182   ASSERT_EQ(MOJO_RESULT_OK, MojoSetMessageContext(message_handle, 0, nullptr,
183                                                   nullptr, nullptr));
184   ASSERT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
185 }
186 
TEST_F(MessageTest,SendLocalMessageWithContext)187 TEST_F(MessageTest, SendLocalMessageWithContext) {
188   // Simple write+read of a message with context. Verifies that such messages
189   // are passed through a local pipe without serialization.
190   auto message = std::make_unique<NeverSerializedMessage>();
191   auto* original_message = message.get();
192 
193   MojoHandle a, b;
194   CreateMessagePipe(&a, &b);
195   EXPECT_EQ(
196       MOJO_RESULT_OK,
197       MojoWriteMessage(
198           a, TestMessageBase::MakeMessageHandle(std::move(message)), nullptr));
199   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE));
200 
201   MojoMessageHandle read_message_handle;
202   EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &read_message_handle));
203   message = TestMessageBase::UnwrapMessageHandle<NeverSerializedMessage>(
204       &read_message_handle);
205   EXPECT_EQ(original_message, message.get());
206 
207   MojoClose(a);
208   MojoClose(b);
209 }
210 
TEST_F(MessageTest,DestroyMessageWithContext)211 TEST_F(MessageTest, DestroyMessageWithContext) {
212   // Tests that |MojoDestroyMessage()| destroys any attached context.
213   bool was_deleted = false;
214   auto message = std::make_unique<NeverSerializedMessage>(
215       base::Bind([](bool* was_deleted) { *was_deleted = true; }, &was_deleted));
216   MojoMessageHandle handle =
217       TestMessageBase::MakeMessageHandle(std::move(message));
218   EXPECT_FALSE(was_deleted);
219   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(handle));
220   EXPECT_TRUE(was_deleted);
221 }
222 
223 const char kTestMessageWithContext1[] = "hello laziness";
224 
225 #if !defined(OS_IOS)
226 
227 const char kTestMessageWithContext2[] = "my old friend";
228 const char kTestMessageWithContext3[] = "something something";
229 const char kTestMessageWithContext4[] = "do moar ipc";
230 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveMessageNoHandles,MessageTest,h)231 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveMessageNoHandles, MessageTest, h) {
232   MojoTestBase::WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE);
233   auto m = MojoTestBase::ReadMessage(h);
234   EXPECT_EQ(kTestMessageWithContext1, m);
235 }
236 
TEST_F(MessageTest,SerializeSimpleMessageNoHandlesWithContext)237 TEST_F(MessageTest, SerializeSimpleMessageNoHandlesWithContext) {
238   RunTestClient("ReceiveMessageNoHandles", [&](MojoHandle h) {
239     auto message = std::make_unique<SimpleMessage>(kTestMessageWithContext1);
240     MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)),
241                      nullptr);
242   });
243 }
244 
TEST_F(MessageTest,SerializeDynamicallySizedMessage)245 TEST_F(MessageTest, SerializeDynamicallySizedMessage) {
246   RunTestClient("ReceiveMessageNoHandles", [&](MojoHandle h) {
247     MojoMessageHandle message;
248     EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
249 
250     void* buffer;
251     uint32_t buffer_size;
252     EXPECT_EQ(MOJO_RESULT_OK,
253               MojoAppendMessageData(message, 0, nullptr, 0, nullptr, &buffer,
254                                     &buffer_size));
255 
256     MojoAppendMessageDataOptions options;
257     options.struct_size = sizeof(options);
258     options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
259     EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(
260                                   message, sizeof(kTestMessageWithContext1) - 1,
261                                   nullptr, 0, &options, &buffer, &buffer_size));
262 
263     memcpy(buffer, kTestMessageWithContext1,
264            sizeof(kTestMessageWithContext1) - 1);
265     MojoWriteMessage(h, message, nullptr);
266   });
267 }
268 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveMessageOneHandle,MessageTest,h)269 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveMessageOneHandle, MessageTest, h) {
270   MojoTestBase::WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE);
271   MojoHandle h1;
272   auto m = MojoTestBase::ReadMessageWithHandles(h, &h1, 1);
273   EXPECT_EQ(kTestMessageWithContext1, m);
274   MojoTestBase::WriteMessage(h1, kTestMessageWithContext2);
275 }
276 
TEST_F(MessageTest,SerializeSimpleMessageOneHandleWithContext)277 TEST_F(MessageTest, SerializeSimpleMessageOneHandleWithContext) {
278   RunTestClient("ReceiveMessageOneHandle", [&](MojoHandle h) {
279     auto message = std::make_unique<SimpleMessage>(kTestMessageWithContext1);
280     mojo::MessagePipe pipe;
281     message->AddMessagePipe(std::move(pipe.handle0));
282     MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)),
283                      nullptr);
284     EXPECT_EQ(kTestMessageWithContext2,
285               MojoTestBase::ReadMessage(pipe.handle1.get().value()));
286   });
287 }
288 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveMessageWithHandles,MessageTest,h)289 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveMessageWithHandles, MessageTest, h) {
290   MojoTestBase::WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE);
291   MojoHandle handles[4];
292   auto m = MojoTestBase::ReadMessageWithHandles(h, handles, 4);
293   EXPECT_EQ(kTestMessageWithContext1, m);
294   MojoTestBase::WriteMessage(handles[0], kTestMessageWithContext1);
295   MojoTestBase::WriteMessage(handles[1], kTestMessageWithContext2);
296   MojoTestBase::WriteMessage(handles[2], kTestMessageWithContext3);
297   MojoTestBase::WriteMessage(handles[3], kTestMessageWithContext4);
298 }
299 
TEST_F(MessageTest,SerializeSimpleMessageWithHandlesWithContext)300 TEST_F(MessageTest, SerializeSimpleMessageWithHandlesWithContext) {
301   RunTestClient("ReceiveMessageWithHandles", [&](MojoHandle h) {
302     auto message = std::make_unique<SimpleMessage>(kTestMessageWithContext1);
303     mojo::MessagePipe pipes[4];
304     message->AddMessagePipe(std::move(pipes[0].handle0));
305     message->AddMessagePipe(std::move(pipes[1].handle0));
306     message->AddMessagePipe(std::move(pipes[2].handle0));
307     message->AddMessagePipe(std::move(pipes[3].handle0));
308     MojoWriteMessage(h, TestMessageBase::MakeMessageHandle(std::move(message)),
309                      nullptr);
310     EXPECT_EQ(kTestMessageWithContext1,
311               MojoTestBase::ReadMessage(pipes[0].handle1.get().value()));
312     EXPECT_EQ(kTestMessageWithContext2,
313               MojoTestBase::ReadMessage(pipes[1].handle1.get().value()));
314     EXPECT_EQ(kTestMessageWithContext3,
315               MojoTestBase::ReadMessage(pipes[2].handle1.get().value()));
316     EXPECT_EQ(kTestMessageWithContext4,
317               MojoTestBase::ReadMessage(pipes[3].handle1.get().value()));
318   });
319 }
320 
321 #endif  // !defined(OS_IOS)
322 
TEST_F(MessageTest,SendLocalSimpleMessageWithHandlesWithContext)323 TEST_F(MessageTest, SendLocalSimpleMessageWithHandlesWithContext) {
324   auto message = std::make_unique<SimpleMessage>(kTestMessageWithContext1);
325   auto* original_message = message.get();
326   mojo::MessagePipe pipes[4];
327   MojoHandle original_handles[4] = {
328       pipes[0].handle0.get().value(), pipes[1].handle0.get().value(),
329       pipes[2].handle0.get().value(), pipes[3].handle0.get().value(),
330   };
331   message->AddMessagePipe(std::move(pipes[0].handle0));
332   message->AddMessagePipe(std::move(pipes[1].handle0));
333   message->AddMessagePipe(std::move(pipes[2].handle0));
334   message->AddMessagePipe(std::move(pipes[3].handle0));
335 
336   MojoHandle a, b;
337   CreateMessagePipe(&a, &b);
338   EXPECT_EQ(
339       MOJO_RESULT_OK,
340       MojoWriteMessage(
341           a, TestMessageBase::MakeMessageHandle(std::move(message)), nullptr));
342   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE));
343 
344   MojoMessageHandle read_message_handle;
345   EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &read_message_handle));
346   message =
347       TestMessageBase::UnwrapMessageHandle<SimpleMessage>(&read_message_handle);
348   EXPECT_EQ(original_message, message.get());
349   ASSERT_EQ(4u, message->handles().size());
350   EXPECT_EQ(original_handles[0], message->handles()[0].get().value());
351   EXPECT_EQ(original_handles[1], message->handles()[1].get().value());
352   EXPECT_EQ(original_handles[2], message->handles()[2].get().value());
353   EXPECT_EQ(original_handles[3], message->handles()[3].get().value());
354 
355   MojoClose(a);
356   MojoClose(b);
357 }
358 
TEST_F(MessageTest,DropUnreadLocalMessageWithContext)359 TEST_F(MessageTest, DropUnreadLocalMessageWithContext) {
360   // Verifies that if a message is sent with context over a pipe and the
361   // receiver closes without reading the message, the context is properly
362   // cleaned up.
363   bool message_was_destroyed = false;
364   auto message = std::make_unique<SimpleMessage>(
365       kTestMessageWithContext1,
366       base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
367                  &message_was_destroyed));
368 
369   mojo::MessagePipe pipe;
370   message->AddMessagePipe(std::move(pipe.handle0));
371   MojoHandle a, b;
372   CreateMessagePipe(&a, &b);
373   EXPECT_EQ(
374       MOJO_RESULT_OK,
375       MojoWriteMessage(
376           a, TestMessageBase::MakeMessageHandle(std::move(message)), nullptr));
377   MojoClose(a);
378   MojoClose(b);
379 
380   EXPECT_TRUE(message_was_destroyed);
381   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(pipe.handle1.get().value(),
382                                            MOJO_HANDLE_SIGNAL_PEER_CLOSED));
383 }
384 
TEST_F(MessageTest,GetMessageDataWithHandles)385 TEST_F(MessageTest, GetMessageDataWithHandles) {
386   MojoHandle h[2];
387   CreateMessagePipe(&h[0], &h[1]);
388 
389   MojoMessageHandle message_handle;
390   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message_handle));
391 
392   MojoAppendMessageDataOptions append_data_options;
393   append_data_options.struct_size = sizeof(append_data_options);
394   append_data_options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
395   const std::string kTestMessage = "hello";
396   void* buffer;
397   uint32_t buffer_size;
398   ASSERT_EQ(MOJO_RESULT_OK,
399             MojoAppendMessageData(
400                 message_handle, static_cast<uint32_t>(kTestMessage.size()), h,
401                 2, &append_data_options, &buffer, &buffer_size));
402   memcpy(buffer, kTestMessage.data(), kTestMessage.size());
403 
404   // Ignore handles the first time around. This should mean a subsequent call is
405   // allowed to grab the handles.
406   MojoGetMessageDataOptions get_data_options;
407   get_data_options.struct_size = sizeof(get_data_options);
408   get_data_options.flags = MOJO_GET_MESSAGE_DATA_FLAG_IGNORE_HANDLES;
409   EXPECT_EQ(MOJO_RESULT_OK,
410             MojoGetMessageData(message_handle, &get_data_options, &buffer,
411                                &buffer_size, nullptr, nullptr));
412 
413   // Now grab the handles.
414   uint32_t num_handles = 2;
415   EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageData(message_handle, nullptr, &buffer,
416                                                &buffer_size, h, &num_handles));
417   EXPECT_EQ(2u, num_handles);
418 
419   // Should still be callable as long as we ignore handles.
420   EXPECT_EQ(MOJO_RESULT_OK,
421             MojoGetMessageData(message_handle, &get_data_options, &buffer,
422                                &buffer_size, nullptr, nullptr));
423 
424   // But not if we don't.
425   EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
426             MojoGetMessageData(message_handle, nullptr, &buffer, &buffer_size,
427                                h, &num_handles));
428 
429   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
430 }
431 
TEST_F(MessageTest,ReadMessageWithContextAsSerializedMessage)432 TEST_F(MessageTest, ReadMessageWithContextAsSerializedMessage) {
433   bool message_was_destroyed = false;
434   std::unique_ptr<TestMessageBase> message =
435       std::make_unique<NeverSerializedMessage>(
436           base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
437                      &message_was_destroyed));
438 
439   MojoHandle a, b;
440   CreateMessagePipe(&a, &b);
441   EXPECT_EQ(
442       MOJO_RESULT_OK,
443       MojoWriteMessage(
444           a, TestMessageBase::MakeMessageHandle(std::move(message)), nullptr));
445   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE));
446 
447   MojoMessageHandle message_handle;
448   EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &message_handle));
449   EXPECT_FALSE(message_was_destroyed);
450 
451   // Not a serialized message, so we can't get serialized contents.
452   uint32_t num_bytes = 0;
453   void* buffer;
454   uint32_t num_handles = 0;
455   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
456             MojoGetMessageData(message_handle, nullptr, &buffer, &num_bytes,
457                                nullptr, &num_handles));
458   EXPECT_FALSE(message_was_destroyed);
459 
460   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
461   EXPECT_TRUE(message_was_destroyed);
462 
463   MojoClose(a);
464   MojoClose(b);
465 }
466 
TEST_F(MessageTest,ReadSerializedMessageAsMessageWithContext)467 TEST_F(MessageTest, ReadSerializedMessageAsMessageWithContext) {
468   MojoHandle a, b;
469   CreateMessagePipe(&a, &b);
470   MojoTestBase::WriteMessage(a, "hello there");
471   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(b, MOJO_HANDLE_SIGNAL_READABLE));
472 
473   MojoMessageHandle message_handle;
474   EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(b, nullptr, &message_handle));
475   uintptr_t context;
476   EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
477             MojoGetMessageContext(message_handle, nullptr, &context));
478   MojoClose(a);
479   MojoClose(b);
480   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
481 }
482 
TEST_F(MessageTest,ForceSerializeMessageWithContext)483 TEST_F(MessageTest, ForceSerializeMessageWithContext) {
484   // Basic test - we can serialize a simple message.
485   bool message_was_destroyed = false;
486   auto message = std::make_unique<SimpleMessage>(
487       kTestMessageWithContext1,
488       base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
489                  &message_was_destroyed));
490   auto message_handle = TestMessageBase::MakeMessageHandle(std::move(message));
491   EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr));
492   EXPECT_TRUE(message_was_destroyed);
493   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
494 
495   // Serialize a message with a single handle. Freeing the message should close
496   // the handle.
497   message_was_destroyed = false;
498   message = std::make_unique<SimpleMessage>(
499       kTestMessageWithContext1,
500       base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
501                  &message_was_destroyed));
502   MessagePipe pipe1;
503   message->AddMessagePipe(std::move(pipe1.handle0));
504   message_handle = TestMessageBase::MakeMessageHandle(std::move(message));
505   EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr));
506   EXPECT_TRUE(message_was_destroyed);
507   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
508   EXPECT_EQ(MOJO_RESULT_OK, WaitForSignals(pipe1.handle1.get().value(),
509                                            MOJO_HANDLE_SIGNAL_PEER_CLOSED));
510 
511   // Serialize a message with a handle and extract its serialized contents.
512   message_was_destroyed = false;
513   message = std::make_unique<SimpleMessage>(
514       kTestMessageWithContext1,
515       base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
516                  &message_was_destroyed));
517   MessagePipe pipe2;
518   message->AddMessagePipe(std::move(pipe2.handle0));
519   message_handle = TestMessageBase::MakeMessageHandle(std::move(message));
520   EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr));
521   EXPECT_TRUE(message_was_destroyed);
522   uint32_t num_bytes = 0;
523   void* buffer = nullptr;
524   uint32_t num_handles = 0;
525   MojoHandle extracted_handle;
526   EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
527             MojoGetMessageData(message_handle, nullptr, &buffer, &num_bytes,
528                                nullptr, &num_handles));
529   EXPECT_EQ(MOJO_RESULT_OK,
530             MojoGetMessageData(message_handle, nullptr, &buffer, &num_bytes,
531                                &extracted_handle, &num_handles));
532   EXPECT_EQ(std::string(kTestMessageWithContext1).size(), num_bytes);
533   EXPECT_EQ(std::string(kTestMessageWithContext1),
534             base::StringPiece(static_cast<char*>(buffer), num_bytes));
535 
536   // Confirm that the handle we extracted from the serialized message is still
537   // connected to the same peer, despite the fact that its handle value may have
538   // changed.
539   const char kTestMessage[] = "hey you";
540   MojoTestBase::WriteMessage(pipe2.handle1.get().value(), kTestMessage);
541   EXPECT_EQ(MOJO_RESULT_OK,
542             WaitForSignals(extracted_handle, MOJO_HANDLE_SIGNAL_READABLE));
543   EXPECT_EQ(kTestMessage, MojoTestBase::ReadMessage(extracted_handle));
544 
545   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
546 }
547 
TEST_F(MessageTest,DoubleSerialize)548 TEST_F(MessageTest, DoubleSerialize) {
549   bool message_was_destroyed = false;
550   auto message = std::make_unique<SimpleMessage>(
551       kTestMessageWithContext1,
552       base::Bind([](bool* was_destroyed) { *was_destroyed = true; },
553                  &message_was_destroyed));
554   auto message_handle = TestMessageBase::MakeMessageHandle(std::move(message));
555 
556   // Ensure we can safely call |MojoSerializeMessage()| twice on the same
557   // message handle.
558   EXPECT_EQ(MOJO_RESULT_OK, MojoSerializeMessage(message_handle, nullptr));
559   EXPECT_TRUE(message_was_destroyed);
560   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
561             MojoSerializeMessage(message_handle, nullptr));
562 
563   // And also check that we can call it again after we've written and read the
564   // message object from a pipe.
565   MessagePipe pipe;
566   EXPECT_EQ(MOJO_RESULT_OK,
567             MojoWriteMessage(pipe.handle0->value(), message_handle, nullptr));
568   EXPECT_EQ(MOJO_RESULT_OK,
569             WaitForSignals(pipe.handle1->value(), MOJO_HANDLE_SIGNAL_READABLE));
570   EXPECT_EQ(MOJO_RESULT_OK,
571             MojoReadMessage(pipe.handle1->value(), nullptr, &message_handle));
572   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
573             MojoSerializeMessage(message_handle, nullptr));
574 
575   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message_handle));
576 }
577 
TEST_F(MessageTest,ExtendMessagePayload)578 TEST_F(MessageTest, ExtendMessagePayload) {
579   MojoMessageHandle message;
580   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
581 
582   const std::string kTestMessagePart1("hello i am message.");
583   void* buffer;
584   uint32_t buffer_size;
585   EXPECT_EQ(MOJO_RESULT_OK,
586             MojoAppendMessageData(
587                 message, static_cast<uint32_t>(kTestMessagePart1.size()),
588                 nullptr, 0, nullptr, &buffer, &buffer_size));
589   ASSERT_GE(buffer_size, static_cast<uint32_t>(kTestMessagePart1.size()));
590   memcpy(buffer, kTestMessagePart1.data(), kTestMessagePart1.size());
591 
592   const std::string kTestMessagePart2 = " in ur computer.";
593   const std::string kTestMessageCombined1 =
594       kTestMessagePart1 + kTestMessagePart2;
595   EXPECT_EQ(MOJO_RESULT_OK,
596             MojoAppendMessageData(
597                 message, static_cast<uint32_t>(kTestMessagePart2.size()),
598                 nullptr, 0, nullptr, &buffer, &buffer_size));
599   memcpy(static_cast<uint8_t*>(buffer) + kTestMessagePart1.size(),
600          kTestMessagePart2.data(), kTestMessagePart2.size());
601 
602   const std::string kTestMessagePart3 = kTestMessagePart2 + " carry ur bits.";
603   const std::string kTestMessageCombined2 =
604       kTestMessageCombined1 + kTestMessagePart3;
605   EXPECT_EQ(MOJO_RESULT_OK,
606             MojoAppendMessageData(
607                 message, static_cast<uint32_t>(kTestMessagePart3.size()),
608                 nullptr, 0, nullptr, &buffer, &buffer_size));
609   memcpy(static_cast<uint8_t*>(buffer) + kTestMessageCombined1.size(),
610          kTestMessagePart3.data(), kTestMessagePart3.size());
611 
612   void* payload;
613   uint32_t payload_size;
614   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
615             MojoGetMessageData(message, nullptr, &payload, &payload_size,
616                                nullptr, nullptr));
617 
618   MojoAppendMessageDataOptions options;
619   options.struct_size = sizeof(options);
620   options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
621   EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, nullptr, 0,
622                                                   &options, nullptr, nullptr));
623 
624   EXPECT_EQ(MOJO_RESULT_OK,
625             MojoGetMessageData(message, nullptr, &payload, &payload_size,
626                                nullptr, nullptr));
627   EXPECT_EQ(kTestMessageCombined2.size(), payload_size);
628   EXPECT_EQ(0, memcmp(payload, kTestMessageCombined2.data(),
629                       kTestMessageCombined2.size()));
630 
631   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
632 }
633 
TEST_F(MessageTest,ExtendMessageWithHandlesPayload)634 TEST_F(MessageTest, ExtendMessageWithHandlesPayload) {
635   MojoMessageHandle message;
636   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
637 
638   MojoHandle handles[2];
639   CreateMessagePipe(&handles[0], &handles[1]);
640 
641   const std::string kTestMessagePart1("hello i am message.");
642   void* buffer;
643   uint32_t buffer_size;
644   EXPECT_EQ(MOJO_RESULT_OK,
645             MojoAppendMessageData(
646                 message, static_cast<uint32_t>(kTestMessagePart1.size()),
647                 handles, 2, nullptr, &buffer, &buffer_size));
648   ASSERT_GE(buffer_size, static_cast<uint32_t>(kTestMessagePart1.size()));
649   memcpy(buffer, kTestMessagePart1.data(), kTestMessagePart1.size());
650 
651   const std::string kTestMessagePart2 = " in ur computer.";
652   const std::string kTestMessageCombined1 =
653       kTestMessagePart1 + kTestMessagePart2;
654   MojoAppendMessageDataOptions options;
655   options.struct_size = sizeof(options);
656   options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
657   EXPECT_EQ(MOJO_RESULT_OK,
658             MojoAppendMessageData(
659                 message, static_cast<uint32_t>(kTestMessagePart2.size()),
660                 nullptr, 0, &options, &buffer, &buffer_size));
661   memcpy(static_cast<uint8_t*>(buffer) + kTestMessagePart1.size(),
662          kTestMessagePart2.data(), kTestMessagePart2.size());
663 
664   void* payload;
665   uint32_t payload_size;
666   uint32_t num_handles = 2;
667   EXPECT_EQ(MOJO_RESULT_OK,
668             MojoGetMessageData(message, nullptr, &payload, &payload_size,
669                                handles, &num_handles));
670   EXPECT_EQ(2u, num_handles);
671   EXPECT_EQ(kTestMessageCombined1.size(), payload_size);
672   EXPECT_EQ(0, memcmp(payload, kTestMessageCombined1.data(),
673                       kTestMessageCombined1.size()));
674 
675   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[0]));
676   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[1]));
677   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
678 }
679 
TEST_F(MessageTest,ExtendMessagePayloadLarge)680 TEST_F(MessageTest, ExtendMessagePayloadLarge) {
681   // We progressively extend a message payload from small to large using various
682   // chunk sizes to test potentially interesting boundary conditions.
683   constexpr size_t kTestChunkSizes[] = {1, 2, 3, 64, 509, 4096, 16384, 65535};
684   for (const size_t kChunkSize : kTestChunkSizes) {
685     MojoMessageHandle message;
686     EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
687 
688     MojoHandle handles[2];
689     CreateMessagePipe(&handles[0], &handles[1]);
690 
691     const std::string kTestMessageHeader("hey pretend i'm a header");
692     void* buffer;
693     uint32_t buffer_size;
694     EXPECT_EQ(MOJO_RESULT_OK,
695               MojoAppendMessageData(
696                   message, static_cast<uint32_t>(kTestMessageHeader.size()),
697                   handles, 2, nullptr, &buffer, &buffer_size));
698     ASSERT_GE(buffer_size, static_cast<uint32_t>(kTestMessageHeader.size()));
699     memcpy(buffer, kTestMessageHeader.data(), kTestMessageHeader.size());
700 
701     // 512 kB should be well beyond any reasonable default buffer size for the
702     // system implementation to choose, meaning that this test should guarantee
703     // several reallocations of the serialized message buffer as we
704     // progressively extend the payload to this size.
705     constexpr size_t kTestMessagePayloadSize = 512 * 1024;
706     std::vector<uint8_t> test_payload(kTestMessagePayloadSize);
707     base::RandBytes(test_payload.data(), kTestMessagePayloadSize);
708 
709     size_t current_payload_size = 0;
710     while (current_payload_size < kTestMessagePayloadSize) {
711       const size_t previous_payload_size = current_payload_size;
712       current_payload_size =
713           std::min(current_payload_size + kChunkSize, kTestMessagePayloadSize);
714       const size_t current_chunk_size =
715           current_payload_size - previous_payload_size;
716       const size_t previous_total_size =
717           kTestMessageHeader.size() + previous_payload_size;
718       const size_t current_total_size =
719           kTestMessageHeader.size() + current_payload_size;
720       EXPECT_EQ(MOJO_RESULT_OK,
721                 MojoAppendMessageData(
722                     message, static_cast<uint32_t>(current_chunk_size), nullptr,
723                     0, nullptr, &buffer, &buffer_size));
724       EXPECT_GE(buffer_size, static_cast<uint32_t>(current_total_size));
725       memcpy(static_cast<uint8_t*>(buffer) + previous_total_size,
726              &test_payload[previous_payload_size], current_chunk_size);
727     }
728 
729     MojoAppendMessageDataOptions options;
730     options.struct_size = sizeof(options);
731     options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
732     EXPECT_EQ(MOJO_RESULT_OK,
733               MojoAppendMessageData(message, 0, nullptr, 0, &options, nullptr,
734                                     nullptr));
735 
736     void* payload;
737     uint32_t payload_size;
738     uint32_t num_handles = 2;
739     EXPECT_EQ(MOJO_RESULT_OK,
740               MojoGetMessageData(message, nullptr, &payload, &payload_size,
741                                  handles, &num_handles));
742     EXPECT_EQ(static_cast<uint32_t>(kTestMessageHeader.size() +
743                                     kTestMessagePayloadSize),
744               payload_size);
745     EXPECT_EQ(0, memcmp(payload, kTestMessageHeader.data(),
746                         kTestMessageHeader.size()));
747     EXPECT_EQ(0,
748               memcmp(static_cast<uint8_t*>(payload) + kTestMessageHeader.size(),
749                      test_payload.data(), kTestMessagePayloadSize));
750 
751     EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[0]));
752     EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[1]));
753     EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
754   }
755 }
756 
TEST_F(MessageTest,CorrectPayloadBufferBoundaries)757 TEST_F(MessageTest, CorrectPayloadBufferBoundaries) {
758   // Exercises writes to the full extent of a message's payload under various
759   // circumstances in an effort to catch any potential bugs in internal
760   // allocations or reported size from Mojo APIs.
761 
762   MojoMessageHandle message;
763   void* buffer = nullptr;
764   uint32_t buffer_size = 0;
765   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
766   EXPECT_EQ(MOJO_RESULT_OK,
767             MojoAppendMessageData(message, 0, nullptr, 0, nullptr, &buffer,
768                                   &buffer_size));
769   // Fill the buffer end-to-end.
770   memset(buffer, 'x', buffer_size);
771 
772   // Continuously grow and fill the message buffer several more times. Should
773   // not crash.
774   constexpr uint32_t kChunkSize = 4096;
775   constexpr size_t kNumIterations = 1000;
776   for (size_t i = 0; i < kNumIterations; ++i) {
777     EXPECT_EQ(MOJO_RESULT_OK,
778               MojoAppendMessageData(message, kChunkSize, nullptr, 0, nullptr,
779                                     &buffer, &buffer_size));
780     memset(buffer, 'x', buffer_size);
781   }
782 
783   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
784 }
785 
TEST_F(MessageTest,CommitInvalidMessageContents)786 TEST_F(MessageTest, CommitInvalidMessageContents) {
787   // Regression test for https://crbug.com/755127. Ensures that we don't crash
788   // if we attempt to commit the contents of an unserialized message.
789   MojoMessageHandle message;
790   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
791   EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, nullptr, 0,
792                                                   nullptr, nullptr, nullptr));
793   MojoHandle a, b;
794   CreateMessagePipe(&a, &b);
795   EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, &a, 1, nullptr,
796                                                   nullptr, nullptr));
797 
798   UserMessageImpl::FailHandleSerializationForTesting(true);
799   MojoAppendMessageDataOptions options;
800   options.struct_size = sizeof(options);
801   options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
802   EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, nullptr, 0,
803                                                   nullptr, nullptr, nullptr));
804   UserMessageImpl::FailHandleSerializationForTesting(false);
805   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
806 }
807 
808 #if !defined(OS_IOS)
809 
TEST_F(MessageTest,ExtendPayloadWithHandlesAttached)810 TEST_F(MessageTest, ExtendPayloadWithHandlesAttached) {
811   // Regression test for https://crbug.com/748996. Verifies that internal
812   // message objects do not retain invalid payload pointers across buffer
813   // relocations.
814 
815   MojoHandle handles[5];
816   CreateMessagePipe(&handles[0], &handles[1]);
817   PlatformChannel channel;
818   handles[2] =
819       WrapPlatformHandle(channel.TakeLocalEndpoint().TakePlatformHandle())
820           .release()
821           .value();
822   handles[3] =
823       WrapPlatformHandle(channel.TakeRemoteEndpoint().TakePlatformHandle())
824           .release()
825           .value();
826   handles[4] = SharedBufferHandle::Create(64).release().value();
827 
828   MojoMessageHandle message;
829   void* buffer = nullptr;
830   uint32_t buffer_size = 0;
831   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
832   EXPECT_EQ(MOJO_RESULT_OK,
833             MojoAppendMessageData(message, 0, handles, 5, nullptr, &buffer,
834                                   &buffer_size));
835 
836   // Force buffer reallocation by extending the payload beyond the original
837   // buffer size. This should typically result in a relocation of the buffer as
838   // well -- at least often enough that breakage will be caught by automated
839   // tests.
840   MojoAppendMessageDataOptions options;
841   options.struct_size = sizeof(options);
842   options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
843   uint32_t payload_size = buffer_size * 64;
844   EXPECT_EQ(MOJO_RESULT_OK,
845             MojoAppendMessageData(message, payload_size, nullptr, 0, &options,
846                                   &buffer, &buffer_size));
847   ASSERT_GE(buffer_size, payload_size);
848   memset(buffer, 'x', payload_size);
849 
850   RunTestClient("ReadAndIgnoreMessage", [&](MojoHandle h) {
851     // Send the message out of process to exercise the regression path where
852     // internally cached, stale payload pointers may be dereferenced and written
853     // into.
854     EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h, message, nullptr));
855   });
856 }
857 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndIgnoreMessage,MessageTest,h)858 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndIgnoreMessage, MessageTest, h) {
859   MojoTestBase::WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE);
860 
861   MojoHandle handles[5];
862   MojoTestBase::ReadMessageWithHandles(h, handles, 5);
863   for (size_t i = 0; i < 5; ++i)
864     EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[i]));
865 }
866 
TEST_F(MessageTest,ExtendPayloadWithHandlesAttachedViaExtension)867 TEST_F(MessageTest, ExtendPayloadWithHandlesAttachedViaExtension) {
868   MojoHandle handles[5];
869   CreateMessagePipe(&handles[0], &handles[4]);
870   PlatformChannel channel;
871   handles[1] =
872       WrapPlatformHandle(channel.TakeLocalEndpoint().TakePlatformHandle())
873           .release()
874           .value();
875   handles[2] =
876       WrapPlatformHandle(channel.TakeRemoteEndpoint().TakePlatformHandle())
877           .release()
878           .value();
879   handles[3] = SharedBufferHandle::Create(64).release().value();
880 
881   MojoMessageHandle message;
882   void* buffer = nullptr;
883   uint32_t buffer_size = 0;
884   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
885   EXPECT_EQ(MOJO_RESULT_OK,
886             MojoAppendMessageData(message, 0, handles, 1, nullptr, &buffer,
887                                   &buffer_size));
888   uint32_t payload_size = buffer_size * 64;
889   EXPECT_EQ(MOJO_RESULT_OK,
890             MojoAppendMessageData(message, payload_size, nullptr, 0, nullptr,
891                                   &buffer, nullptr));
892 
893   // Add more handles.
894   EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, handles + 1, 1,
895                                                   nullptr, &buffer, nullptr));
896   MojoAppendMessageDataOptions options;
897   options.struct_size = sizeof(options);
898   options.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
899   EXPECT_EQ(MOJO_RESULT_OK, MojoAppendMessageData(message, 0, handles + 2, 3,
900                                                   &options, &buffer, nullptr));
901   memset(buffer, 'x', payload_size);
902 
903   RunTestClient("ReadMessageAndCheckPipe", [&](MojoHandle h) {
904     // Send the message out of process to exercise the regression path where
905     // internally cached, stale payload pointers may be dereferenced and written
906     // into.
907     EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h, message, nullptr));
908   });
909 }
910 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadMessageAndCheckPipe,MessageTest,h)911 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadMessageAndCheckPipe, MessageTest, h) {
912   MojoTestBase::WaitForSignals(h, MOJO_HANDLE_SIGNAL_READABLE);
913 
914   const std::string kTestMessage("hey pipe");
915   MojoHandle handles[5];
916   MojoTestBase::ReadMessageWithHandles(h, handles, 5);
917   MojoTestBase::WriteMessage(handles[0], kTestMessage);
918   MojoTestBase::WaitForSignals(handles[4], MOJO_HANDLE_SIGNAL_READABLE);
919   EXPECT_EQ(kTestMessage, MojoTestBase::ReadMessage(handles[4]));
920   for (size_t i = 0; i < 5; ++i)
921     EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handles[i]));
922 }
923 
924 #endif  // !defined(OS_IOS)
925 
TEST_F(MessageTest,PartiallySerializedMessagesDontLeakHandles)926 TEST_F(MessageTest, PartiallySerializedMessagesDontLeakHandles) {
927   MojoMessageHandle message;
928   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &message));
929 
930   MojoHandle handles[2];
931   CreateMessagePipe(&handles[0], &handles[1]);
932 
933   const std::string kTestMessagePart1("hello i am message.");
934   void* buffer;
935   uint32_t buffer_size;
936   EXPECT_EQ(MOJO_RESULT_OK,
937             MojoAppendMessageData(
938                 message, static_cast<uint32_t>(kTestMessagePart1.size()),
939                 nullptr, 0, nullptr, &buffer, &buffer_size));
940   ASSERT_GE(buffer_size, static_cast<uint32_t>(kTestMessagePart1.size()));
941   memcpy(buffer, kTestMessagePart1.data(), kTestMessagePart1.size());
942 
943   EXPECT_EQ(MOJO_RESULT_OK,
944             MojoAppendMessageData(message, 0, handles, 1, nullptr, &buffer,
945                                   &buffer_size));
946 
947   // This must close |handles[0]|, which we can detect by observing the
948   // signal state of |handles[1].
949   EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(message));
950   EXPECT_EQ(MOJO_RESULT_OK,
951             WaitForSignals(handles[1], MOJO_HANDLE_SIGNAL_PEER_CLOSED));
952 }
953 
954 }  // namespace
955 }  // namespace core
956 }  // namespace mojo
957