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