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 |