• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST_F(SharedBufferTest,CreateSharedBuffer)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 
TEST_F(SharedBufferTest,DuplicateSharedBuffer)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 
TEST_F(SharedBufferTest,PassSharedBufferLocal)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.
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CopyToBufferClient,SharedBufferTest,h)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 
TEST_F(SharedBufferTest,PassSharedBufferCrossProcess)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.
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateBufferClient,SharedBufferTest,h)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 
TEST_F(SharedBufferTest,PassSharedBufferFromChild)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 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBuffer,SharedBufferTest,h)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 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBuffer,SharedBufferTest,h)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 
TEST_F(SharedBufferTest,PassSharedBufferFromChildToChild)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 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassBufferParent,SharedBufferTest,parent)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 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceiveAndEditBufferParent,SharedBufferTest,parent)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
TEST_F(SharedBufferTest,MAYBE_PassHandleBetweenCousins)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 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReadAndMapWriteSharedBuffer,SharedBufferTest,h)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
TEST_F(SharedBufferTest,MAYBE_CreateAndPassReadOnlyBuffer)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 
DEFINE_TEST_CLIENT_TEST_WITH_PIPE(CreateAndPassReadOnlyBuffer,SharedBufferTest,h)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
TEST_F(SharedBufferTest,MAYBE_CreateAndPassFromChildReadOnlyBuffer)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