shared_buffer_unittest.cc 9.8 KB

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