| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 |
| 9 #include <string> | 10 #include <string> |
| 10 #include <utility> | 11 #include <utility> |
| 11 #include <vector> | 12 #include <vector> |
| 12 | 13 |
| 13 #include "base/bind.h" | 14 #include "base/containers/hash_tables.h" |
| 14 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
| 15 #include "base/files/file_util.h" | 16 #include "base/files/file_util.h" |
| 16 #include "base/files/scoped_file.h" | 17 #include "base/files/scoped_file.h" |
| 17 #include "base/files/scoped_temp_dir.h" | 18 #include "base/files/scoped_temp_dir.h" |
| 18 #include "base/location.h" | |
| 19 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/strings/string_split.h" |
| 20 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 21 #include "mojo/edk/embedder/embedder.h" | |
| 22 #include "mojo/edk/embedder/platform_channel_pair.h" | |
| 23 #include "mojo/edk/embedder/platform_shared_buffer.h" | |
| 24 #include "mojo/edk/embedder/scoped_platform_handle.h" | 22 #include "mojo/edk/embedder/scoped_platform_handle.h" |
| 25 #include "mojo/edk/system/dispatcher.h" | 23 #include "mojo/edk/system/handle_signals_state.h" |
| 26 #include "mojo/edk/system/message_pipe_test_utils.h" | |
| 27 #include "mojo/edk/system/platform_handle_dispatcher.h" | |
| 28 #include "mojo/edk/system/raw_channel.h" | |
| 29 #include "mojo/edk/system/shared_buffer_dispatcher.h" | |
| 30 #include "mojo/edk/system/test_utils.h" | 24 #include "mojo/edk/system/test_utils.h" |
| 25 #include "mojo/edk/test/mojo_test_base.h" |
| 31 #include "mojo/edk/test/test_utils.h" | 26 #include "mojo/edk/test/test_utils.h" |
| 27 #include "mojo/public/c/system/buffer.h" |
| 28 #include "mojo/public/c/system/functions.h" |
| 29 #include "mojo/public/c/system/types.h" |
| 32 #include "testing/gtest/include/gtest/gtest.h" | 30 #include "testing/gtest/include/gtest/gtest.h" |
| 33 | 31 |
| 34 | 32 |
| 35 namespace mojo { | 33 namespace mojo { |
| 36 namespace edk { | 34 namespace edk { |
| 37 namespace { | 35 namespace { |
| 38 | 36 |
| 39 class MultiprocessMessagePipeTest | 37 class MultiprocessMessagePipeTest : public test::MojoTestBase { |
| 40 : public test::MultiprocessMessagePipeTestBase {}; | 38 protected: |
| 39 // Convenience class for tests which will control command-driven children. |
| 40 // See the CommandDrivenClient definition below. |
| 41 class CommandDrivenClientController { |
| 42 public: |
| 43 explicit CommandDrivenClientController(MojoHandle h) : h_(h) {} |
| 44 |
| 45 void Send(const std::string& command) { |
| 46 WriteMessage(h_, command); |
| 47 EXPECT_EQ("ok", ReadMessage(h_)); |
| 48 } |
| 49 |
| 50 void SendHandle(const std::string& name, MojoHandle p) { |
| 51 WriteMessageWithHandles(h_, "take:" + name, &p, 1); |
| 52 EXPECT_EQ("ok", ReadMessage(h_)); |
| 53 } |
| 54 |
| 55 MojoHandle RetrieveHandle(const std::string& name) { |
| 56 WriteMessage(h_, "return:" + name); |
| 57 MojoHandle p; |
| 58 EXPECT_EQ("ok", ReadMessageWithHandles(h_, &p, 1)); |
| 59 return p; |
| 60 } |
| 61 |
| 62 void Exit() { WriteMessage(h_, "exit"); } |
| 63 |
| 64 private: |
| 65 MojoHandle h_; |
| 66 }; |
| 67 }; |
| 41 | 68 |
| 42 // For each message received, sends a reply message with the same contents | 69 // For each message received, sends a reply message with the same contents |
| 43 // repeated twice, until the other end is closed or it receives "quitquitquit" | 70 // repeated twice, until the other end is closed or it receives "quitquitquit" |
| 44 // (which it doesn't reply to). It'll return the number of messages received, | 71 // (which it doesn't reply to). It'll return the number of messages received, |
| 45 // not including any "quitquitquit" message, modulo 100. | 72 // not including any "quitquitquit" message, modulo 100. |
| 46 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) { | 73 DEFINE_TEST_CLIENT_WITH_PIPE(EchoEcho, MultiprocessMessagePipeTest, h) { |
| 47 ScopedPlatformHandle client_platform_handle = | |
| 48 std::move(test::MultiprocessTestHelper::client_platform_handle); | |
| 49 CHECK(client_platform_handle.is_valid()); | |
| 50 ScopedMessagePipeHandle mp = | |
| 51 CreateMessagePipe(std::move(client_platform_handle)); | |
| 52 | |
| 53 const std::string quitquitquit("quitquitquit"); | 74 const std::string quitquitquit("quitquitquit"); |
| 54 int rv = 0; | 75 int rv = 0; |
| 55 for (;; rv = (rv + 1) % 100) { | 76 for (;; rv = (rv + 1) % 100) { |
| 56 // Wait for our end of the message pipe to be readable. | 77 // Wait for our end of the message pipe to be readable. |
| 57 HandleSignalsState hss; | 78 HandleSignalsState hss; |
| 58 MojoResult result = | 79 MojoResult result = |
| 59 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 80 MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 60 MOJO_DEADLINE_INDEFINITE, &hss); | 81 MOJO_DEADLINE_INDEFINITE, &hss); |
| 61 if (result != MOJO_RESULT_OK) { | 82 if (result != MOJO_RESULT_OK) { |
| 62 // It was closed, probably. | 83 // It was closed, probably. |
| 63 CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION); | 84 CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION); |
| 64 CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 85 CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); |
| 65 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 86 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED); |
| 66 break; | 87 break; |
| 67 } else { | 88 } else { |
| 68 CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 89 CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 69 CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 90 CHECK((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 70 } | 91 } |
| 71 | 92 |
| 72 std::string read_buffer(1000, '\0'); | 93 std::string read_buffer(1000, '\0'); |
| 73 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 94 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |
| 74 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | 95 CHECK_EQ(MojoReadMessage(h, &read_buffer[0], |
| 75 &read_buffer_size, nullptr, | 96 &read_buffer_size, nullptr, |
| 76 0, MOJO_READ_MESSAGE_FLAG_NONE), | 97 0, MOJO_READ_MESSAGE_FLAG_NONE), |
| 77 MOJO_RESULT_OK); | 98 MOJO_RESULT_OK); |
| 78 read_buffer.resize(read_buffer_size); | 99 read_buffer.resize(read_buffer_size); |
| 79 VLOG(2) << "Child got: " << read_buffer; | 100 VLOG(2) << "Child got: " << read_buffer; |
| 80 | 101 |
| 81 if (read_buffer == quitquitquit) { | 102 if (read_buffer == quitquitquit) { |
| 82 VLOG(2) << "Child quitting."; | 103 VLOG(2) << "Child quitting."; |
| 83 break; | 104 break; |
| 84 } | 105 } |
| 85 | 106 |
| 86 std::string write_buffer = read_buffer + read_buffer; | 107 std::string write_buffer = read_buffer + read_buffer; |
| 87 CHECK_EQ(MojoWriteMessage(mp.get().value(), write_buffer.data(), | 108 CHECK_EQ(MojoWriteMessage(h, write_buffer.data(), |
| 88 static_cast<uint32_t>(write_buffer.size()), | 109 static_cast<uint32_t>(write_buffer.size()), |
| 89 nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), | 110 nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), |
| 90 MOJO_RESULT_OK); | 111 MOJO_RESULT_OK); |
| 91 } | 112 } |
| 92 | 113 |
| 93 return rv; | 114 return rv; |
| 94 } | 115 } |
| 95 | 116 |
| 96 // Sends "hello" to child, and expects "hellohello" back. | 117 // Sends "hello" to child, and expects "hellohello" back. |
| 97 #if defined(OS_ANDROID) | 118 #if defined(OS_ANDROID) |
| 98 // Android multi-process tests are not executing the new process. This is flaky. | 119 // Android multi-process tests are not executing the new process. This is flaky. |
| 99 #define MAYBE_Basic DISABLED_Basic | 120 #define MAYBE_Basic DISABLED_Basic |
| 100 #else | 121 #else |
| 101 #define MAYBE_Basic Basic | 122 #define MAYBE_Basic Basic |
| 102 #endif // defined(OS_ANDROID) | 123 #endif // defined(OS_ANDROID) |
| 103 TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { | 124 TEST_F(MultiprocessMessagePipeTest, MAYBE_Basic) { |
| 104 helper()->StartChild("EchoEcho"); | 125 RUN_CHILD_ON_PIPE(EchoEcho, h) |
| 126 std::string hello("hello"); |
| 127 ASSERT_EQ(MOJO_RESULT_OK, |
| 128 MojoWriteMessage(h, hello.data(), |
| 129 static_cast<uint32_t>(hello.size()), nullptr, 0u, |
| 130 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 105 | 131 |
| 106 ScopedMessagePipeHandle mp = | 132 HandleSignalsState hss; |
| 107 CreateMessagePipe(std::move(helper()->server_platform_handle)); | 133 ASSERT_EQ(MOJO_RESULT_OK, |
| 134 MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 135 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 136 // The child may or may not have closed its end of the message pipe and died |
| 137 // (and we may or may not know it yet), so our end may or may not appear as |
| 138 // writable. |
| 139 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 140 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 108 | 141 |
| 109 std::string hello("hello"); | 142 std::string read_buffer(1000, '\0'); |
| 110 ASSERT_EQ(MOJO_RESULT_OK, | 143 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |
| 111 MojoWriteMessage(mp.get().value(), hello.data(), | 144 CHECK_EQ(MojoReadMessage(h, &read_buffer[0], |
| 112 static_cast<uint32_t>(hello.size()), nullptr, 0u, | 145 &read_buffer_size, nullptr, 0, |
| 113 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 146 MOJO_READ_MESSAGE_FLAG_NONE), |
| 147 MOJO_RESULT_OK); |
| 148 read_buffer.resize(read_buffer_size); |
| 149 VLOG(2) << "Parent got: " << read_buffer; |
| 150 ASSERT_EQ(hello + hello, read_buffer); |
| 114 | 151 |
| 115 HandleSignalsState hss; | 152 std::string quitquitquit("quitquitquit"); |
| 116 ASSERT_EQ(MOJO_RESULT_OK, | 153 CHECK_EQ(MojoWriteMessage(h, quitquitquit.data(), |
| 117 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 154 static_cast<uint32_t>(quitquitquit.size()), |
| 118 MOJO_DEADLINE_INDEFINITE, &hss)); | 155 nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE), |
| 119 // The child may or may not have closed its end of the message pipe and died | 156 MOJO_RESULT_OK); |
| 120 // (and we may or may not know it yet), so our end may or may not appear as | 157 END_CHILD_AND_EXPECT_EXIT_CODE(1 % 100); |
| 121 // writable. | |
| 122 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
| 123 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
| 124 | |
| 125 std::string read_buffer(1000, '\0'); | |
| 126 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
| 127 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | |
| 128 &read_buffer_size, nullptr, 0, | |
| 129 MOJO_READ_MESSAGE_FLAG_NONE), | |
| 130 MOJO_RESULT_OK); | |
| 131 read_buffer.resize(read_buffer_size); | |
| 132 VLOG(2) << "Parent got: " << read_buffer; | |
| 133 ASSERT_EQ(hello + hello, read_buffer); | |
| 134 | |
| 135 MojoClose(mp.release().value()); | |
| 136 | |
| 137 // We sent one message. | |
| 138 ASSERT_EQ(1 % 100, helper()->WaitForChildShutdown()); | |
| 139 } | 158 } |
| 140 | 159 |
| 141 // Sends a bunch of messages to the child. Expects them "repeated" back. Waits | 160 // Sends a bunch of messages to the child. Expects them "repeated" back. Waits |
| 142 // for the child to close its end before quitting. | 161 // for the child to close its end before quitting. |
| 143 #if defined(OS_ANDROID) | 162 #if defined(OS_ANDROID) |
| 144 // Android multi-process tests are not executing the new process. This is flaky. | 163 // Android multi-process tests are not executing the new process. This is flaky. |
| 145 #define MAYBE_QueueMessages DISABLED_QueueMessages | 164 #define MAYBE_QueueMessages DISABLED_QueueMessages |
| 146 #else | 165 #else |
| 147 #define MAYBE_QueueMessages QueueMessages | 166 #define MAYBE_QueueMessages QueueMessages |
| 148 #endif // defined(OS_ANDROID) | 167 #endif // defined(OS_ANDROID) |
| 149 TEST_F(MultiprocessMessagePipeTest, MAYBE_QueueMessages) { | 168 TEST_F(MultiprocessMessagePipeTest, MAYBE_QueueMessages) { |
| 150 helper()->StartChild("EchoEcho"); | 169 static const size_t kNumMessages = 1001; |
| 170 RUN_CHILD_ON_PIPE(EchoEcho, h) |
| 171 for (size_t i = 0; i < kNumMessages; i++) { |
| 172 std::string write_buffer(i, 'A' + (i % 26)); |
| 173 ASSERT_EQ(MOJO_RESULT_OK, |
| 174 MojoWriteMessage(h, write_buffer.data(), |
| 175 static_cast<uint32_t>(write_buffer.size()), |
| 176 nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 177 } |
| 151 | 178 |
| 152 ScopedMessagePipeHandle mp = | 179 for (size_t i = 0; i < kNumMessages; i++) { |
| 153 CreateMessagePipe(std::move(helper()->server_platform_handle)); | 180 HandleSignalsState hss; |
| 181 ASSERT_EQ(MOJO_RESULT_OK, |
| 182 MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 183 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 184 // The child may or may not have closed its end of the message pipe and |
| 185 // died (and we may or may not know it yet), so our end may or may not |
| 186 // appear as writable. |
| 187 ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 188 ASSERT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 154 | 189 |
| 155 static const size_t kNumMessages = 1001; | 190 std::string read_buffer(kNumMessages * 2, '\0'); |
| 156 for (size_t i = 0; i < kNumMessages; i++) { | 191 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |
| 157 std::string write_buffer(i, 'A' + (i % 26)); | 192 ASSERT_EQ(MojoReadMessage(h, &read_buffer[0], |
| 193 &read_buffer_size, nullptr, 0, |
| 194 MOJO_READ_MESSAGE_FLAG_NONE), |
| 195 MOJO_RESULT_OK); |
| 196 read_buffer.resize(read_buffer_size); |
| 197 |
| 198 ASSERT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); |
| 199 } |
| 200 |
| 201 const std::string quitquitquit("quitquitquit"); |
| 158 ASSERT_EQ(MOJO_RESULT_OK, | 202 ASSERT_EQ(MOJO_RESULT_OK, |
| 159 MojoWriteMessage(mp.get().value(), write_buffer.data(), | 203 MojoWriteMessage(h, quitquitquit.data(), |
| 160 static_cast<uint32_t>(write_buffer.size()), | 204 static_cast<uint32_t>(quitquitquit.size()), |
| 161 nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); | 205 nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 162 } | |
| 163 | 206 |
| 164 for (size_t i = 0; i < kNumMessages; i++) { | 207 // Wait for it to become readable, which should fail (since we sent |
| 208 // "quitquitquit"). |
| 165 HandleSignalsState hss; | 209 HandleSignalsState hss; |
| 166 ASSERT_EQ(MOJO_RESULT_OK, | 210 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| 167 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 211 MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 168 MOJO_DEADLINE_INDEFINITE, &hss)); | 212 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 169 // The child may or may not have closed its end of the message pipe and died | 213 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |
| 170 // (and we may or may not know it yet), so our end may or may not appear as | 214 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |
| 171 // writable. | 215 END_CHILD_AND_EXPECT_EXIT_CODE(static_cast<int>(kNumMessages % 100)); |
| 172 ASSERT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
| 173 ASSERT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
| 174 | |
| 175 std::string read_buffer(kNumMessages * 2, '\0'); | |
| 176 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
| 177 ASSERT_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | |
| 178 &read_buffer_size, nullptr, 0, | |
| 179 MOJO_READ_MESSAGE_FLAG_NONE), | |
| 180 MOJO_RESULT_OK); | |
| 181 read_buffer.resize(read_buffer_size); | |
| 182 | |
| 183 ASSERT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); | |
| 184 } | |
| 185 | |
| 186 const std::string quitquitquit("quitquitquit"); | |
| 187 ASSERT_EQ(MOJO_RESULT_OK, | |
| 188 MojoWriteMessage(mp.get().value(), quitquitquit.data(), | |
| 189 static_cast<uint32_t>(quitquitquit.size()), | |
| 190 nullptr, 0u, MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 191 | |
| 192 // Wait for it to become readable, which should fail (since we sent | |
| 193 // "quitquitquit"). | |
| 194 HandleSignalsState hss; | |
| 195 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
| 196 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
| 197 MOJO_DEADLINE_INDEFINITE, &hss)); | |
| 198 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
| 199 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
| 200 | |
| 201 ASSERT_EQ(static_cast<int>(kNumMessages % 100), | |
| 202 helper()->WaitForChildShutdown()); | |
| 203 } | 216 } |
| 204 | 217 |
| 205 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { | 218 DEFINE_TEST_CLIENT_WITH_PIPE(CheckSharedBuffer, MultiprocessMessagePipeTest, |
| 206 ScopedPlatformHandle client_platform_handle = | 219 h) { |
| 207 std::move(test::MultiprocessTestHelper::client_platform_handle); | |
| 208 CHECK(client_platform_handle.is_valid()); | |
| 209 ScopedMessagePipeHandle mp = | |
| 210 CreateMessagePipe(std::move(client_platform_handle)); | |
| 211 | |
| 212 // Wait for the first message from our parent. | 220 // Wait for the first message from our parent. |
| 213 HandleSignalsState hss; | 221 HandleSignalsState hss; |
| 214 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 222 CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 215 MOJO_DEADLINE_INDEFINITE, &hss), | 223 MOJO_DEADLINE_INDEFINITE, &hss), |
| 216 MOJO_RESULT_OK); | 224 MOJO_RESULT_OK); |
| 217 // In this test, the parent definitely doesn't close its end of the message | 225 // In this test, the parent definitely doesn't close its end of the message |
| 218 // pipe before we do. | 226 // pipe before we do. |
| 219 CHECK_EQ(hss.satisfied_signals, | 227 CHECK_EQ(hss.satisfied_signals, |
| 220 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 228 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |
| 221 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 229 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |
| 222 MOJO_HANDLE_SIGNAL_WRITABLE | | 230 MOJO_HANDLE_SIGNAL_WRITABLE | |
| 223 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 231 MOJO_HANDLE_SIGNAL_PEER_CLOSED); |
| 224 | 232 |
| 225 // It should have a shared buffer. | 233 // It should have a shared buffer. |
| 226 std::string read_buffer(100, '\0'); | 234 std::string read_buffer(100, '\0'); |
| 227 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | 235 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |
| 228 MojoHandle handles[10]; | 236 MojoHandle handles[10]; |
| 229 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); // Maximum number to receive | 237 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); // Maximum number to receive |
| 230 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | 238 CHECK_EQ(MojoReadMessage(h, &read_buffer[0], |
| 231 &num_bytes, &handles[0], | 239 &num_bytes, &handles[0], |
| 232 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | 240 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), |
| 233 MOJO_RESULT_OK); | 241 MOJO_RESULT_OK); |
| 234 read_buffer.resize(num_bytes); | 242 read_buffer.resize(num_bytes); |
| 235 CHECK_EQ(read_buffer, std::string("go 1")); | 243 CHECK_EQ(read_buffer, std::string("go 1")); |
| 236 CHECK_EQ(num_handlers, 1u); | 244 CHECK_EQ(num_handlers, 1u); |
| 237 | 245 |
| 238 // Make a mapping. | 246 // Make a mapping. |
| 239 void* buffer; | 247 void* buffer; |
| 240 CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, &buffer, | 248 CHECK_EQ(MojoMapBuffer(handles[0], 0, 100, &buffer, |
| 241 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), | 249 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), |
| 242 MOJO_RESULT_OK); | 250 MOJO_RESULT_OK); |
| 243 | 251 |
| 244 // Write some stuff to the shared buffer. | 252 // Write some stuff to the shared buffer. |
| 245 static const char kHello[] = "hello"; | 253 static const char kHello[] = "hello"; |
| 246 memcpy(buffer, kHello, sizeof(kHello)); | 254 memcpy(buffer, kHello, sizeof(kHello)); |
| 247 | 255 |
| 248 // We should be able to close the dispatcher now. | 256 // We should be able to close the dispatcher now. |
| 249 MojoClose(handles[0]); | 257 MojoClose(handles[0]); |
| 250 | 258 |
| 251 // And send a message to signal that we've written stuff. | 259 // And send a message to signal that we've written stuff. |
| 252 const std::string go2("go 2"); | 260 const std::string go2("go 2"); |
| 253 CHECK_EQ(MojoWriteMessage(mp.get().value(), go2.data(), | 261 CHECK_EQ(MojoWriteMessage(h, go2.data(), |
| 254 static_cast<uint32_t>(go2.size()), nullptr, 0u, | 262 static_cast<uint32_t>(go2.size()), nullptr, 0u, |
| 255 MOJO_WRITE_MESSAGE_FLAG_NONE), | 263 MOJO_WRITE_MESSAGE_FLAG_NONE), |
| 256 MOJO_RESULT_OK); | 264 MOJO_RESULT_OK); |
| 257 | 265 |
| 258 // Now wait for our parent to send us a message. | 266 // Now wait for our parent to send us a message. |
| 259 hss = HandleSignalsState(); | 267 hss = HandleSignalsState(); |
| 260 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 268 CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 261 MOJO_DEADLINE_INDEFINITE, &hss), | 269 MOJO_DEADLINE_INDEFINITE, &hss), |
| 262 MOJO_RESULT_OK); | 270 MOJO_RESULT_OK); |
| 263 CHECK_EQ(hss.satisfied_signals, | 271 CHECK_EQ(hss.satisfied_signals, |
| 264 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 272 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |
| 265 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 273 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |
| 266 MOJO_HANDLE_SIGNAL_WRITABLE | | 274 MOJO_HANDLE_SIGNAL_WRITABLE | |
| 267 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 275 MOJO_HANDLE_SIGNAL_PEER_CLOSED); |
| 268 | 276 |
| 269 read_buffer = std::string(100, '\0'); | 277 read_buffer = std::string(100, '\0'); |
| 270 num_bytes = static_cast<uint32_t>(read_buffer.size()); | 278 num_bytes = static_cast<uint32_t>(read_buffer.size()); |
| 271 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], &num_bytes, | 279 CHECK_EQ(MojoReadMessage(h, &read_buffer[0], &num_bytes, |
| 272 nullptr, 0, MOJO_READ_MESSAGE_FLAG_NONE), | 280 nullptr, 0, MOJO_READ_MESSAGE_FLAG_NONE), |
| 273 MOJO_RESULT_OK); | 281 MOJO_RESULT_OK); |
| 274 read_buffer.resize(num_bytes); | 282 read_buffer.resize(num_bytes); |
| 275 CHECK_EQ(read_buffer, std::string("go 3")); | 283 CHECK_EQ(read_buffer, std::string("go 3")); |
| 276 | 284 |
| 277 // It should have written something to the shared buffer. | 285 // It should have written something to the shared buffer. |
| 278 static const char kWorld[] = "world!!!"; | 286 static const char kWorld[] = "world!!!"; |
| 279 CHECK_EQ(memcmp(buffer, kWorld, sizeof(kWorld)), 0); | 287 CHECK_EQ(memcmp(buffer, kWorld, sizeof(kWorld)), 0); |
| 280 | 288 |
| 281 // And we're done. | 289 // And we're done. |
| 282 | 290 |
| 283 return 0; | 291 return 0; |
| 284 } | 292 } |
| 285 | 293 |
| 286 #if defined(OS_ANDROID) | 294 #if defined(OS_ANDROID) |
| 287 // Android multi-process tests are not executing the new process. This is flaky. | 295 // Android multi-process tests are not executing the new process. This is flaky. |
| 288 #define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing | 296 #define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing |
| 289 #else | 297 #else |
| 290 #define MAYBE_SharedBufferPassing SharedBufferPassing | 298 #define MAYBE_SharedBufferPassing SharedBufferPassing |
| 291 #endif | 299 #endif |
| 292 TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { | 300 TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { |
| 293 helper()->StartChild("CheckSharedBuffer"); | 301 RUN_CHILD_ON_PIPE(CheckSharedBuffer, h) |
| 302 // Make a shared buffer. |
| 303 MojoCreateSharedBufferOptions options; |
| 304 options.struct_size = sizeof(options); |
| 305 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; |
| 294 | 306 |
| 295 ScopedMessagePipeHandle mp = | 307 MojoHandle shared_buffer; |
| 296 CreateMessagePipe(std::move(helper()->server_platform_handle)); | 308 ASSERT_EQ(MOJO_RESULT_OK, |
| 309 MojoCreateSharedBuffer(&options, 100, &shared_buffer)); |
| 297 | 310 |
| 298 // Make a shared buffer. | 311 // Send the shared buffer. |
| 299 MojoCreateSharedBufferOptions options; | 312 const std::string go1("go 1"); |
| 300 options.struct_size = sizeof(options); | |
| 301 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | |
| 302 | 313 |
| 303 MojoHandle shared_buffer; | 314 MojoHandle duplicated_shared_buffer; |
| 304 ASSERT_EQ(MOJO_RESULT_OK, | 315 ASSERT_EQ(MOJO_RESULT_OK, |
| 305 MojoCreateSharedBuffer(&options, 100, &shared_buffer)); | 316 MojoDuplicateBufferHandle( |
| 317 shared_buffer, |
| 318 nullptr, |
| 319 &duplicated_shared_buffer)); |
| 320 MojoHandle handles[1]; |
| 321 handles[0] = duplicated_shared_buffer; |
| 322 ASSERT_EQ(MOJO_RESULT_OK, |
| 323 MojoWriteMessage(h, &go1[0], |
| 324 static_cast<uint32_t>(go1.size()), &handles[0], |
| 325 MOJO_ARRAYSIZE(handles), |
| 326 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 306 | 327 |
| 307 // Send the shared buffer. | 328 // Wait for a message from the child. |
| 308 const std::string go1("go 1"); | 329 HandleSignalsState hss; |
| 330 ASSERT_EQ(MOJO_RESULT_OK, |
| 331 MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 332 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 333 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 334 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 309 | 335 |
| 310 MojoHandle duplicated_shared_buffer; | 336 std::string read_buffer(100, '\0'); |
| 311 ASSERT_EQ(MOJO_RESULT_OK, | 337 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |
| 312 MojoDuplicateBufferHandle( | 338 ASSERT_EQ(MOJO_RESULT_OK, |
| 313 shared_buffer, | 339 MojoReadMessage(h, &read_buffer[0], |
| 314 nullptr, | 340 &num_bytes, nullptr, 0, |
| 315 &duplicated_shared_buffer)); | 341 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 316 MojoHandle handles[1]; | 342 read_buffer.resize(num_bytes); |
| 317 handles[0] = duplicated_shared_buffer; | 343 ASSERT_EQ(std::string("go 2"), read_buffer); |
| 318 ASSERT_EQ(MOJO_RESULT_OK, | |
| 319 MojoWriteMessage(mp.get().value(), &go1[0], | |
| 320 static_cast<uint32_t>(go1.size()), &handles[0], | |
| 321 MOJO_ARRAYSIZE(handles), | |
| 322 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 323 | 344 |
| 324 // Wait for a message from the child. | 345 // After we get it, the child should have written something to the shared |
| 325 HandleSignalsState hss; | 346 // buffer. |
| 326 ASSERT_EQ(MOJO_RESULT_OK, | 347 static const char kHello[] = "hello"; |
| 327 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 348 void* buffer; |
| 328 MOJO_DEADLINE_INDEFINITE, &hss)); | 349 CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, &buffer, |
| 329 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 350 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), |
| 330 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 351 MOJO_RESULT_OK); |
| 352 ASSERT_EQ(0, memcmp(buffer, kHello, sizeof(kHello))); |
| 331 | 353 |
| 332 std::string read_buffer(100, '\0'); | 354 // Now we'll write some stuff to the shared buffer. |
| 333 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | 355 static const char kWorld[] = "world!!!"; |
| 334 ASSERT_EQ(MOJO_RESULT_OK, | 356 memcpy(buffer, kWorld, sizeof(kWorld)); |
| 335 MojoReadMessage(mp.get().value(), &read_buffer[0], | |
| 336 &num_bytes, nullptr, 0, | |
| 337 MOJO_READ_MESSAGE_FLAG_NONE)); | |
| 338 read_buffer.resize(num_bytes); | |
| 339 ASSERT_EQ(std::string("go 2"), read_buffer); | |
| 340 | 357 |
| 341 // After we get it, the child should have written something to the shared | 358 // And send a message to signal that we've written stuff. |
| 342 // buffer. | 359 const std::string go3("go 3"); |
| 343 static const char kHello[] = "hello"; | 360 ASSERT_EQ(MOJO_RESULT_OK, |
| 344 void* buffer; | 361 MojoWriteMessage(h, &go3[0], |
| 345 CHECK_EQ(MojoMapBuffer(shared_buffer, 0, 100, &buffer, | 362 static_cast<uint32_t>(go3.size()), nullptr, 0u, |
| 346 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE), | 363 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 347 MOJO_RESULT_OK); | |
| 348 ASSERT_EQ(0, memcmp(buffer, kHello, sizeof(kHello))); | |
| 349 | 364 |
| 350 // Now we'll write some stuff to the shared buffer. | 365 // Wait for |h| to become readable, which should fail. |
| 351 static const char kWorld[] = "world!!!"; | 366 hss = HandleSignalsState(); |
| 352 memcpy(buffer, kWorld, sizeof(kWorld)); | 367 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| 353 | 368 MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 354 // And send a message to signal that we've written stuff. | 369 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 355 const std::string go3("go 3"); | 370 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |
| 356 ASSERT_EQ(MOJO_RESULT_OK, | 371 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |
| 357 MojoWriteMessage(mp.get().value(), &go3[0], | 372 END_CHILD() |
| 358 static_cast<uint32_t>(go3.size()), nullptr, 0u, | |
| 359 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 360 | |
| 361 // Wait for |mp| to become readable, which should fail. | |
| 362 hss = HandleSignalsState(); | |
| 363 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
| 364 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
| 365 MOJO_DEADLINE_INDEFINITE, &hss)); | |
| 366 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
| 367 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
| 368 | |
| 369 MojoClose(mp.release().value()); | |
| 370 | |
| 371 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
| 372 } | 373 } |
| 373 | 374 |
| 374 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { | 375 DEFINE_TEST_CLIENT_WITH_PIPE(CheckPlatformHandleFile, |
| 375 ScopedPlatformHandle client_platform_handle = | 376 MultiprocessMessagePipeTest, h) { |
| 376 std::move(test::MultiprocessTestHelper::client_platform_handle); | |
| 377 CHECK(client_platform_handle.is_valid()); | |
| 378 ScopedMessagePipeHandle mp = | |
| 379 CreateMessagePipe(std::move(client_platform_handle)); | |
| 380 | |
| 381 HandleSignalsState hss; | 377 HandleSignalsState hss; |
| 382 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 378 CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 383 MOJO_DEADLINE_INDEFINITE, &hss), | 379 MOJO_DEADLINE_INDEFINITE, &hss), |
| 384 MOJO_RESULT_OK); | 380 MOJO_RESULT_OK); |
| 385 CHECK_EQ(hss.satisfied_signals, | 381 CHECK_EQ(hss.satisfied_signals, |
| 386 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 382 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |
| 387 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 383 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |
| 388 MOJO_HANDLE_SIGNAL_WRITABLE | | 384 MOJO_HANDLE_SIGNAL_WRITABLE | |
| 389 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 385 MOJO_HANDLE_SIGNAL_PEER_CLOSED); |
| 390 | 386 |
| 391 std::string read_buffer(100, '\0'); | 387 std::string read_buffer(100, '\0'); |
| 392 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); | 388 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |
| 393 MojoHandle handles[255]; // Maximum number to receive. | 389 MojoHandle handles[255]; // Maximum number to receive. |
| 394 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | 390 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); |
| 395 | 391 |
| 396 CHECK_EQ(MojoReadMessage(mp.get().value(), &read_buffer[0], | 392 CHECK_EQ(MojoReadMessage(h, &read_buffer[0], |
| 397 &num_bytes, &handles[0], | 393 &num_bytes, &handles[0], |
| 398 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | 394 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), |
| 399 MOJO_RESULT_OK); | 395 MOJO_RESULT_OK); |
| 400 MojoClose(mp.release().value()); | |
| 401 | 396 |
| 402 read_buffer.resize(num_bytes); | 397 read_buffer.resize(num_bytes); |
| 403 char hello[32]; | 398 char hello[32]; |
| 404 int num_handles = 0; | 399 int num_handles = 0; |
| 405 sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles); | 400 sscanf(read_buffer.c_str(), "%s %d", hello, &num_handles); |
| 406 CHECK_EQ(std::string("hello"), std::string(hello)); | 401 CHECK_EQ(std::string("hello"), std::string(hello)); |
| 407 CHECK_GT(num_handles, 0); | 402 CHECK_GT(num_handles, 0); |
| 408 | 403 |
| 409 for (int i = 0; i < num_handles; ++i) { | 404 for (int i = 0; i < num_handles; ++i) { |
| 410 ScopedPlatformHandle h; | 405 ScopedPlatformHandle h; |
| 411 CHECK_EQ(PassWrappedPlatformHandle( | 406 CHECK_EQ(PassWrappedPlatformHandle(handles[i], &h), MOJO_RESULT_OK); |
| 412 handles[i], &h), | |
| 413 MOJO_RESULT_OK); | |
| 414 CHECK(h.is_valid()); | 407 CHECK(h.is_valid()); |
| 415 MojoClose(handles[i]); | 408 MojoClose(handles[i]); |
| 416 | 409 |
| 417 base::ScopedFILE fp(test::FILEFromPlatformHandle(std::move(h), "r")); | 410 base::ScopedFILE fp(test::FILEFromPlatformHandle(std::move(h), "r")); |
| 418 CHECK(fp); | 411 CHECK(fp); |
| 419 std::string fread_buffer(100, '\0'); | 412 std::string fread_buffer(100, '\0'); |
| 420 size_t bytes_read = | 413 size_t bytes_read = |
| 421 fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get()); | 414 fread(&fread_buffer[0], 1, fread_buffer.size(), fp.get()); |
| 422 fread_buffer.resize(bytes_read); | 415 fread_buffer.resize(bytes_read); |
| 423 CHECK_EQ(fread_buffer, "world"); | 416 CHECK_EQ(fread_buffer, "world"); |
| 424 } | 417 } |
| 425 | 418 |
| 426 return 0; | 419 return 0; |
| 427 } | 420 } |
| 428 | 421 |
| 429 class MultiprocessMessagePipeTestWithPipeCount | 422 class MultiprocessMessagePipeTestWithPipeCount |
| 430 : public test::MultiprocessMessagePipeTestBase, | 423 : public MultiprocessMessagePipeTest, |
| 431 public testing::WithParamInterface<size_t> {}; | 424 public testing::WithParamInterface<size_t> {}; |
| 432 | 425 |
| 433 TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { | 426 TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) { |
| 434 base::ScopedTempDir temp_dir; | 427 base::ScopedTempDir temp_dir; |
| 435 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 428 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 436 | 429 |
| 437 helper()->StartChild("CheckPlatformHandleFile"); | 430 RUN_CHILD_ON_PIPE(CheckPlatformHandleFile, h) |
| 438 ScopedMessagePipeHandle mp = | 431 std::vector<MojoHandle> handles; |
| 439 CreateMessagePipe(std::move(helper()->server_platform_handle)); | |
| 440 | 432 |
| 441 std::vector<MojoHandle> handles; | 433 size_t pipe_count = GetParam(); |
| 434 for (size_t i = 0; i < pipe_count; ++i) { |
| 435 base::FilePath unused; |
| 436 base::ScopedFILE fp( |
| 437 CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); |
| 438 const std::string world("world"); |
| 439 CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size()); |
| 440 fflush(fp.get()); |
| 441 rewind(fp.get()); |
| 442 MojoHandle handle; |
| 443 ASSERT_EQ( |
| 444 CreatePlatformHandleWrapper( |
| 445 ScopedPlatformHandle(test::PlatformHandleFromFILE(std::move(fp))), |
| 446 &handle), |
| 447 MOJO_RESULT_OK); |
| 448 handles.push_back(handle); |
| 449 } |
| 442 | 450 |
| 443 size_t pipe_count = GetParam(); | 451 char message[128]; |
| 444 for (size_t i = 0; i < pipe_count; ++i) { | 452 sprintf(message, "hello %d", static_cast<int>(pipe_count)); |
| 445 base::FilePath unused; | 453 ASSERT_EQ(MOJO_RESULT_OK, |
| 446 base::ScopedFILE fp( | 454 MojoWriteMessage(h, message, |
| 447 CreateAndOpenTemporaryFileInDir(temp_dir.path(), &unused)); | 455 static_cast<uint32_t>(strlen(message)), |
| 448 const std::string world("world"); | 456 &handles[0], |
| 449 CHECK_EQ(fwrite(&world[0], 1, world.size(), fp.get()), world.size()); | 457 static_cast<uint32_t>(handles.size()), |
| 450 fflush(fp.get()); | 458 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 451 rewind(fp.get()); | |
| 452 MojoHandle handle; | |
| 453 ASSERT_EQ( | |
| 454 CreatePlatformHandleWrapper( | |
| 455 ScopedPlatformHandle(test::PlatformHandleFromFILE(std::move(fp))), | |
| 456 &handle), | |
| 457 MOJO_RESULT_OK); | |
| 458 handles.push_back(handle); | |
| 459 } | |
| 460 | 459 |
| 461 char message[128]; | 460 // Wait for it to become readable, which should fail. |
| 462 sprintf(message, "hello %d", static_cast<int>(pipe_count)); | 461 HandleSignalsState hss; |
| 463 ASSERT_EQ(MOJO_RESULT_OK, | 462 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| 464 MojoWriteMessage(mp.get().value(), message, | 463 MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 465 static_cast<uint32_t>(strlen(message)), | 464 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 466 &handles[0], static_cast<uint32_t>(handles.size()), | 465 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); |
| 467 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 466 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); |
| 468 | 467 END_CHILD() |
| 469 // Wait for it to become readable, which should fail. | |
| 470 HandleSignalsState hss; | |
| 471 ASSERT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
| 472 MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
| 473 MOJO_DEADLINE_INDEFINITE, &hss)); | |
| 474 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); | |
| 475 ASSERT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); | |
| 476 | |
| 477 MojoClose(mp.release().value()); | |
| 478 | |
| 479 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
| 480 } | 468 } |
| 481 | 469 |
| 482 // Android multi-process tests are not executing the new process. This is flaky. | 470 // Android multi-process tests are not executing the new process. This is flaky. |
| 483 #if !defined(OS_ANDROID) | 471 #if !defined(OS_ANDROID) |
| 484 INSTANTIATE_TEST_CASE_P(PipeCount, | 472 INSTANTIATE_TEST_CASE_P(PipeCount, |
| 485 MultiprocessMessagePipeTestWithPipeCount, | 473 MultiprocessMessagePipeTestWithPipeCount, |
| 486 testing::Values(1u, 128u, 140u)); | 474 // TODO: Re-enable the 140-pipe case when ChannelPosix |
| 475 // has support for sending lots of handles. |
| 476 testing::Values(1u, 128u/*, 140u*/)); |
| 487 #endif | 477 #endif |
| 488 | 478 |
| 489 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckMessagePipe) { | 479 DEFINE_TEST_CLIENT_WITH_PIPE(CheckMessagePipe, MultiprocessMessagePipeTest, h) { |
| 490 ScopedPlatformHandle client_platform_handle = | |
| 491 std::move(test::MultiprocessTestHelper::client_platform_handle); | |
| 492 CHECK(client_platform_handle.is_valid()); | |
| 493 | |
| 494 ScopedMessagePipeHandle mp = | |
| 495 CreateMessagePipe(std::move(client_platform_handle)); | |
| 496 | |
| 497 // Wait for the first message from our parent. | 480 // Wait for the first message from our parent. |
| 498 HandleSignalsState hss; | 481 HandleSignalsState hss; |
| 499 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 482 CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 500 MOJO_DEADLINE_INDEFINITE, &hss), | 483 MOJO_DEADLINE_INDEFINITE, &hss), |
| 501 MOJO_RESULT_OK); | 484 MOJO_RESULT_OK); |
| 502 // In this test, the parent definitely doesn't close its end of the message | 485 // In this test, the parent definitely doesn't close its end of the message |
| 503 // pipe before we do. | 486 // pipe before we do. |
| 504 CHECK_EQ(hss.satisfied_signals, | 487 CHECK_EQ(hss.satisfied_signals, |
| 505 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 488 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |
| 506 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 489 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |
| 507 MOJO_HANDLE_SIGNAL_WRITABLE | | 490 MOJO_HANDLE_SIGNAL_WRITABLE | |
| 508 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 491 MOJO_HANDLE_SIGNAL_PEER_CLOSED); |
| 509 | 492 |
| 510 // It should have a message pipe. | 493 // It should have a message pipe. |
| 511 MojoHandle handles[10]; | 494 MojoHandle handles[10]; |
| 512 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | 495 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); |
| 513 CHECK_EQ(MojoReadMessage(mp.get().value(), nullptr, | 496 CHECK_EQ(MojoReadMessage(h, nullptr, |
| 514 nullptr, &handles[0], | 497 nullptr, &handles[0], |
| 515 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | 498 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), |
| 516 MOJO_RESULT_OK); | 499 MOJO_RESULT_OK); |
| 517 CHECK_EQ(num_handlers, 1u); | 500 CHECK_EQ(num_handlers, 1u); |
| 518 | 501 |
| 519 // Read data from the received message pipe. | 502 // Read data from the received message pipe. |
| 520 CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, | 503 CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, |
| 521 MOJO_DEADLINE_INDEFINITE, &hss), | 504 MOJO_DEADLINE_INDEFINITE, &hss), |
| 522 MOJO_RESULT_OK); | 505 MOJO_RESULT_OK); |
| 523 CHECK_EQ(hss.satisfied_signals, | 506 CHECK_EQ(hss.satisfied_signals, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 545 return 0; | 528 return 0; |
| 546 } | 529 } |
| 547 | 530 |
| 548 #if defined(OS_ANDROID) | 531 #if defined(OS_ANDROID) |
| 549 // Android multi-process tests are not executing the new process. This is flaky. | 532 // Android multi-process tests are not executing the new process. This is flaky. |
| 550 #define MAYBE_MessagePipePassing DISABLED_MessagePipePassing | 533 #define MAYBE_MessagePipePassing DISABLED_MessagePipePassing |
| 551 #else | 534 #else |
| 552 #define MAYBE_MessagePipePassing MessagePipePassing | 535 #define MAYBE_MessagePipePassing MessagePipePassing |
| 553 #endif | 536 #endif |
| 554 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipePassing) { | 537 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipePassing) { |
| 555 helper()->StartChild("CheckMessagePipe"); | 538 RUN_CHILD_ON_PIPE(CheckMessagePipe, h) |
| 539 MojoCreateSharedBufferOptions options; |
| 540 options.struct_size = sizeof(options); |
| 541 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; |
| 556 | 542 |
| 557 ScopedMessagePipeHandle mp = | 543 MojoHandle mp1, mp2; |
| 558 CreateMessagePipe(std::move(helper()->server_platform_handle)); | 544 ASSERT_EQ(MOJO_RESULT_OK, |
| 559 MojoCreateSharedBufferOptions options; | 545 MojoCreateMessagePipe(nullptr, &mp1, &mp2)); |
| 560 options.struct_size = sizeof(options); | |
| 561 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | |
| 562 | 546 |
| 563 MojoHandle mp1, mp2; | 547 // Write a string into one end of the new message pipe and send the other |
| 564 ASSERT_EQ(MOJO_RESULT_OK, | 548 // end. |
| 565 MojoCreateMessagePipe(nullptr, &mp1, &mp2)); | 549 const std::string hello("hello"); |
| 550 ASSERT_EQ(MOJO_RESULT_OK, |
| 551 MojoWriteMessage(mp1, &hello[0], |
| 552 static_cast<uint32_t>(hello.size()), nullptr, 0, |
| 553 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 554 ASSERT_EQ(MOJO_RESULT_OK, |
| 555 MojoWriteMessage(h, nullptr, 0, &mp2, 1, |
| 556 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 566 | 557 |
| 567 // Write a string into one end of the new message pipe and send the other end. | 558 // Wait for a message from the child. |
| 568 const std::string hello("hello"); | 559 HandleSignalsState hss; |
| 569 ASSERT_EQ(MOJO_RESULT_OK, | 560 ASSERT_EQ(MOJO_RESULT_OK, |
| 570 MojoWriteMessage(mp1, &hello[0], | 561 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |
| 571 static_cast<uint32_t>(hello.size()), nullptr, 0, | 562 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 572 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 563 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 573 ASSERT_EQ(MOJO_RESULT_OK, | 564 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 574 MojoWriteMessage(mp.get().value(), nullptr, 0, &mp2, 1, | |
| 575 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 576 | 565 |
| 577 // Wait for a message from the child. | 566 std::string read_buffer(100, '\0'); |
| 578 HandleSignalsState hss; | 567 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |
| 579 ASSERT_EQ(MOJO_RESULT_OK, | 568 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], |
| 580 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | 569 &read_buffer_size, nullptr, |
| 581 MOJO_DEADLINE_INDEFINITE, &hss)); | 570 0, MOJO_READ_MESSAGE_FLAG_NONE), |
| 582 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 571 MOJO_RESULT_OK); |
| 583 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 572 read_buffer.resize(read_buffer_size); |
| 573 CHECK_EQ(read_buffer, std::string("world")); |
| 584 | 574 |
| 585 std::string read_buffer(100, '\0'); | 575 MojoClose(mp1); |
| 586 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 576 END_CHILD() |
| 587 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | |
| 588 &read_buffer_size, nullptr, | |
| 589 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
| 590 MOJO_RESULT_OK); | |
| 591 read_buffer.resize(read_buffer_size); | |
| 592 CHECK_EQ(read_buffer, std::string("world")); | |
| 593 | |
| 594 MojoClose(mp1); | |
| 595 MojoClose(mp.release().value()); | |
| 596 | |
| 597 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
| 598 } | 577 } |
| 599 | 578 |
| 600 // Like above test, but verifies passing the other MP handle works as well. | 579 // Like above test, but verifies passing the other MP handle works as well. |
| 601 #if defined(OS_ANDROID) | 580 #if defined(OS_ANDROID) |
| 602 // Android multi-process tests are not executing the new process. This is flaky. | 581 // Android multi-process tests are not executing the new process. This is flaky. |
| 603 #define MAYBE_MessagePipeTwoPassing DISABLED_MessagePipeTwoPassing | 582 #define MAYBE_MessagePipeTwoPassing DISABLED_MessagePipeTwoPassing |
| 604 #else | 583 #else |
| 605 #define MAYBE_MessagePipeTwoPassing MessagePipeTwoPassing | 584 #define MAYBE_MessagePipeTwoPassing MessagePipeTwoPassing |
| 606 #endif | 585 #endif |
| 607 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipeTwoPassing) { | 586 TEST_F(MultiprocessMessagePipeTest, MAYBE_MessagePipeTwoPassing) { |
| 608 helper()->StartChild("CheckMessagePipe"); | 587 RUN_CHILD_ON_PIPE(CheckMessagePipe, h) |
| 588 MojoHandle mp1, mp2; |
| 589 ASSERT_EQ(MOJO_RESULT_OK, |
| 590 MojoCreateMessagePipe(nullptr, &mp2, &mp1)); |
| 609 | 591 |
| 610 ScopedMessagePipeHandle mp = | 592 // Write a string into one end of the new message pipe and send the other |
| 611 CreateMessagePipe(std::move(helper()->server_platform_handle)); | 593 // end. |
| 594 const std::string hello("hello"); |
| 595 ASSERT_EQ(MOJO_RESULT_OK, |
| 596 MojoWriteMessage(mp1, &hello[0], |
| 597 static_cast<uint32_t>(hello.size()), nullptr, 0u, |
| 598 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 599 ASSERT_EQ(MOJO_RESULT_OK, |
| 600 MojoWriteMessage(h, nullptr, 0u, &mp2, 1u, |
| 601 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 612 | 602 |
| 613 MojoHandle mp1, mp2; | 603 // Wait for a message from the child. |
| 614 ASSERT_EQ(MOJO_RESULT_OK, | 604 HandleSignalsState hss; |
| 615 MojoCreateMessagePipe(nullptr, &mp2, &mp1)); | 605 ASSERT_EQ(MOJO_RESULT_OK, |
| 606 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |
| 607 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 608 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 609 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 616 | 610 |
| 617 // Write a string into one end of the new message pipe and send the other end. | 611 std::string read_buffer(100, '\0'); |
| 618 const std::string hello("hello"); | 612 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |
| 619 ASSERT_EQ(MOJO_RESULT_OK, | 613 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], |
| 620 MojoWriteMessage(mp1, &hello[0], | 614 &read_buffer_size, nullptr, |
| 621 static_cast<uint32_t>(hello.size()), nullptr, 0u, | 615 0, MOJO_READ_MESSAGE_FLAG_NONE), |
| 622 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 616 MOJO_RESULT_OK); |
| 623 ASSERT_EQ(MOJO_RESULT_OK, | 617 read_buffer.resize(read_buffer_size); |
| 624 MojoWriteMessage(mp.get().value(), nullptr, 0u, &mp2, 1u, | 618 CHECK_EQ(read_buffer, std::string("world")); |
| 625 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 619 END_CHILD(); |
| 626 | |
| 627 // Wait for a message from the child. | |
| 628 HandleSignalsState hss; | |
| 629 ASSERT_EQ(MOJO_RESULT_OK, | |
| 630 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | |
| 631 MOJO_DEADLINE_INDEFINITE, &hss)); | |
| 632 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
| 633 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | |
| 634 | |
| 635 std::string read_buffer(100, '\0'); | |
| 636 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | |
| 637 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | |
| 638 &read_buffer_size, nullptr, | |
| 639 0, MOJO_READ_MESSAGE_FLAG_NONE), | |
| 640 MOJO_RESULT_OK); | |
| 641 read_buffer.resize(read_buffer_size); | |
| 642 CHECK_EQ(read_buffer, std::string("world")); | |
| 643 | |
| 644 MojoClose(mp.release().value()); | |
| 645 | |
| 646 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | |
| 647 } | 620 } |
| 648 | 621 |
| 649 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(DataPipeConsumer) { | 622 DEFINE_TEST_CLIENT_WITH_PIPE(DataPipeConsumer, MultiprocessMessagePipeTest, h) { |
| 650 ScopedPlatformHandle client_platform_handle = | |
| 651 std::move(test::MultiprocessTestHelper::client_platform_handle); | |
| 652 CHECK(client_platform_handle.is_valid()); | |
| 653 | |
| 654 ScopedMessagePipeHandle mp = | |
| 655 CreateMessagePipe(std::move(client_platform_handle)); | |
| 656 | |
| 657 // Wait for the first message from our parent. | 623 // Wait for the first message from our parent. |
| 658 HandleSignalsState hss; | 624 HandleSignalsState hss; |
| 659 CHECK_EQ(MojoWait(mp.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | 625 CHECK_EQ(MojoWait(h, MOJO_HANDLE_SIGNAL_READABLE, |
| 660 MOJO_DEADLINE_INDEFINITE, &hss), | 626 MOJO_DEADLINE_INDEFINITE, &hss), |
| 661 MOJO_RESULT_OK); | 627 MOJO_RESULT_OK); |
| 662 // In this test, the parent definitely doesn't close its end of the message | 628 // In this test, the parent definitely doesn't close its end of the message |
| 663 // pipe before we do. | 629 // pipe before we do. |
| 664 CHECK_EQ(hss.satisfied_signals, | 630 CHECK_EQ(hss.satisfied_signals, |
| 665 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); | 631 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); |
| 666 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | | 632 CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE | |
| 667 MOJO_HANDLE_SIGNAL_WRITABLE | | 633 MOJO_HANDLE_SIGNAL_WRITABLE | |
| 668 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 634 MOJO_HANDLE_SIGNAL_PEER_CLOSED); |
| 669 | 635 |
| 670 // It should have a message pipe. | 636 // It should have a message pipe. |
| 671 MojoHandle handles[10]; | 637 MojoHandle handles[10]; |
| 672 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); | 638 uint32_t num_handlers = MOJO_ARRAYSIZE(handles); |
| 673 CHECK_EQ(MojoReadMessage(mp.get().value(), nullptr, | 639 CHECK_EQ(MojoReadMessage(h, nullptr, |
| 674 nullptr, &handles[0], | 640 nullptr, &handles[0], |
| 675 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), | 641 &num_handlers, MOJO_READ_MESSAGE_FLAG_NONE), |
| 676 MOJO_RESULT_OK); | 642 MOJO_RESULT_OK); |
| 677 CHECK_EQ(num_handlers, 1u); | 643 CHECK_EQ(num_handlers, 1u); |
| 678 | 644 |
| 679 // Read data from the received message pipe. | 645 // Read data from the received message pipe. |
| 680 CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, | 646 CHECK_EQ(MojoWait(handles[0], MOJO_HANDLE_SIGNAL_READABLE, |
| 681 MOJO_DEADLINE_INDEFINITE, &hss), | 647 MOJO_DEADLINE_INDEFINITE, &hss), |
| 682 MOJO_RESULT_OK); | 648 MOJO_RESULT_OK); |
| 683 CHECK_EQ(hss.satisfied_signals, | 649 CHECK_EQ(hss.satisfied_signals, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 705 return 0; | 671 return 0; |
| 706 } | 672 } |
| 707 | 673 |
| 708 #if defined(OS_ANDROID) | 674 #if defined(OS_ANDROID) |
| 709 // Android multi-process tests are not executing the new process. This is flaky. | 675 // Android multi-process tests are not executing the new process. This is flaky. |
| 710 #define MAYBE_DataPipeConsumer DISABLED_DataPipeConsumer | 676 #define MAYBE_DataPipeConsumer DISABLED_DataPipeConsumer |
| 711 #else | 677 #else |
| 712 #define MAYBE_DataPipeConsumer DataPipeConsumer | 678 #define MAYBE_DataPipeConsumer DataPipeConsumer |
| 713 #endif | 679 #endif |
| 714 TEST_F(MultiprocessMessagePipeTest, MAYBE_DataPipeConsumer) { | 680 TEST_F(MultiprocessMessagePipeTest, MAYBE_DataPipeConsumer) { |
| 715 helper()->StartChild("DataPipeConsumer"); | 681 RUN_CHILD_ON_PIPE(DataPipeConsumer, h) |
| 716 | 682 MojoCreateSharedBufferOptions options; |
| 717 ScopedMessagePipeHandle mp = | 683 options.struct_size = sizeof(options); |
| 718 CreateMessagePipe(std::move(helper()->server_platform_handle)); | 684 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; |
| 719 MojoCreateSharedBufferOptions options; | 685 |
| 720 options.struct_size = sizeof(options); | 686 MojoHandle mp1, mp2; |
| 721 options.flags = MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE; | 687 ASSERT_EQ(MOJO_RESULT_OK, |
| 722 | 688 MojoCreateMessagePipe(nullptr, &mp2, &mp1)); |
| 723 MojoHandle mp1, mp2; | 689 |
| 724 ASSERT_EQ(MOJO_RESULT_OK, | 690 // Write a string into one end of the new message pipe and send the other |
| 725 MojoCreateMessagePipe(nullptr, &mp2, &mp1)); | 691 // end. |
| 726 | 692 const std::string hello("hello"); |
| 727 // Write a string into one end of the new message pipe and send the other end. | 693 ASSERT_EQ(MOJO_RESULT_OK, |
| 728 const std::string hello("hello"); | 694 MojoWriteMessage(mp1, &hello[0], |
| 729 ASSERT_EQ(MOJO_RESULT_OK, | 695 static_cast<uint32_t>(hello.size()), nullptr, 0u, |
| 730 MojoWriteMessage(mp1, &hello[0], | 696 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 731 static_cast<uint32_t>(hello.size()), nullptr, 0u, | 697 ASSERT_EQ(MOJO_RESULT_OK, |
| 732 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 698 MojoWriteMessage(h, nullptr, 0, &mp2, 1u, |
| 733 ASSERT_EQ(MOJO_RESULT_OK, | 699 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 734 MojoWriteMessage(mp.get().value(), nullptr, 0, &mp2, 1u, | 700 |
| 735 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 701 // Wait for a message from the child. |
| 736 | 702 HandleSignalsState hss; |
| 737 // Wait for a message from the child. | 703 ASSERT_EQ(MOJO_RESULT_OK, |
| 738 HandleSignalsState hss; | 704 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |
| 739 ASSERT_EQ(MOJO_RESULT_OK, | 705 MOJO_DEADLINE_INDEFINITE, &hss)); |
| 740 MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, | 706 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 741 MOJO_DEADLINE_INDEFINITE, &hss)); | 707 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); |
| 742 EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 708 |
| 743 EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); | 709 std::string read_buffer(100, '\0'); |
| 744 | 710 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |
| 745 std::string read_buffer(100, '\0'); | 711 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], |
| 746 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 712 &read_buffer_size, nullptr, |
| 747 CHECK_EQ(MojoReadMessage(mp1, &read_buffer[0], | 713 0, MOJO_READ_MESSAGE_FLAG_NONE), |
| 748 &read_buffer_size, nullptr, | 714 MOJO_RESULT_OK); |
| 749 0, MOJO_READ_MESSAGE_FLAG_NONE), | 715 read_buffer.resize(read_buffer_size); |
| 750 MOJO_RESULT_OK); | 716 CHECK_EQ(read_buffer, std::string("world")); |
| 751 read_buffer.resize(read_buffer_size); | 717 |
| 752 CHECK_EQ(read_buffer, std::string("world")); | 718 MojoClose(mp1); |
| 753 | 719 END_CHILD(); |
| 754 MojoClose(mp1); | 720 } |
| 755 MojoClose(mp.release().value()); | 721 |
| 756 | 722 TEST_F(MultiprocessMessagePipeTest, CreateMessagePipe) { |
| 757 ASSERT_EQ(0, helper()->WaitForChildShutdown()); | 723 MojoHandle p0, p1; |
| 724 CreateMessagePipe(&p0, &p1); |
| 725 VerifyTransmission(p0, p1, "hey man"); |
| 726 VerifyTransmission(p1, p0, "slow down"); |
| 727 VerifyTransmission(p0, p1, std::string(10 * 1024 * 1024, 'a')); |
| 728 VerifyTransmission(p1, p0, std::string(10 * 1024 * 1024, 'e')); |
| 729 |
| 730 CloseHandle(p0); |
| 731 CloseHandle(p1); |
| 732 } |
| 733 |
| 734 TEST_F(MultiprocessMessagePipeTest, PassMessagePipeLocal) { |
| 735 MojoHandle p0, p1; |
| 736 CreateMessagePipe(&p0, &p1); |
| 737 VerifyTransmission(p0, p1, "testing testing"); |
| 738 VerifyTransmission(p1, p0, "one two three"); |
| 739 |
| 740 MojoHandle p2, p3; |
| 741 |
| 742 CreateMessagePipe(&p2, &p3); |
| 743 VerifyTransmission(p2, p3, "testing testing"); |
| 744 VerifyTransmission(p3, p2, "one two three"); |
| 745 |
| 746 // Pass p2 over p0 to p1. |
| 747 const std::string message = "ceci n'est pas une pipe"; |
| 748 WriteMessageWithHandles(p0, message, &p2, 1); |
| 749 EXPECT_EQ(message, ReadMessageWithHandles(p1, &p2, 1)); |
| 750 |
| 751 CloseHandle(p0); |
| 752 CloseHandle(p1); |
| 753 |
| 754 // Verify that the received handle (now in p2) still works. |
| 755 VerifyTransmission(p2, p3, "Easy come, easy go; will you let me go?"); |
| 756 VerifyTransmission(p3, p2, "Bismillah! NO! We will not let you go!"); |
| 757 |
| 758 CloseHandle(p2); |
| 759 CloseHandle(p3); |
| 760 } |
| 761 |
| 762 // Echos the primordial channel until "exit". |
| 763 DEFINE_TEST_CLIENT_WITH_PIPE(ChannelEchoClient, MultiprocessMessagePipeTest, |
| 764 h) { |
| 765 for (;;) { |
| 766 std::string message = ReadMessage(h); |
| 767 if (message == "exit") |
| 768 break; |
| 769 WriteMessage(h, message); |
| 770 } |
| 771 return 0; |
| 772 } |
| 773 |
| 774 TEST_F(MultiprocessMessagePipeTest, MultiprocessChannelPipe) { |
| 775 RUN_CHILD_ON_PIPE(ChannelEchoClient, h) |
| 776 VerifyEcho(h, "in an interstellar burst"); |
| 777 VerifyEcho(h, "i am back to save the universe"); |
| 778 VerifyEcho(h, std::string(10 * 1024 * 1024, 'o')); |
| 779 |
| 780 WriteMessage(h, "exit"); |
| 781 END_CHILD() |
| 782 } |
| 783 |
| 784 // Receives a pipe handle from the primordial channel and echos on it until |
| 785 // "exit". Used to test simple pipe transfer across processes via channels. |
| 786 DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceClient, MultiprocessMessagePipeTest, |
| 787 h) { |
| 788 MojoHandle p; |
| 789 ReadMessageWithHandles(h, &p, 1); |
| 790 for (;;) { |
| 791 std::string message = ReadMessage(p); |
| 792 if (message == "exit") |
| 793 break; |
| 794 WriteMessage(p, message); |
| 795 } |
| 796 return 0; |
| 797 } |
| 798 |
| 799 TEST_F(MultiprocessMessagePipeTest, PassMessagePipeCrossProcess) { |
| 800 MojoHandle p0, p1; |
| 801 CreateMessagePipe(&p0, &p1); |
| 802 RUN_CHILD_ON_PIPE(EchoServiceClient, h) |
| 803 |
| 804 // Pass one end of the pipe to the other process. |
| 805 WriteMessageWithHandles(h, "here take this", &p1, 1); |
| 806 |
| 807 VerifyEcho(p0, "and you may ask yourself"); |
| 808 VerifyEcho(p0, "where does that highway go?"); |
| 809 VerifyEcho(p0, std::string(20 * 1024 * 1024, 'i')); |
| 810 |
| 811 WriteMessage(p0, "exit"); |
| 812 END_CHILD() |
| 813 CloseHandle(p0); |
| 814 } |
| 815 |
| 816 // Receives a pipe handle from the primordial channel and reads new handles |
| 817 // from it. Each read handle establishes a new echo channel. |
| 818 DEFINE_TEST_CLIENT_WITH_PIPE(EchoServiceFactoryClient, |
| 819 MultiprocessMessagePipeTest, h) { |
| 820 MojoHandle p; |
| 821 ReadMessageWithHandles(h, &p, 1); |
| 822 |
| 823 std::vector<MojoHandle> handles(2); |
| 824 handles[0] = h; |
| 825 handles[1] = p; |
| 826 std::vector<MojoHandleSignals> signals(2, MOJO_HANDLE_SIGNAL_READABLE); |
| 827 for (;;) { |
| 828 uint32_t index; |
| 829 CHECK_EQ(MojoWaitMany(handles.data(), signals.data(), |
| 830 static_cast<uint32_t>(handles.size()), |
| 831 MOJO_DEADLINE_INDEFINITE, &index, nullptr), |
| 832 MOJO_RESULT_OK); |
| 833 DCHECK_LE(index, handles.size()); |
| 834 if (index == 0) { |
| 835 // If data is available on the first pipe, it should be an exit command. |
| 836 EXPECT_EQ(std::string("exit"), ReadMessage(h)); |
| 837 break; |
| 838 } else if (index == 1) { |
| 839 // If the second pipe, it should be a new handle requesting echo service. |
| 840 MojoHandle echo_request; |
| 841 ReadMessageWithHandles(p, &echo_request, 1); |
| 842 handles.push_back(echo_request); |
| 843 signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); |
| 844 } else { |
| 845 // Otherwise it was one of our established echo pipes. Echo! |
| 846 WriteMessage(handles[index], ReadMessage(handles[index])); |
| 847 } |
| 848 } |
| 849 |
| 850 for (size_t i = 1; i < handles.size(); ++i) |
| 851 CloseHandle(handles[i]); |
| 852 |
| 853 return 0; |
| 854 } |
| 855 |
| 856 TEST_F(MultiprocessMessagePipeTest, PassMoarMessagePipesCrossProcess) { |
| 857 MojoHandle echo_factory_proxy, echo_factory_request; |
| 858 CreateMessagePipe(&echo_factory_proxy, &echo_factory_request); |
| 859 |
| 860 MojoHandle echo_proxy_a, echo_request_a; |
| 861 CreateMessagePipe(&echo_proxy_a, &echo_request_a); |
| 862 |
| 863 MojoHandle echo_proxy_b, echo_request_b; |
| 864 CreateMessagePipe(&echo_proxy_b, &echo_request_b); |
| 865 |
| 866 MojoHandle echo_proxy_c, echo_request_c; |
| 867 CreateMessagePipe(&echo_proxy_c, &echo_request_c); |
| 868 |
| 869 RUN_CHILD_ON_PIPE(EchoServiceFactoryClient, h) |
| 870 WriteMessageWithHandles( |
| 871 h, "gief factory naow plz", &echo_factory_request, 1); |
| 872 |
| 873 WriteMessageWithHandles(echo_factory_proxy, "give me an echo service plz!", |
| 874 &echo_request_a, 1); |
| 875 WriteMessageWithHandles(echo_factory_proxy, "give me one too!", |
| 876 &echo_request_b, 1); |
| 877 |
| 878 VerifyEcho(echo_proxy_a, "i came here for an argument"); |
| 879 VerifyEcho(echo_proxy_a, "shut your festering gob"); |
| 880 VerifyEcho(echo_proxy_a, "mumble mumble mumble"); |
| 881 |
| 882 VerifyEcho(echo_proxy_b, "wubalubadubdub"); |
| 883 VerifyEcho(echo_proxy_b, "wubalubadubdub"); |
| 884 |
| 885 WriteMessageWithHandles(echo_factory_proxy, "hook me up also thanks", |
| 886 &echo_request_c, 1); |
| 887 |
| 888 VerifyEcho(echo_proxy_a, "the frobinators taste like frobinators"); |
| 889 VerifyEcho(echo_proxy_b, "beep bop boop"); |
| 890 VerifyEcho(echo_proxy_c, "zzzzzzzzzzzzzzzzzzzzzzzzzz"); |
| 891 |
| 892 WriteMessage(h, "exit"); |
| 893 END_CHILD() |
| 894 |
| 895 CloseHandle(echo_factory_proxy); |
| 896 CloseHandle(echo_proxy_a); |
| 897 CloseHandle(echo_proxy_b); |
| 898 CloseHandle(echo_proxy_c); |
| 899 } |
| 900 |
| 901 TEST_F(MultiprocessMessagePipeTest, ChannelPipesWithMultipleChildren) { |
| 902 RUN_CHILD_ON_PIPE(ChannelEchoClient, a) |
| 903 RUN_CHILD_ON_PIPE(ChannelEchoClient, b) |
| 904 VerifyEcho(a, "hello child 0"); |
| 905 VerifyEcho(b, "hello child 1"); |
| 906 |
| 907 WriteMessage(a, "exit"); |
| 908 WriteMessage(b, "exit"); |
| 909 END_CHILD() |
| 910 END_CHILD() |
| 911 } |
| 912 |
| 913 // Reads and turns a pipe handle some number of times to create lots of |
| 914 // transient proxies. |
| 915 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(PingPongPipeClient, |
| 916 MultiprocessMessagePipeTest, h) { |
| 917 const size_t kNumBounces = 50; |
| 918 MojoHandle p0, p1; |
| 919 ReadMessageWithHandles(h, &p0, 1); |
| 920 ReadMessageWithHandles(h, &p1, 1); |
| 921 for (size_t i = 0; i < kNumBounces; ++i) { |
| 922 WriteMessageWithHandles(h, "", &p1, 1); |
| 923 ReadMessageWithHandles(h, &p1, 1); |
| 924 } |
| 925 WriteMessageWithHandles(h, "", &p0, 1); |
| 926 WriteMessage(p1, "bye"); |
| 927 MojoClose(p1); |
| 928 EXPECT_EQ("quit", ReadMessage(h)); |
| 929 } |
| 930 |
| 931 TEST_F(MultiprocessMessagePipeTest, PingPongPipe) { |
| 932 MojoHandle p0, p1; |
| 933 CreateMessagePipe(&p0, &p1); |
| 934 |
| 935 RUN_CHILD_ON_PIPE(PingPongPipeClient, h) |
| 936 const size_t kNumBounces = 50; |
| 937 WriteMessageWithHandles(h, "", &p0, 1); |
| 938 WriteMessageWithHandles(h, "", &p1, 1); |
| 939 for (size_t i = 0; i < kNumBounces; ++i) { |
| 940 ReadMessageWithHandles(h, &p1, 1); |
| 941 WriteMessageWithHandles(h, "", &p1, 1); |
| 942 } |
| 943 ReadMessageWithHandles(h, &p0, 1); |
| 944 WriteMessage(h, "quit"); |
| 945 END_CHILD() |
| 946 |
| 947 EXPECT_EQ("bye", ReadMessage(p0)); |
| 948 |
| 949 // We should still be able to observe peer closure from the other end. |
| 950 EXPECT_EQ(MOJO_RESULT_OK, |
| 951 MojoWait(p0, MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 952 MOJO_DEADLINE_INDEFINITE, nullptr)); |
| 953 } |
| 954 |
| 955 // Parses commands from the parent pipe and does whatever it's asked to do. |
| 956 DEFINE_TEST_CLIENT_WITH_PIPE(CommandDrivenClient, MultiprocessMessagePipeTest, |
| 957 h) { |
| 958 base::hash_map<std::string, MojoHandle> named_pipes; |
| 959 for (;;) { |
| 960 MojoHandle p; |
| 961 auto parts = base::SplitString(ReadMessageWithOptionalHandle(h, &p), ":", |
| 962 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); |
| 963 CHECK(!parts.empty()); |
| 964 std::string command = parts[0]; |
| 965 if (command == "take") { |
| 966 // Take a pipe. |
| 967 CHECK_EQ(parts.size(), 2u); |
| 968 CHECK_NE(p, MOJO_HANDLE_INVALID); |
| 969 named_pipes[parts[1]] = p; |
| 970 WriteMessage(h, "ok"); |
| 971 } else if (command == "return") { |
| 972 // Return a pipe. |
| 973 CHECK_EQ(parts.size(), 2u); |
| 974 CHECK_EQ(p, MOJO_HANDLE_INVALID); |
| 975 p = named_pipes[parts[1]]; |
| 976 CHECK_NE(p, MOJO_HANDLE_INVALID); |
| 977 named_pipes.erase(parts[1]); |
| 978 WriteMessageWithHandles(h, "ok", &p, 1); |
| 979 } else if (command == "say") { |
| 980 // Say something to a named pipe. |
| 981 CHECK_EQ(parts.size(), 3u); |
| 982 CHECK_EQ(p, MOJO_HANDLE_INVALID); |
| 983 p = named_pipes[parts[1]]; |
| 984 CHECK_NE(p, MOJO_HANDLE_INVALID); |
| 985 CHECK(!parts[2].empty()); |
| 986 WriteMessage(p, parts[2]); |
| 987 WriteMessage(h, "ok"); |
| 988 } else if (command == "hear") { |
| 989 // Expect to read something from a named pipe. |
| 990 CHECK_EQ(parts.size(), 3u); |
| 991 CHECK_EQ(p, MOJO_HANDLE_INVALID); |
| 992 p = named_pipes[parts[1]]; |
| 993 CHECK_NE(p, MOJO_HANDLE_INVALID); |
| 994 CHECK(!parts[2].empty()); |
| 995 CHECK_EQ(parts[2], ReadMessage(p)); |
| 996 WriteMessage(h, "ok"); |
| 997 } else if (command == "pass") { |
| 998 // Pass one named pipe over another named pipe. |
| 999 CHECK_EQ(parts.size(), 3u); |
| 1000 CHECK_EQ(p, MOJO_HANDLE_INVALID); |
| 1001 p = named_pipes[parts[1]]; |
| 1002 MojoHandle carrier = named_pipes[parts[2]]; |
| 1003 CHECK_NE(p, MOJO_HANDLE_INVALID); |
| 1004 CHECK_NE(carrier, MOJO_HANDLE_INVALID); |
| 1005 named_pipes.erase(parts[1]); |
| 1006 WriteMessageWithHandles(carrier, "got a pipe for ya", &p, 1); |
| 1007 WriteMessage(h, "ok"); |
| 1008 } else if (command == "catch") { |
| 1009 // Expect to receive one named pipe from another named pipe. |
| 1010 CHECK_EQ(parts.size(), 3u); |
| 1011 CHECK_EQ(p, MOJO_HANDLE_INVALID); |
| 1012 MojoHandle carrier = named_pipes[parts[2]]; |
| 1013 CHECK_NE(carrier, MOJO_HANDLE_INVALID); |
| 1014 ReadMessageWithHandles(carrier, &p, 1); |
| 1015 CHECK_NE(p, MOJO_HANDLE_INVALID); |
| 1016 named_pipes[parts[1]] = p; |
| 1017 WriteMessage(h, "ok"); |
| 1018 } else if (command == "exit") { |
| 1019 CHECK_EQ(parts.size(), 1u); |
| 1020 break; |
| 1021 } |
| 1022 } |
| 1023 |
| 1024 for (auto& pipe: named_pipes) |
| 1025 CloseHandle(pipe.second); |
| 1026 |
| 1027 return 0; |
| 1028 } |
| 1029 |
| 1030 TEST_F(MultiprocessMessagePipeTest, ChildToChildPipes) { |
| 1031 RUN_CHILD_ON_PIPE(CommandDrivenClient, h0) |
| 1032 RUN_CHILD_ON_PIPE(CommandDrivenClient, h1) |
| 1033 CommandDrivenClientController a(h0); |
| 1034 CommandDrivenClientController b(h1); |
| 1035 |
| 1036 // Create a pipe and pass each end to a different client. |
| 1037 MojoHandle p0, p1; |
| 1038 CreateMessagePipe(&p0, &p1); |
| 1039 a.SendHandle("x", p0); |
| 1040 b.SendHandle("y", p1); |
| 1041 |
| 1042 // Make sure they can talk. |
| 1043 a.Send("say:x:hello sir"); |
| 1044 b.Send("hear:y:hello sir"); |
| 1045 |
| 1046 b.Send("say:y:i love multiprocess pipes!"); |
| 1047 a.Send("hear:x:i love multiprocess pipes!"); |
| 1048 |
| 1049 a.Exit(); |
| 1050 b.Exit(); |
| 1051 END_CHILD() |
| 1052 END_CHILD() |
| 1053 } |
| 1054 |
| 1055 TEST_F(MultiprocessMessagePipeTest, MoreChildToChildPipes) { |
| 1056 RUN_CHILD_ON_PIPE(CommandDrivenClient, h0) |
| 1057 RUN_CHILD_ON_PIPE(CommandDrivenClient, h1) |
| 1058 RUN_CHILD_ON_PIPE(CommandDrivenClient, h2) |
| 1059 RUN_CHILD_ON_PIPE(CommandDrivenClient, h3) |
| 1060 CommandDrivenClientController a(h0), b(h1), c(h2), d(h3); |
| 1061 |
| 1062 // Connect a to b and c to d |
| 1063 |
| 1064 MojoHandle p0, p1; |
| 1065 |
| 1066 CreateMessagePipe(&p0, &p1); |
| 1067 a.SendHandle("b_pipe", p0); |
| 1068 b.SendHandle("a_pipe", p1); |
| 1069 |
| 1070 MojoHandle p2, p3; |
| 1071 |
| 1072 CreateMessagePipe(&p2, &p3); |
| 1073 c.SendHandle("d_pipe", p2); |
| 1074 d.SendHandle("c_pipe", p3); |
| 1075 |
| 1076 // Connect b to c via a and d |
| 1077 MojoHandle p4, p5; |
| 1078 CreateMessagePipe(&p4, &p5); |
| 1079 a.SendHandle("d_pipe", p4); |
| 1080 d.SendHandle("a_pipe", p5); |
| 1081 |
| 1082 // Have |a| pass its new |d|-pipe to |b|. It will eventually connect |
| 1083 // to |c|. |
| 1084 a.Send("pass:d_pipe:b_pipe"); |
| 1085 b.Send("catch:c_pipe:a_pipe"); |
| 1086 |
| 1087 // Have |d| pass its new |a|-pipe to |c|. It will now be connected to |
| 1088 // |b|. |
| 1089 d.Send("pass:a_pipe:c_pipe"); |
| 1090 c.Send("catch:b_pipe:d_pipe"); |
| 1091 |
| 1092 // Make sure b and c and talk. |
| 1093 b.Send("say:c_pipe:it's a beautiful day"); |
| 1094 c.Send("hear:b_pipe:it's a beautiful day"); |
| 1095 |
| 1096 // Create x and y and have b and c exchange them. |
| 1097 MojoHandle x, y; |
| 1098 CreateMessagePipe(&x, &y); |
| 1099 b.SendHandle("x", x); |
| 1100 c.SendHandle("y", y); |
| 1101 b.Send("pass:x:c_pipe"); |
| 1102 c.Send("pass:y:b_pipe"); |
| 1103 b.Send("catch:y:c_pipe"); |
| 1104 c.Send("catch:x:b_pipe"); |
| 1105 |
| 1106 // Make sure the pipe still works in both directions. |
| 1107 b.Send("say:y:hello"); |
| 1108 c.Send("hear:x:hello"); |
| 1109 c.Send("say:x:goodbye"); |
| 1110 b.Send("hear:y:goodbye"); |
| 1111 |
| 1112 // Take both pipes back. |
| 1113 y = c.RetrieveHandle("x"); |
| 1114 x = b.RetrieveHandle("y"); |
| 1115 |
| 1116 VerifyTransmission(x, y, "still works"); |
| 1117 VerifyTransmission(y, x, "in both directions"); |
| 1118 |
| 1119 CloseHandle(x); |
| 1120 CloseHandle(y); |
| 1121 |
| 1122 a.Exit(); |
| 1123 b.Exit(); |
| 1124 c.Exit(); |
| 1125 d.Exit(); |
| 1126 END_CHILD() |
| 1127 END_CHILD() |
| 1128 END_CHILD() |
| 1129 END_CHILD() |
| 1130 } |
| 1131 |
| 1132 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeer, |
| 1133 MultiprocessMessagePipeTest, h) { |
| 1134 MojoHandle p; |
| 1135 EXPECT_EQ("foo", ReadMessageWithHandles(h, &p, 1)); |
| 1136 |
| 1137 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 1138 MOJO_DEADLINE_INDEFINITE, nullptr)); |
| 1139 } |
| 1140 |
| 1141 TEST_F(MultiprocessMessagePipeTest, SendPipeThenClosePeer) { |
| 1142 RUN_CHILD_ON_PIPE(ReceivePipeWithClosedPeer, h) |
| 1143 MojoHandle a, b; |
| 1144 CreateMessagePipe(&a, &b); |
| 1145 |
| 1146 // Send |a| and immediately close |b|. The child should observe closure. |
| 1147 WriteMessageWithHandles(h, "foo", &a, 1); |
| 1148 MojoClose(b); |
| 1149 END_CHILD() |
| 1150 } |
| 1151 |
| 1152 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(SendOtherChildPipeWithClosedPeer, |
| 1153 MultiprocessMessagePipeTest, h) { |
| 1154 // Create a new pipe and send one end to the parent, who will connect it to |
| 1155 // a client running ReceivePipeWithClosedPeerFromOtherChild. |
| 1156 MojoHandle application_proxy, application_request; |
| 1157 CreateMessagePipe(&application_proxy, &application_request); |
| 1158 WriteMessageWithHandles(h, "c2a plz", &application_request, 1); |
| 1159 |
| 1160 // Create another pipe and send one end to the remote "application". |
| 1161 MojoHandle service_proxy, service_request; |
| 1162 CreateMessagePipe(&service_proxy, &service_request); |
| 1163 WriteMessageWithHandles(application_proxy, "c2s lol", &service_request, 1); |
| 1164 |
| 1165 // Immediately close the service proxy. The "application" should detect this. |
| 1166 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(service_proxy)); |
| 1167 |
| 1168 // Wait for quit. |
| 1169 EXPECT_EQ("quit", ReadMessage(h)); |
| 1170 } |
| 1171 |
| 1172 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(ReceivePipeWithClosedPeerFromOtherChild, |
| 1173 MultiprocessMessagePipeTest, h) { |
| 1174 // Receive a pipe from the parent. This is akin to an "application request". |
| 1175 MojoHandle application_client; |
| 1176 EXPECT_EQ("c2a", ReadMessageWithHandles(h, &application_client, 1)); |
| 1177 |
| 1178 // Receive a pipe from the "application" "client". |
| 1179 MojoHandle service_client; |
| 1180 EXPECT_EQ("c2s lol", |
| 1181 ReadMessageWithHandles(application_client, &service_client, 1)); |
| 1182 |
| 1183 // Wait for the service client to signal closure. |
| 1184 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(service_client, |
| 1185 MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 1186 MOJO_DEADLINE_INDEFINITE, nullptr)); |
| 1187 |
| 1188 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(service_client)); |
| 1189 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(application_client)); |
| 1190 } |
| 1191 |
| 1192 TEST_F(MultiprocessMessagePipeTest, SendPipeWithClosedPeerBetweenChildren) { |
| 1193 RUN_CHILD_ON_PIPE(SendOtherChildPipeWithClosedPeer, kid_a) |
| 1194 RUN_CHILD_ON_PIPE(ReceivePipeWithClosedPeerFromOtherChild, kid_b) |
| 1195 // Receive an "application request" from the first child and forward it |
| 1196 // to the second child. |
| 1197 MojoHandle application_request; |
| 1198 EXPECT_EQ("c2a plz", |
| 1199 ReadMessageWithHandles(kid_a, &application_request, 1)); |
| 1200 |
| 1201 WriteMessageWithHandles(kid_b, "c2a", &application_request, 1); |
| 1202 END_CHILD() |
| 1203 |
| 1204 WriteMessage(kid_a, "quit"); |
| 1205 END_CHILD() |
| 1206 } |
| 1207 |
| 1208 TEST_F(MultiprocessMessagePipeTest, SendClosePeerSend) { |
| 1209 MojoHandle a, b; |
| 1210 CreateMessagePipe(&a, &b); |
| 1211 |
| 1212 MojoHandle c, d; |
| 1213 CreateMessagePipe(&c, &d); |
| 1214 |
| 1215 // Send |a| over |c|, immediately close |b|, then send |a| back over |d|. |
| 1216 WriteMessageWithHandles(c, "foo", &a, 1); |
| 1217 EXPECT_EQ("foo", ReadMessageWithHandles(d, &a, 1)); |
| 1218 WriteMessageWithHandles(d, "bar", &a, 1); |
| 1219 EXPECT_EQ("bar", ReadMessageWithHandles(c, &a, 1)); |
| 1220 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b)); |
| 1221 |
| 1222 // We should be able to detect peer closure on |a|. |
| 1223 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(a, MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 1224 MOJO_DEADLINE_INDEFINITE, nullptr)); |
| 1225 } |
| 1226 |
| 1227 DEFINE_TEST_CLIENT_TEST_WITH_PIPE(WriteCloseSendPeerClient, |
| 1228 MultiprocessMessagePipeTest, h) { |
| 1229 MojoHandle pipe[2]; |
| 1230 EXPECT_EQ("foo", ReadMessageWithHandles(h, pipe, 2)); |
| 1231 |
| 1232 // Write some messages to the first endpoint and then close it. |
| 1233 WriteMessage(pipe[0], "baz"); |
| 1234 WriteMessage(pipe[0], "qux"); |
| 1235 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(pipe[0])); |
| 1236 |
| 1237 MojoHandle c, d; |
| 1238 CreateMessagePipe(&c, &d); |
| 1239 |
| 1240 // Pass the orphaned endpoint over another pipe before passing it back to |
| 1241 // the parent, just for some extra proxying goodness. |
| 1242 WriteMessageWithHandles(c, "foo", &pipe[1], 1); |
| 1243 EXPECT_EQ("foo", ReadMessageWithHandles(d, &pipe[1], 1)); |
| 1244 |
| 1245 // And finally pass it back to the parent. |
| 1246 WriteMessageWithHandles(h, "bar", &pipe[1], 1); |
| 1247 |
| 1248 EXPECT_EQ("quit", ReadMessage(h)); |
| 1249 } |
| 1250 |
| 1251 TEST_F(MultiprocessMessagePipeTest, WriteCloseSendPeer) { |
| 1252 MojoHandle pipe[2]; |
| 1253 CreateMessagePipe(&pipe[0], &pipe[1]); |
| 1254 |
| 1255 RUN_CHILD_ON_PIPE(WriteCloseSendPeerClient, h) |
| 1256 // Pass the pipe to the child. |
| 1257 WriteMessageWithHandles(h, "foo", pipe, 2); |
| 1258 |
| 1259 // Read back an endpoint which should have messages on it. |
| 1260 MojoHandle p; |
| 1261 EXPECT_EQ("bar", ReadMessageWithHandles(h, &p, 1)); |
| 1262 |
| 1263 EXPECT_EQ("baz", ReadMessage(p)); |
| 1264 EXPECT_EQ("qux", ReadMessage(p)); |
| 1265 |
| 1266 // Expect to have peer closure signaled. |
| 1267 EXPECT_EQ(MOJO_RESULT_OK, MojoWait(p, MOJO_HANDLE_SIGNAL_PEER_CLOSED, |
| 1268 MOJO_DEADLINE_INDEFINITE, nullptr)); |
| 1269 |
| 1270 WriteMessage(h, "quit"); |
| 1271 END_CHILD() |
| 758 } | 1272 } |
| 759 | 1273 |
| 760 } // namespace | 1274 } // namespace |
| 761 } // namespace edk | 1275 } // namespace edk |
| 762 } // namespace mojo | 1276 } // namespace mojo |
| OLD | NEW |