Home | History | Annotate | Download | only in core
      1 // Copyright 2015 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 <string.h>
      6 
      7 #include <string>
      8 #include <utility>
      9 
     10 #include "base/logging.h"
     11 #include "base/memory/shared_memory.h"
     12 #include "base/strings/string_piece.h"
     13 #include "build/build_config.h"
     14 #include "mojo/core/core.h"
     15 #include "mojo/core/shared_buffer_dispatcher.h"
     16 #include "mojo/core/test/mojo_test_base.h"
     17 #include "mojo/public/c/system/types.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 namespace mojo {
     21 namespace core {
     22 namespace {
     23 
     24 using SharedBufferTest = test::MojoTestBase;
     25 
     26 TEST_F(SharedBufferTest, CreateSharedBuffer) {
     27   const std::string message = "hello";
     28   MojoHandle h = CreateBuffer(message.size());
     29   WriteToBuffer(h, 0, message);
     30   ExpectBufferContents(h, 0, message);
     31 }
     32 
     33 TEST_F(SharedBufferTest, DuplicateSharedBuffer) {
     34   const std::string message = "hello";
     35   MojoHandle h = CreateBuffer(message.size());
     36   WriteToBuffer(h, 0, message);
     37 
     38   MojoHandle dupe = DuplicateBuffer(h, false);
     39   ExpectBufferContents(dupe, 0, message);
     40 }
     41 
     42 TEST_F(SharedBufferTest, PassSharedBufferLocal) {
     43   const std::string message = "hello";
     44   MojoHandle h = CreateBuffer(message.size());
     45   WriteToBuffer(h, 0, message);
     46 
     47   MojoHandle dupe = DuplicateBuffer(h, false);
     48   MojoHandle p0, p1;
     49   CreateMessagePipe(&p0, &p1);
     50 
     51   WriteMessageWithHandles(p0, "...", &dupe, 1);
     52   EXPECT_EQ("...", ReadMessageWithHandles(p1, &dupe, 1));
     53 
     54   ExpectBufferContents(dupe, 0, message);
     55 }
     56 
     57 #if !defined(OS_IOS)
     58 
     59 // Reads a single message with a shared buffer handle, maps the buffer, copies
     60 // the message contents into it, then exits.
     61 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CopyToBufferClient, SharedBufferTest, h) {
     62   MojoHandle b;
     63   std::string message = ReadMessageWithHandles(h, &b, 1);
     64   WriteToBuffer(b, 0, message);
     65 
     66   EXPECT_EQ("quit", ReadMessage(h));
     67 }
     68 
     69 TEST_F(SharedBufferTest, PassSharedBufferCrossProcess) {
     70   const std::string message = "hello";
     71   MojoHandle b = CreateBuffer(message.size());
     72 
     73   RunTestClient("CopyToBufferClient", [&](MojoHandle h) {
     74     MojoHandle dupe = DuplicateBuffer(b, false);
     75     WriteMessageWithHandles(h, message, &dupe, 1);
     76     WriteMessage(h, "quit");
     77   });
     78 
     79   ExpectBufferContents(b, 0, message);
     80 }
     81 
     82 // Creates a new buffer, maps it, writes a message contents to it, unmaps it,
     83 // and finally passes it back to the parent.
     84 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateBufferClient, SharedBufferTest, h) {
     85   std::string message = ReadMessage(h);
     86   MojoHandle b = CreateBuffer(message.size());
     87   WriteToBuffer(b, 0, message);
     88   WriteMessageWithHandles(h, "have a buffer", &b, 1);
     89 
     90   EXPECT_EQ("quit", ReadMessage(h));
     91 }
     92 
     93 TEST_F(SharedBufferTest, PassSharedBufferFromChild) {
     94   const std::string message = "hello";
     95   MojoHandle b;
     96   RunTestClient("CreateBufferClient", [&](MojoHandle h) {
     97     WriteMessage(h, message);
     98     ReadMessageWithHandles(h, &b, 1);
     99     WriteMessage(h, "quit");
    100   });
    101 
    102   ExpectBufferContents(b, 0, message);
    103 }
    104 
    105 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBuffer, SharedBufferTest, h) {
    106   // Receive a pipe handle over the primordial pipe. This will be connected to
    107   // another child process.
    108   MojoHandle other_child;
    109   std::string message = ReadMessageWithHandles(h, &other_child, 1);
    110 
    111   // Create a new shared buffer.
    112   MojoHandle b = CreateBuffer(message.size());
    113 
    114   // Send a copy of the buffer to the parent and the other child.
    115   MojoHandle dupe = DuplicateBuffer(b, false);
    116   WriteMessageWithHandles(h, "", &b, 1);
    117   WriteMessageWithHandles(other_child, "", &dupe, 1);
    118 
    119   EXPECT_EQ("quit", ReadMessage(h));
    120 }
    121 
    122 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBuffer, SharedBufferTest, h) {
    123   // Receive a pipe handle over the primordial pipe. This will be connected to
    124   // another child process (running CreateAndPassBuffer).
    125   MojoHandle other_child;
    126   std::string message = ReadMessageWithHandles(h, &other_child, 1);
    127 
    128   // Receive a shared buffer from the other child.
    129   MojoHandle b;
    130   ReadMessageWithHandles(other_child, &b, 1);
    131 
    132   // Write the message from the parent into the buffer and exit.
    133   WriteToBuffer(b, 0, message);
    134   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
    135   EXPECT_EQ("quit", ReadMessage(h));
    136 }
    137 
    138 TEST_F(SharedBufferTest, PassSharedBufferFromChildToChild) {
    139   const std::string message = "hello";
    140   MojoHandle p0, p1;
    141   CreateMessagePipe(&p0, &p1);
    142 
    143   MojoHandle b;
    144   RunTestClient("CreateAndPassBuffer", [&](MojoHandle h0) {
    145     RunTestClient("ReceiveAndEditBuffer", [&](MojoHandle h1) {
    146       // Send one end of the pipe to each child. The first child will create
    147       // and pass a buffer to the second child and back to us. The second child
    148       // will write our message into the buffer.
    149       WriteMessageWithHandles(h0, message, &p0, 1);
    150       WriteMessageWithHandles(h1, message, &p1, 1);
    151 
    152       // Receive the buffer back from the first child.
    153       ReadMessageWithHandles(h0, &b, 1);
    154 
    155       WriteMessage(h1, "quit");
    156     });
    157     WriteMessage(h0, "quit");
    158   });
    159 
    160   // The second child should have written this message.
    161   ExpectBufferContents(b, 0, message);
    162 }
    163 
    164 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBufferParent,
    165                                   SharedBufferTest,
    166                                   parent) {
    167   RunTestClient("CreateAndPassBuffer", [&](MojoHandle child) {
    168     // Read a pipe from the parent and forward it to our child.
    169     MojoHandle pipe;
    170     std::string message = ReadMessageWithHandles(parent, &pipe, 1);
    171 
    172     WriteMessageWithHandles(child, message, &pipe, 1);
    173 
    174     // Read a buffer handle from the child and pass it back to the parent.
    175     MojoHandle buffer;
    176     EXPECT_EQ("", ReadMessageWithHandles(child, &buffer, 1));
    177     WriteMessageWithHandles(parent, "", &buffer, 1);
    178 
    179     EXPECT_EQ("quit", ReadMessage(parent));
    180     WriteMessage(child, "quit");
    181   });
    182 }
    183 
    184 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBufferParent,
    185                                   SharedBufferTest,
    186                                   parent) {
    187   RunTestClient("ReceiveAndEditBuffer", [&](MojoHandle child) {
    188     // Read a pipe from the parent and forward it to our child.
    189     MojoHandle pipe;
    190     std::string message = ReadMessageWithHandles(parent, &pipe, 1);
    191     WriteMessageWithHandles(child, message, &pipe, 1);
    192 
    193     EXPECT_EQ("quit", ReadMessage(parent));
    194     WriteMessage(child, "quit");
    195   });
    196 }
    197 
    198 #if defined(OS_ANDROID) || defined(OS_MACOSX)
    199 // Android multi-process tests are not executing the new process. This is flaky.
    200 // Passing shared memory handles between cousins is not currently supported on
    201 // OSX.
    202 #define MAYBE_PassHandleBetweenCousins DISABLED_PassHandleBetweenCousins
    203 #else
    204 #define MAYBE_PassHandleBetweenCousins PassHandleBetweenCousins
    205 #endif
    206 TEST_F(SharedBufferTest, MAYBE_PassHandleBetweenCousins) {
    207   const std::string message = "hello";
    208   MojoHandle p0, p1;
    209   CreateMessagePipe(&p0, &p1);
    210 
    211   // Spawn two children who will each spawn their own child. Make sure the
    212   // grandchildren (cousins to each other) can pass platform handles.
    213   MojoHandle b;
    214   RunTestClient("CreateAndPassBufferParent", [&](MojoHandle child1) {
    215     RunTestClient("ReceiveAndEditBufferParent", [&](MojoHandle child2) {
    216       MojoHandle pipe[2];
    217       CreateMessagePipe(&pipe[0], &pipe[1]);
    218 
    219       WriteMessageWithHandles(child1, message, &pipe[0], 1);
    220       WriteMessageWithHandles(child2, message, &pipe[1], 1);
    221 
    222       // Receive the buffer back from the first child.
    223       ReadMessageWithHandles(child1, &b, 1);
    224 
    225       WriteMessage(child2, "quit");
    226     });
    227     WriteMessage(child1, "quit");
    228   });
    229 
    230   // The second grandchild should have written this message.
    231   ExpectBufferContents(b, 0, message);
    232 }
    233 
    234 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndMapWriteSharedBuffer,
    235                                   SharedBufferTest,
    236                                   h) {
    237   // Receive the shared buffer.
    238   MojoHandle b;
    239   EXPECT_EQ("hello", ReadMessageWithHandles(h, &b, 1));
    240 
    241   // Read from the bufer.
    242   ExpectBufferContents(b, 0, "hello");
    243 
    244   // Extract the shared memory handle and verify that it is read-only.
    245   auto* dispatcher =
    246       static_cast<SharedBufferDispatcher*>(Core::Get()->GetDispatcher(b).get());
    247   base::subtle::PlatformSharedMemoryRegion& region =
    248       dispatcher->GetRegionForTesting();
    249   EXPECT_EQ(region.GetMode(),
    250             base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly);
    251 
    252   EXPECT_EQ("quit", ReadMessage(h));
    253   WriteMessage(h, "ok");
    254 }
    255 
    256 #if defined(OS_ANDROID)
    257 // Android multi-process tests are not executing the new process. This is flaky.
    258 #define MAYBE_CreateAndPassReadOnlyBuffer DISABLED_CreateAndPassReadOnlyBuffer
    259 #else
    260 #define MAYBE_CreateAndPassReadOnlyBuffer CreateAndPassReadOnlyBuffer
    261 #endif
    262 TEST_F(SharedBufferTest, MAYBE_CreateAndPassReadOnlyBuffer) {
    263   RunTestClient("ReadAndMapWriteSharedBuffer", [&](MojoHandle h) {
    264     // Create a new shared buffer.
    265     MojoHandle b = CreateBuffer(1234);
    266     WriteToBuffer(b, 0, "hello");
    267 
    268     // Send a read-only copy of the buffer to the child.
    269     MojoHandle dupe = DuplicateBuffer(b, true /* read_only */);
    270     WriteMessageWithHandles(h, "hello", &dupe, 1);
    271 
    272     WriteMessage(h, "quit");
    273     EXPECT_EQ("ok", ReadMessage(h));
    274   });
    275 }
    276 
    277 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassReadOnlyBuffer,
    278                                   SharedBufferTest,
    279                                   h) {
    280   // Create a new shared buffer.
    281   MojoHandle b = CreateBuffer(1234);
    282   WriteToBuffer(b, 0, "hello");
    283 
    284   // Send a read-only copy of the buffer to the parent.
    285   MojoHandle dupe = DuplicateBuffer(b, true /* read_only */);
    286   WriteMessageWithHandles(h, "", &dupe, 1);
    287 
    288   EXPECT_EQ("quit", ReadMessage(h));
    289   WriteMessage(h, "ok");
    290 }
    291 
    292 #if defined(OS_ANDROID)
    293 // Android multi-process tests are not executing the new process. This is flaky.
    294 #define MAYBE_CreateAndPassFromChildReadOnlyBuffer \
    295   DISABLED_CreateAndPassFromChildReadOnlyBuffer
    296 #else
    297 #define MAYBE_CreateAndPassFromChildReadOnlyBuffer \
    298   CreateAndPassFromChildReadOnlyBuffer
    299 #endif
    300 TEST_F(SharedBufferTest, MAYBE_CreateAndPassFromChildReadOnlyBuffer) {
    301   RunTestClient("CreateAndPassReadOnlyBuffer", [&](MojoHandle h) {
    302     MojoHandle b;
    303     EXPECT_EQ("", ReadMessageWithHandles(h, &b, 1));
    304     ExpectBufferContents(b, 0, "hello");
    305 
    306     // Extract the shared memory handle and verify that it is read-only.
    307     auto* dispatcher = static_cast<SharedBufferDispatcher*>(
    308         Core::Get()->GetDispatcher(b).get());
    309     base::subtle::PlatformSharedMemoryRegion& region =
    310         dispatcher->GetRegionForTesting();
    311     EXPECT_EQ(region.GetMode(),
    312               base::subtle::PlatformSharedMemoryRegion::Mode::kReadOnly);
    313 
    314     WriteMessage(h, "quit");
    315     EXPECT_EQ("ok", ReadMessage(h));
    316   });
    317 }
    318 
    319 #endif  // !defined(OS_IOS)
    320 
    321 }  // namespace
    322 }  // namespace core
    323 }  // namespace mojo
    324