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 // TODO(vtl): Enable this on non-POSIX once we have a non-POSIX implementation. | 5 // TODO(vtl): Enable this on non-POSIX once we have a non-POSIX implementation. |
6 #include "build/build_config.h" | 6 #include "build/build_config.h" |
7 #if defined(OS_POSIX) | 7 #if defined(OS_POSIX) |
8 | 8 |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/callback.h" | 15 #include "base/callback.h" |
16 #include "base/location.h" | 16 #include "base/location.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
19 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
20 #include "mojo/common/test/multiprocess_test_base.h" | 20 #include "mojo/common/test/multiprocess_test_helper.h" |
21 #include "mojo/system/channel.h" | 21 #include "mojo/system/channel.h" |
22 #include "mojo/system/embedder/scoped_platform_handle.h" | 22 #include "mojo/system/embedder/scoped_platform_handle.h" |
23 #include "mojo/system/local_message_pipe_endpoint.h" | 23 #include "mojo/system/local_message_pipe_endpoint.h" |
24 #include "mojo/system/message_pipe.h" | 24 #include "mojo/system/message_pipe.h" |
25 #include "mojo/system/proxy_message_pipe_endpoint.h" | 25 #include "mojo/system/proxy_message_pipe_endpoint.h" |
26 #include "mojo/system/test_utils.h" | 26 #include "mojo/system/test_utils.h" |
27 #include "mojo/system/waiter.h" | 27 #include "mojo/system/waiter.h" |
| 28 #include "testing/gtest/include/gtest/gtest.h" |
28 | 29 |
29 namespace mojo { | 30 namespace mojo { |
30 namespace system { | 31 namespace system { |
31 namespace { | 32 namespace { |
32 | 33 |
| 34 // TODO(vtl): Replace this with a |TestIOThread|. |
33 class IOThreadWrapper { | 35 class IOThreadWrapper { |
34 public: | 36 public: |
35 IOThreadWrapper() : io_thread_("io_thread") {} | 37 IOThreadWrapper() : io_thread_("io_thread") {} |
36 ~IOThreadWrapper() { | 38 ~IOThreadWrapper() { |
37 CHECK(!channel_.get()); | 39 CHECK(!channel_.get()); |
38 CHECK(!io_thread_.IsRunning()); | 40 CHECK(!io_thread_.IsRunning()); |
39 } | 41 } |
40 | 42 |
41 void PostTask(const tracked_objects::Location& from_here, | 43 void PostTask(const tracked_objects::Location& from_here, |
42 const base::Closure& task) { | 44 const base::Closure& task) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 channel_->Shutdown(); | 105 channel_->Shutdown(); |
104 channel_ = NULL; | 106 channel_ = NULL; |
105 } | 107 } |
106 | 108 |
107 base::Thread io_thread_; | 109 base::Thread io_thread_; |
108 scoped_refptr<Channel> channel_; | 110 scoped_refptr<Channel> channel_; |
109 | 111 |
110 DISALLOW_COPY_AND_ASSIGN(IOThreadWrapper); | 112 DISALLOW_COPY_AND_ASSIGN(IOThreadWrapper); |
111 }; | 113 }; |
112 | 114 |
113 class MultiprocessMessagePipeTest : public mojo::test::MultiprocessTestBase { | 115 class MultiprocessMessagePipeTest : public testing::Test { |
114 public: | 116 public: |
115 MultiprocessMessagePipeTest() {} | 117 MultiprocessMessagePipeTest() {} |
116 virtual ~MultiprocessMessagePipeTest() {} | 118 virtual ~MultiprocessMessagePipeTest() {} |
117 | 119 |
118 virtual void TearDown() OVERRIDE { | 120 virtual void TearDown() OVERRIDE { |
119 if (io_thread_wrapper_.is_initialized()) | 121 if (io_thread_wrapper_.is_initialized()) |
120 io_thread_wrapper_.Shutdown(); | 122 io_thread_wrapper_.Shutdown(); |
121 mojo::test::MultiprocessTestBase::TearDown(); | |
122 } | 123 } |
123 | 124 |
| 125 protected: |
124 void Init(scoped_refptr<MessagePipe> mp) { | 126 void Init(scoped_refptr<MessagePipe> mp) { |
125 io_thread_wrapper_.Init(server_platform_handle.Pass(), mp); | 127 io_thread_wrapper_.Init(helper_.server_platform_handle.Pass(), mp); |
126 } | 128 } |
127 | 129 |
| 130 mojo::test::MultiprocessTestHelper* helper() { return &helper_; } |
| 131 |
128 private: | 132 private: |
129 IOThreadWrapper io_thread_wrapper_; | 133 IOThreadWrapper io_thread_wrapper_; |
| 134 mojo::test::MultiprocessTestHelper helper_; |
130 | 135 |
131 DISALLOW_COPY_AND_ASSIGN(MultiprocessMessagePipeTest); | 136 DISALLOW_COPY_AND_ASSIGN(MultiprocessMessagePipeTest); |
132 }; | 137 }; |
133 | 138 |
134 MojoResult WaitIfNecessary(scoped_refptr<MessagePipe> mp, MojoWaitFlags flags) { | 139 MojoResult WaitIfNecessary(scoped_refptr<MessagePipe> mp, MojoWaitFlags flags) { |
135 Waiter waiter; | 140 Waiter waiter; |
136 waiter.Init(); | 141 waiter.Init(); |
137 | 142 |
138 MojoResult add_result = mp->AddWaiter(0, &waiter, flags, MOJO_RESULT_OK); | 143 MojoResult add_result = mp->AddWaiter(0, &waiter, flags, MOJO_RESULT_OK); |
139 if (add_result != MOJO_RESULT_OK) { | 144 if (add_result != MOJO_RESULT_OK) { |
140 return (add_result == MOJO_RESULT_ALREADY_EXISTS) ? MOJO_RESULT_OK : | 145 return (add_result == MOJO_RESULT_ALREADY_EXISTS) ? MOJO_RESULT_OK : |
141 add_result; | 146 add_result; |
142 } | 147 } |
143 | 148 |
144 MojoResult wait_result = waiter.Wait(MOJO_DEADLINE_INDEFINITE); | 149 MojoResult wait_result = waiter.Wait(MOJO_DEADLINE_INDEFINITE); |
145 mp->RemoveWaiter(0, &waiter); | 150 mp->RemoveWaiter(0, &waiter); |
146 return wait_result; | 151 return wait_result; |
147 } | 152 } |
148 | 153 |
149 // For each message received, sends a reply message with the same contents | 154 // For each message received, sends a reply message with the same contents |
150 // repeated twice, until the other end is closed or it receives "quitquitquit" | 155 // repeated twice, until the other end is closed or it receives "quitquitquit" |
151 // (which it doesn't reply to). It'll return the number of messages received, | 156 // (which it doesn't reply to). It'll return the number of messages received, |
152 // not including any "quitquitquit" message, modulo 100. | 157 // not including any "quitquitquit" message, modulo 100. |
153 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) { | 158 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(EchoEcho) { |
154 IOThreadWrapper io_thread_wrapper; | 159 IOThreadWrapper io_thread_wrapper; |
155 embedder::ScopedPlatformHandle client_platform_handle = | 160 embedder::ScopedPlatformHandle client_platform_handle = |
156 MultiprocessMessagePipeTest::client_platform_handle.Pass(); | 161 mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); |
157 CHECK(client_platform_handle.is_valid()); | 162 CHECK(client_platform_handle.is_valid()); |
158 scoped_refptr<MessagePipe> mp(new MessagePipe( | 163 scoped_refptr<MessagePipe> mp(new MessagePipe( |
159 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), | 164 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
160 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); | 165 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
161 io_thread_wrapper.Init(client_platform_handle.Pass(), mp); | 166 io_thread_wrapper.Init(client_platform_handle.Pass(), mp); |
162 | 167 |
163 const std::string quitquitquit("quitquitquit"); | 168 const std::string quitquitquit("quitquitquit"); |
164 int rv = 0; | 169 int rv = 0; |
165 for (;; rv = (rv + 1) % 100) { | 170 for (;; rv = (rv + 1) % 100) { |
166 // Wait for our end of the message pipe to be readable. | 171 // Wait for our end of the message pipe to be readable. |
(...skipping 29 matching lines...) Expand all Loading... |
196 } | 201 } |
197 | 202 |
198 | 203 |
199 mp->Close(0); | 204 mp->Close(0); |
200 io_thread_wrapper.Shutdown(); | 205 io_thread_wrapper.Shutdown(); |
201 return rv; | 206 return rv; |
202 } | 207 } |
203 | 208 |
204 // Sends "hello" to child, and expects "hellohello" back. | 209 // Sends "hello" to child, and expects "hellohello" back. |
205 TEST_F(MultiprocessMessagePipeTest, Basic) { | 210 TEST_F(MultiprocessMessagePipeTest, Basic) { |
206 StartChild("EchoEcho"); | 211 helper()->StartChild("EchoEcho"); |
207 | 212 |
208 scoped_refptr<MessagePipe> mp(new MessagePipe( | 213 scoped_refptr<MessagePipe> mp(new MessagePipe( |
209 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), | 214 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
210 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); | 215 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
211 Init(mp); | 216 Init(mp); |
212 | 217 |
213 std::string hello("hello"); | 218 std::string hello("hello"); |
214 EXPECT_EQ(MOJO_RESULT_OK, | 219 EXPECT_EQ(MOJO_RESULT_OK, |
215 mp->WriteMessage(0, | 220 mp->WriteMessage(0, |
216 hello.data(), static_cast<uint32_t>(hello.size()), | 221 hello.data(), static_cast<uint32_t>(hello.size()), |
217 NULL, | 222 NULL, |
218 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 223 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
219 | 224 |
220 EXPECT_EQ(MOJO_RESULT_OK, WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); | 225 EXPECT_EQ(MOJO_RESULT_OK, WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); |
221 | 226 |
222 std::string read_buffer(1000, '\0'); | 227 std::string read_buffer(1000, '\0'); |
223 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); | 228 uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer.size()); |
224 CHECK_EQ(mp->ReadMessage(0, | 229 CHECK_EQ(mp->ReadMessage(0, |
225 &read_buffer[0], &read_buffer_size, | 230 &read_buffer[0], &read_buffer_size, |
226 NULL, NULL, | 231 NULL, NULL, |
227 MOJO_READ_MESSAGE_FLAG_NONE), | 232 MOJO_READ_MESSAGE_FLAG_NONE), |
228 MOJO_RESULT_OK); | 233 MOJO_RESULT_OK); |
229 read_buffer.resize(read_buffer_size); | 234 read_buffer.resize(read_buffer_size); |
230 VLOG(2) << "Parent got: " << read_buffer; | 235 VLOG(2) << "Parent got: " << read_buffer; |
231 EXPECT_EQ(hello + hello, read_buffer); | 236 EXPECT_EQ(hello + hello, read_buffer); |
232 | 237 |
233 mp->Close(0); | 238 mp->Close(0); |
234 | 239 |
235 // We sent one message. | 240 // We sent one message. |
236 EXPECT_EQ(1 % 100, WaitForChildShutdown()); | 241 EXPECT_EQ(1 % 100, helper()->WaitForChildShutdown()); |
237 } | 242 } |
238 | 243 |
239 // Sends a bunch of messages to the child. Expects them "repeated" back. Waits | 244 // Sends a bunch of messages to the child. Expects them "repeated" back. Waits |
240 // for the child to close its end before quitting. | 245 // for the child to close its end before quitting. |
241 TEST_F(MultiprocessMessagePipeTest, QueueMessages) { | 246 TEST_F(MultiprocessMessagePipeTest, QueueMessages) { |
242 StartChild("EchoEcho"); | 247 helper()->StartChild("EchoEcho"); |
243 | 248 |
244 scoped_refptr<MessagePipe> mp(new MessagePipe( | 249 scoped_refptr<MessagePipe> mp(new MessagePipe( |
245 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), | 250 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
246 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); | 251 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
247 Init(mp); | 252 Init(mp); |
248 | 253 |
249 static const size_t kNumMessages = 1001; | 254 static const size_t kNumMessages = 1001; |
250 for (size_t i = 0; i < kNumMessages; i++) { | 255 for (size_t i = 0; i < kNumMessages; i++) { |
251 std::string write_buffer(i, 'A' + (i % 26)); | 256 std::string write_buffer(i, 'A' + (i % 26)); |
252 EXPECT_EQ(MOJO_RESULT_OK, | 257 EXPECT_EQ(MOJO_RESULT_OK, |
(...skipping 27 matching lines...) Expand all Loading... |
280 EXPECT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); | 285 EXPECT_EQ(std::string(i * 2, 'A' + (i % 26)), read_buffer); |
281 } | 286 } |
282 | 287 |
283 // Wait for it to become readable, which should fail (since we sent | 288 // Wait for it to become readable, which should fail (since we sent |
284 // "quitquitquit"). | 289 // "quitquitquit"). |
285 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 290 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
286 WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); | 291 WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); |
287 | 292 |
288 mp->Close(0); | 293 mp->Close(0); |
289 | 294 |
290 EXPECT_EQ(static_cast<int>(kNumMessages % 100), WaitForChildShutdown()); | 295 EXPECT_EQ(static_cast<int>(kNumMessages % 100), |
| 296 helper()->WaitForChildShutdown()); |
291 } | 297 } |
292 | 298 |
293 } // namespace | 299 } // namespace |
294 } // namespace system | 300 } // namespace system |
295 } // namespace mojo | 301 } // namespace mojo |
296 | 302 |
297 #endif // defined(OS_POSIX) | 303 #endif // defined(OS_POSIX) |
OLD | NEW |