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