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 <stdio.h>
7#include <string.h>
8
9#include <string>
10#include <vector>
11
12#include "base/bind.h"
13#include "base/files/file_path.h"
14#include "base/files/file_util.h"
15#include "base/files/scoped_file.h"
16#include "base/files/scoped_temp_dir.h"
17#include "base/location.h"
18#include "base/logging.h"
19#include "base/macros.h"
20#include "build/build_config.h"  // TODO(vtl): Remove this.
21#include "mojo/common/test/test_utils.h"
22#include "mojo/embedder/platform_shared_buffer.h"
23#include "mojo/embedder/scoped_platform_handle.h"
24#include "mojo/system/channel.h"
25#include "mojo/system/dispatcher.h"
26#include "mojo/system/message_pipe.h"
27#include "mojo/system/message_pipe_test_utils.h"
28#include "mojo/system/platform_handle_dispatcher.h"
29#include "mojo/system/raw_channel.h"
30#include "mojo/system/shared_buffer_dispatcher.h"
31#include "mojo/system/test_utils.h"
32#include "testing/gtest/include/gtest/gtest.h"
33
34namespace mojo {
35namespace system {
36namespace {
37
38class MultiprocessMessagePipeTest
39    : public test::MultiprocessMessagePipeTestBase {};
40
41// For each message received, sends a reply message with the same contents
42// repeated twice, until the other end is closed or it receives "quitquitquit"
43// (which it doesn't reply to). It'll return the number of messages received,
44// not including any "quitquitquit" message, modulo 100.
45MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) {
46  embedder::SimplePlatformSupport platform_support;
47  test::ChannelThread channel_thread(&platform_support);
48  embedder::ScopedPlatformHandle client_platform_handle =
49      mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
50  CHECK(client_platform_handle.is_valid());
51  scoped_refptr<ChannelEndpoint> ep;
52  scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
53  channel_thread.Start(client_platform_handle.Pass(), ep);
54
55  const std::string quitquitquit("quitquitquit");
56  int rv = 0;
57  for (;; rv = (rv + 1) % 100) {
58    // Wait for our end of the message pipe to be readable.
59    HandleSignalsState hss;
60    MojoResult result =
61        test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss);
62    if (result != MOJO_RESULT_OK) {
63      // It was closed, probably.
64      CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION);
65      CHECK_EQ(hss.satisfied_signals, 0u);
66      CHECK_EQ(hss.satisfiable_signals, 0u);
67      break;
68    } else {
69      CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
70      CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
71    }
72
73    std::string read_buffer(1000, '\0');
74    uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
75    CHECK_EQ(mp->ReadMessage(0,
76                             UserPointer<void>(&read_buffer[0]),
77                             MakeUserPointer(&read_buffer_size),
78                             nullptr,
79                             nullptr,
80                             MOJO_READ_MESSAGE_FLAG_NONE),
81             MOJO_RESULT_OK);
82    read_buffer.resize(read_buffer_size);
83    VLOG(2) << "Child got: " << read_buffer;
84
85    if (read_buffer == quitquitquit) {
86      VLOG(2) << "Child quitting.";
87      break;
88    }
89
90    std::string write_buffer = read_buffer + read_buffer;
91    CHECK_EQ(mp->WriteMessage(0,
92                              UserPointer<const void>(write_buffer.data()),
93                              static_cast<uint32_t>(write_buffer.size()),
94                              nullptr,
95                              MOJO_WRITE_MESSAGE_FLAG_NONE),
96             MOJO_RESULT_OK);
97  }
98
99  mp->Close(0);
100  return rv;
101}
102
103// Sends "hello" to child, and expects "hellohello" back.
104TEST_F(MultiprocessMessagePipeTest, Basic) {
105  helper()->StartChild("EchoEcho");
106
107  scoped_refptr<ChannelEndpoint> ep;
108  scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
109  Init(ep);
110
111  std::string hello("hello");
112  EXPECT_EQ(MOJO_RESULT_OK,
113            mp->WriteMessage(0,
114                             UserPointer<const void>(hello.data()),
115                             static_cast<uint32_t>(hello.size()),
116                             nullptr,
117                             MOJO_WRITE_MESSAGE_FLAG_NONE));
118
119  HandleSignalsState hss;
120  EXPECT_EQ(MOJO_RESULT_OK,
121            test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
122  // The child may or may not have closed its end of the message pipe and died
123  // (and we may or may not know it yet), so our end may or may not appear as
124  // writable.
125  EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
126  EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
127
128  std::string read_buffer(1000, '\0');
129  uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
130  CHECK_EQ(mp->ReadMessage(0,
131                           UserPointer<void>(&read_buffer[0]),
132                           MakeUserPointer(&read_buffer_size),
133                           nullptr,
134                           nullptr,
135                           MOJO_READ_MESSAGE_FLAG_NONE),
136           MOJO_RESULT_OK);
137  read_buffer.resize(read_buffer_size);
138  VLOG(2) << "Parent got: " << read_buffer;
139  EXPECT_EQ(hello + hello, read_buffer);
140
141  mp->Close(0);
142
143  // We sent one message.
144  EXPECT_EQ(1 % 100, helper()->WaitForChildShutdown());
145}
146
147// Sends a bunch of messages to the child. Expects them "repeated" back. Waits
148// for the child to close its end before quitting.
149TEST_F(MultiprocessMessagePipeTest, QueueMessages) {
150  helper()->StartChild("EchoEcho");
151
152  scoped_refptr<ChannelEndpoint> ep;
153  scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
154  Init(ep);
155
156  static const size_t kNumMessages = 1001;
157  for (size_t i = 0; i < kNumMessages; i++) {
158    std::string write_buffer(i, 'A' + (i % 26));
159    EXPECT_EQ(MOJO_RESULT_OK,
160              mp->WriteMessage(0,
161                               UserPointer<const void>(write_buffer.data()),
162                               static_cast<uint32_t>(write_buffer.size()),
163                               nullptr,
164                               MOJO_WRITE_MESSAGE_FLAG_NONE));
165  }
166
167  const std::string quitquitquit("quitquitquit");
168  EXPECT_EQ(MOJO_RESULT_OK,
169            mp->WriteMessage(0,
170                             UserPointer<const void>(quitquitquit.data()),
171                             static_cast<uint32_t>(quitquitquit.size()),
172                             nullptr,
173                             MOJO_WRITE_MESSAGE_FLAG_NONE));
174
175  for (size_t i = 0; i < kNumMessages; i++) {
176    HandleSignalsState hss;
177    EXPECT_EQ(MOJO_RESULT_OK,
178              test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
179    // The child may or may not have closed its end of the message pipe and died
180    // (and we may or may not know it yet), so our end may or may not appear as
181    // writable.
182    EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
183    EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
184
185    std::string read_buffer(kNumMessages * 2, '\0');
186    uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size());
187    CHECK_EQ(mp->ReadMessage(0,
188                             UserPointer<void>(&read_buffer[0]),
189                             MakeUserPointer(&read_buffer_size),
190                             nullptr,
191                             nullptr,
192                             MOJO_READ_MESSAGE_FLAG_NONE),
193             MOJO_RESULT_OK);
194    read_buffer.resize(read_buffer_size);
195
196    EXPECT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer);
197  }
198
199  // Wait for it to become readable, which should fail (since we sent
200  // "quitquitquit").
201  HandleSignalsState hss;
202  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
203            test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
204  EXPECT_EQ(0u, hss.satisfied_signals);
205  EXPECT_EQ(0u, hss.satisfiable_signals);
206
207  mp->Close(0);
208
209  EXPECT_EQ(static_cast<int>(kNumMessages % 100),
210            helper()->WaitForChildShutdown());
211}
212
213MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) {
214  embedder::SimplePlatformSupport platform_support;
215  test::ChannelThread channel_thread(&platform_support);
216  embedder::ScopedPlatformHandle client_platform_handle =
217      mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
218  CHECK(client_platform_handle.is_valid());
219  scoped_refptr<ChannelEndpoint> ep;
220  scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
221  channel_thread.Start(client_platform_handle.Pass(), ep);
222
223  // Wait for the first message from our parent.
224  HandleSignalsState hss;
225  CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss),
226           MOJO_RESULT_OK);
227  // In this test, the parent definitely doesn't close its end of the message
228  // pipe before we do.
229  CHECK_EQ(hss.satisfied_signals,
230           MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
231  CHECK_EQ(hss.satisfiable_signals,
232           MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
233
234  // It should have a shared buffer.
235  std::string read_buffer(100, '\0');
236  uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
237  DispatcherVector dispatchers;
238  uint32_t num_dispatchers = 10;  // Maximum number to receive.
239  CHECK_EQ(mp->ReadMessage(0,
240                           UserPointer<void>(&read_buffer[0]),
241                           MakeUserPointer(&num_bytes),
242                           &dispatchers,
243                           &num_dispatchers,
244                           MOJO_READ_MESSAGE_FLAG_NONE),
245           MOJO_RESULT_OK);
246  read_buffer.resize(num_bytes);
247  CHECK_EQ(read_buffer, std::string("go 1"));
248  CHECK_EQ(num_dispatchers, 1u);
249
250  CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::kTypeSharedBuffer);
251
252  scoped_refptr<SharedBufferDispatcher> dispatcher(
253      static_cast<SharedBufferDispatcher*>(dispatchers[0].get()));
254
255  // Make a mapping.
256  scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
257  CHECK_EQ(dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping),
258           MOJO_RESULT_OK);
259  CHECK(mapping);
260  CHECK(mapping->GetBase());
261  CHECK_EQ(mapping->GetLength(), 100u);
262
263  // Write some stuff to the shared buffer.
264  static const char kHello[] = "hello";
265  memcpy(mapping->GetBase(), kHello, sizeof(kHello));
266
267  // We should be able to close the dispatcher now.
268  dispatcher->Close();
269
270  // And send a message to signal that we've written stuff.
271  const std::string go2("go 2");
272  CHECK_EQ(mp->WriteMessage(0,
273                            UserPointer<const void>(&go2[0]),
274                            static_cast<uint32_t>(go2.size()),
275                            nullptr,
276                            MOJO_WRITE_MESSAGE_FLAG_NONE),
277           MOJO_RESULT_OK);
278
279  // Now wait for our parent to send us a message.
280  hss = HandleSignalsState();
281  CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss),
282           MOJO_RESULT_OK);
283  CHECK_EQ(hss.satisfied_signals,
284           MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
285  CHECK_EQ(hss.satisfiable_signals,
286           MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
287
288  read_buffer = std::string(100, '\0');
289  num_bytes = static_cast<uint32_t>(read_buffer.size());
290  CHECK_EQ(mp->ReadMessage(0,
291                           UserPointer<void>(&read_buffer[0]),
292                           MakeUserPointer(&num_bytes),
293                           nullptr,
294                           nullptr,
295                           MOJO_READ_MESSAGE_FLAG_NONE),
296           MOJO_RESULT_OK);
297  read_buffer.resize(num_bytes);
298  CHECK_EQ(read_buffer, std::string("go 3"));
299
300  // It should have written something to the shared buffer.
301  static const char kWorld[] = "world!!!";
302  CHECK_EQ(memcmp(mapping->GetBase(), kWorld, sizeof(kWorld)), 0);
303
304  // And we're done.
305  mp->Close(0);
306
307  return 0;
308}
309
310#if defined(OS_POSIX)
311#define MAYBE_SharedBufferPassing SharedBufferPassing
312#else
313// Not yet implemented (on Windows).
314#define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing
315#endif
316TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) {
317  helper()->StartChild("CheckSharedBuffer");
318
319  scoped_refptr<ChannelEndpoint> ep;
320  scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
321  Init(ep);
322
323  // Make a shared buffer.
324  scoped_refptr<SharedBufferDispatcher> dispatcher;
325  EXPECT_EQ(MOJO_RESULT_OK,
326            SharedBufferDispatcher::Create(
327                platform_support(),
328                SharedBufferDispatcher::kDefaultCreateOptions,
329                100,
330                &dispatcher));
331  ASSERT_TRUE(dispatcher.get());
332
333  // Make a mapping.
334  scoped_ptr<embedder::PlatformSharedBufferMapping> mapping;
335  EXPECT_EQ(MOJO_RESULT_OK,
336            dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
337  ASSERT_TRUE(mapping);
338  ASSERT_TRUE(mapping->GetBase());
339  ASSERT_EQ(100u, mapping->GetLength());
340
341  // Send the shared buffer.
342  const std::string go1("go 1");
343  DispatcherTransport transport(
344      test::DispatcherTryStartTransport(dispatcher.get()));
345  ASSERT_TRUE(transport.is_valid());
346
347  std::vector<DispatcherTransport> transports;
348  transports.push_back(transport);
349  EXPECT_EQ(MOJO_RESULT_OK,
350            mp->WriteMessage(0,
351                             UserPointer<const void>(&go1[0]),
352                             static_cast<uint32_t>(go1.size()),
353                             &transports,
354                             MOJO_WRITE_MESSAGE_FLAG_NONE));
355  transport.End();
356
357  EXPECT_TRUE(dispatcher->HasOneRef());
358  dispatcher = nullptr;
359
360  // Wait for a message from the child.
361  HandleSignalsState hss;
362  EXPECT_EQ(MOJO_RESULT_OK,
363            test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
364  EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
365  EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE));
366
367  std::string read_buffer(100, '\0');
368  uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
369  EXPECT_EQ(MOJO_RESULT_OK,
370            mp->ReadMessage(0,
371                            UserPointer<void>(&read_buffer[0]),
372                            MakeUserPointer(&num_bytes),
373                            nullptr,
374                            nullptr,
375                            MOJO_READ_MESSAGE_FLAG_NONE));
376  read_buffer.resize(num_bytes);
377  EXPECT_EQ(std::string("go 2"), read_buffer);
378
379  // After we get it, the child should have written something to the shared
380  // buffer.
381  static const char kHello[] = "hello";
382  EXPECT_EQ(0, memcmp(mapping->GetBase(), kHello, sizeof(kHello)));
383
384  // Now we'll write some stuff to the shared buffer.
385  static const char kWorld[] = "world!!!";
386  memcpy(mapping->GetBase(), kWorld, sizeof(kWorld));
387
388  // And send a message to signal that we've written stuff.
389  const std::string go3("go 3");
390  EXPECT_EQ(MOJO_RESULT_OK,
391            mp->WriteMessage(0,
392                             UserPointer<const void>(&go3[0]),
393                             static_cast<uint32_t>(go3.size()),
394                             nullptr,
395                             MOJO_WRITE_MESSAGE_FLAG_NONE));
396
397  // Wait for |mp| to become readable, which should fail.
398  hss = HandleSignalsState();
399  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
400            test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
401  EXPECT_EQ(0u, hss.satisfied_signals);
402  EXPECT_EQ(0u, hss.satisfiable_signals);
403
404  mp->Close(0);
405
406  EXPECT_EQ(0, helper()->WaitForChildShutdown());
407}
408
409MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) {
410  embedder::SimplePlatformSupport platform_support;
411  test::ChannelThread channel_thread(&platform_support);
412  embedder::ScopedPlatformHandle client_platform_handle =
413      mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
414  CHECK(client_platform_handle.is_valid());
415  scoped_refptr<ChannelEndpoint> ep;
416  scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
417  channel_thread.Start(client_platform_handle.Pass(), ep);
418
419  HandleSignalsState hss;
420  CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss),
421           MOJO_RESULT_OK);
422  CHECK_EQ(hss.satisfied_signals,
423           MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
424  CHECK_EQ(hss.satisfiable_signals,
425           MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
426
427  std::string read_buffer(100, '\0');
428  uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
429  DispatcherVector dispatchers;
430  uint32_t num_dispatchers = 10;  // Maximum number to receive.
431  CHECK_EQ(mp->ReadMessage(0,
432                           UserPointer<void>(&read_buffer[0]),
433                           MakeUserPointer(&num_bytes),
434                           &dispatchers,
435                           &num_dispatchers,
436                           MOJO_READ_MESSAGE_FLAG_NONE),
437           MOJO_RESULT_OK);
438  mp->Close(0);
439
440  read_buffer.resize(num_bytes);
441  CHECK_EQ(read_buffer, std::string("hello"));
442  CHECK_EQ(num_dispatchers, 1u);
443
444  CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::kTypePlatformHandle);
445
446  scoped_refptr<PlatformHandleDispatcher> dispatcher(
447      static_cast<PlatformHandleDispatcher*>(dispatchers[0].get()));
448  embedder::ScopedPlatformHandle h = dispatcher->PassPlatformHandle().Pass();
449  CHECK(h.is_valid());
450  dispatcher->Close();
451
452  base::ScopedFILE fp(mojo::test::FILEFromPlatformHandle(h.Pass(), "r"));
453  CHECK(fp);
454  std::string fread_buffer(100, '\0');
455  size_t bytes_read = fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get());
456  fread_buffer.resize(bytes_read);
457  CHECK_EQ(fread_buffer, "world");
458
459  return 0;
460}
461
462#if defined(OS_POSIX)
463#define MAYBE_PlatformHandlePassing PlatformHandlePassing
464#else
465// Not yet implemented (on Windows).
466#define MAYBE_PlatformHandlePassing DISABLED_PlatformHandlePassing
467#endif
468TEST_F(MultiprocessMessagePipeTest, MAYBE_PlatformHandlePassing) {
469  base::ScopedTempDir temp_dir;
470  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
471
472  helper()->StartChild("CheckPlatformHandleFile");
473
474  scoped_refptr<ChannelEndpoint> ep;
475  scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
476  Init(ep);
477
478  base::FilePath unused;
479  base::ScopedFILE fp(
480      CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused));
481  const std::string world("world");
482  ASSERT_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size());
483  fflush(fp.get());
484  rewind(fp.get());
485
486  embedder::ScopedPlatformHandle h(
487      mojo::test::PlatformHandleFromFILE(fp.Pass()));
488  scoped_refptr<PlatformHandleDispatcher> dispatcher(
489      new PlatformHandleDispatcher(h.Pass()));
490
491  const std::string hello("hello");
492  DispatcherTransport transport(
493      test::DispatcherTryStartTransport(dispatcher.get()));
494  ASSERT_TRUE(transport.is_valid());
495
496  std::vector<DispatcherTransport> transports;
497  transports.push_back(transport);
498  EXPECT_EQ(MOJO_RESULT_OK,
499            mp->WriteMessage(0,
500                             UserPointer<const void>(&hello[0]),
501                             static_cast<uint32_t>(hello.size()),
502                             &transports,
503                             MOJO_WRITE_MESSAGE_FLAG_NONE));
504  transport.End();
505
506  EXPECT_TRUE(dispatcher->HasOneRef());
507  dispatcher = nullptr;
508
509  // Wait for it to become readable, which should fail.
510  HandleSignalsState hss;
511  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
512            test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
513  EXPECT_EQ(0u, hss.satisfied_signals);
514  EXPECT_EQ(0u, hss.satisfiable_signals);
515
516  mp->Close(0);
517
518  EXPECT_EQ(0, helper()->WaitForChildShutdown());
519}
520
521}  // namespace
522}  // namespace system
523}  // namespace mojo
524