Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1208)

Side by Side Diff: mojo/system/remote_message_pipe_posix_unittest.cc

Issue 60103005: Mojo: First stab at making MessagePipes work across OS pipes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« base/compiler_specific.h ('K') | « mojo/system/raw_channel_win.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 // TODO(vtl): Factor out the POSIX-specific bits of this test (once we have a
6 // non-POSIX implementation).
7
8 #include "mojo/system/message_pipe.h"
9
10 #include <fcntl.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <sys/socket.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16
17 #include "base/basictypes.h"
18 #include "base/bind.h"
19 #include "base/callback.h"
20 #include "base/location.h"
21 #include "base/logging.h"
22 #include "base/message_loop/message_loop.h"
23 #include "base/synchronization/waitable_event.h"
24 #include "base/threading/thread.h"
25 #include "mojo/system/channel.h"
26 #include "mojo/system/local_message_pipe_endpoint.h"
27 #include "mojo/system/platform_channel_handle.h"
28 #include "mojo/system/proxy_message_pipe_endpoint.h"
29 #include "mojo/system/test_utils.h"
30 #include "mojo/system/waiter.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 namespace mojo {
34 namespace system {
35 namespace {
36
37 class RemoteMessagePipeTest : public testing::Test {
38 public:
39 RemoteMessagePipeTest() : io_thread_("io_thread") {
40 }
41
42 virtual ~RemoteMessagePipeTest() {
43 }
44
45 virtual void SetUp() OVERRIDE {
46 io_thread_.StartWithOptions(
47 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
48
49 test::PostTaskAndWait(io_thread_task_runner(),
50 FROM_HERE,
51 base::Bind(&RemoteMessagePipeTest::SetUpOnIOThread,
52 base::Unretained(this)));
53 }
54
55 virtual void TearDown() OVERRIDE {
56 test::PostTaskAndWait(io_thread_task_runner(),
57 FROM_HERE,
58 base::Bind(&RemoteMessagePipeTest::TearDownOnIOThread,
59 base::Unretained(this)));
60 io_thread_.Stop();
61 }
62
63 // This connects MP 0, port 1 and MP 1, port 0 (leaving MP 0, port 0 and MP 1,
64 // port 1 as the user-visible endpoints) to channel 0 and 1, respectively. MP
65 // 0, port 1 and MP 1, port 0 must have |ProxyMessagePipeEndpoint|s.
66 void ConnectMessagePipesOnIOThread(scoped_refptr<MessagePipe> mp_0,
67 scoped_refptr<MessagePipe> mp_1) {
68 CHECK_EQ(base::MessageLoop::current(), io_thread_message_loop());
69
70 MessageInTransit::EndpointId local_id_0 =
71 channels_[0]->AttachMessagePipeEndpoint(mp_0, 1);
72 MessageInTransit::EndpointId local_id_1 =
73 channels_[1]->AttachMessagePipeEndpoint(mp_1, 0);
74
75 channels_[0]->RunMessagePipeEndpoint(local_id_0, local_id_1);
76 channels_[1]->RunMessagePipeEndpoint(local_id_1, local_id_0);
77 }
78
79 protected:
80 base::MessageLoop* io_thread_message_loop() {
81 return io_thread_.message_loop();
82 }
83
84 scoped_refptr<base::TaskRunner> io_thread_task_runner() {
85 return io_thread_message_loop()->message_loop_proxy();
86 }
87
88 private:
89 void SetUpOnIOThread() {
90 CHECK_EQ(base::MessageLoop::current(), io_thread_message_loop());
91
92 // Create the socket.
93 int fds[2];
94 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
95
96 // Set the ends to non-blocking.
97 PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0);
98 PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0);
99
100 // Create and initialize |Channel|s.
101 channels_[0] = new Channel();
102 CHECK(channels_[0]->Init(PlatformChannelHandle(fds[0])));
103 channels_[1] = new Channel();
104 CHECK(channels_[1]->Init(PlatformChannelHandle(fds[1])));
105 }
106
107 void TearDownOnIOThread() {
108 channels_[1]->Shutdown();
109 channels_[1] = NULL;
110 channels_[0]->Shutdown();
111 channels_[0] = NULL;
112 }
113
114 base::Thread io_thread_;
115 scoped_refptr<Channel> channels_[2];
116
117 DISALLOW_COPY_AND_ASSIGN(RemoteMessagePipeTest);
118 };
119
120 TEST_F(RemoteMessagePipeTest, Basic) {
121 const char hello[] = "hello";
122 const char world[] = "world!!!1!!!1!";
123 char buffer[100] = { 0 };
124 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
125 Waiter waiter;
126
127 // Connect message pipes. MP 0, port 1 will be attached to channel 0 and
128 // connected to MP 1, port 0, which will be attached to channel 1. This leaves
129 // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints.
130
131 scoped_refptr<MessagePipe> mp_0(new MessagePipe(
132 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()),
133 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint())));
134 scoped_refptr<MessagePipe> mp_1(new MessagePipe(
135 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()),
136 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint())));
137 test::PostTaskAndWait(
138 io_thread_task_runner(),
139 FROM_HERE,
140 base::Bind(&RemoteMessagePipeTest::ConnectMessagePipesOnIOThread,
141 base::Unretained(this), mp_0, mp_1));
142
143 // Write in one direction: MP 0, port 0 -> ... -> MP 1, port 1.
144
145 // Prepare to wait on MP 1, port 1. (Add the waiter now. Otherwise, if we do
146 // it later, it might already be readable.)
147 waiter.Init();
148 EXPECT_EQ(MOJO_RESULT_OK,
149 mp_1->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_READABLE, 123));
150
151 // Write to MP 0, port 0.
152 EXPECT_EQ(MOJO_RESULT_OK,
153 mp_0->WriteMessage(0,
154 hello, sizeof(hello),
155 NULL, 0,
156 MOJO_WRITE_MESSAGE_FLAG_NONE));
157
158 // Wait.
159 EXPECT_EQ(123, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
160 mp_1->RemoveWaiter(1, &waiter);
161
162 // Read from MP 1, port 1.
163 EXPECT_EQ(MOJO_RESULT_OK,
164 mp_1->ReadMessage(1,
165 buffer, &buffer_size,
166 NULL, NULL,
167 MOJO_READ_MESSAGE_FLAG_NONE));
168 EXPECT_EQ(sizeof(hello), static_cast<size_t>(buffer_size));
169 EXPECT_EQ(0, strcmp(buffer, hello));
170
171 // Write in the other direction: MP 1, port 1 -> ... -> MP 0, port 0.
172
173 waiter.Init();
174 EXPECT_EQ(MOJO_RESULT_OK,
175 mp_0->AddWaiter(0, &waiter, MOJO_WAIT_FLAG_READABLE, 456));
176
177 EXPECT_EQ(MOJO_RESULT_OK,
178 mp_1->WriteMessage(1,
179 world, sizeof(world),
180 NULL, 0,
181 MOJO_WRITE_MESSAGE_FLAG_NONE));
182
183 EXPECT_EQ(456, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
184 mp_0->RemoveWaiter(0, &waiter);
185
186 buffer_size = static_cast<uint32_t>(sizeof(buffer));
187 EXPECT_EQ(MOJO_RESULT_OK,
188 mp_0->ReadMessage(0,
189 buffer, &buffer_size,
190 NULL, NULL,
191 MOJO_READ_MESSAGE_FLAG_NONE));
192 EXPECT_EQ(sizeof(world), static_cast<size_t>(buffer_size));
193 EXPECT_EQ(0, strcmp(buffer, world));
194
195 // Close MP 0, port 0.
196 mp_0->Close(0);
197
198 // Try to wait for MP 1, port 1 to become readable. This will eventually fail
199 // when it realizes that MP 0, port 0 has been closed. (It may also fail
200 // immediately.)
201 waiter.Init();
202 MojoResult result = mp_1->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_READABLE, 789);
203 if (result == MOJO_RESULT_OK) {
204 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
205 waiter.Wait(MOJO_DEADLINE_INDEFINITE));
206 mp_1->RemoveWaiter(1, &waiter);
207 } else {
208 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
209 }
210
211 // And MP 1, port 1.
212 mp_1->Close(1);
213 }
214
215 TEST_F(RemoteMessagePipeTest, Multiplex) {
216 const char hello[] = "hello";
217 const char world[] = "world!!!1!!!1!";
218 char buffer[100] = { 0 };
219 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
220 Waiter waiter;
221
222 // Connect message pipes as in the |Basic| test.
223
224 scoped_refptr<MessagePipe> mp_0(new MessagePipe(
225 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()),
226 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint())));
227 scoped_refptr<MessagePipe> mp_1(new MessagePipe(
228 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()),
229 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint())));
230 test::PostTaskAndWait(
231 io_thread_task_runner(),
232 FROM_HERE,
233 base::Bind(&RemoteMessagePipeTest::ConnectMessagePipesOnIOThread,
234 base::Unretained(this), mp_0, mp_1));
235
236 // Now put another message pipe on the channel.
237
238 scoped_refptr<MessagePipe> mp_2(new MessagePipe(
239 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()),
240 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint())));
241 scoped_refptr<MessagePipe> mp_3(new MessagePipe(
242 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()),
243 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint())));
244 test::PostTaskAndWait(
245 io_thread_task_runner(),
246 FROM_HERE,
247 base::Bind(&RemoteMessagePipeTest::ConnectMessagePipesOnIOThread,
248 base::Unretained(this), mp_2, mp_3));
249
250 // Write: MP 2, port 0 -> MP 3, port 1.
251
252 waiter.Init();
253 EXPECT_EQ(MOJO_RESULT_OK,
254 mp_3->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_READABLE, 789));
255
256 EXPECT_EQ(MOJO_RESULT_OK,
257 mp_2->WriteMessage(0,
258 hello, sizeof(hello),
259 NULL, 0,
260 MOJO_WRITE_MESSAGE_FLAG_NONE));
261
262 EXPECT_EQ(789, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
263 mp_3->RemoveWaiter(1, &waiter);
264
265 // Make sure there's nothing on MP 0, port 0 or MP 1, port 1 or MP 2, port 0.
266 buffer_size = static_cast<uint32_t>(sizeof(buffer));
267 EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
268 mp_0->ReadMessage(0,
269 buffer, &buffer_size,
270 NULL, NULL,
271 MOJO_READ_MESSAGE_FLAG_NONE));
272 buffer_size = static_cast<uint32_t>(sizeof(buffer));
273 EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
274 mp_1->ReadMessage(1,
275 buffer, &buffer_size,
276 NULL, NULL,
277 MOJO_READ_MESSAGE_FLAG_NONE));
278 buffer_size = static_cast<uint32_t>(sizeof(buffer));
279 EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
280 mp_2->ReadMessage(0,
281 buffer, &buffer_size,
282 NULL, NULL,
283 MOJO_READ_MESSAGE_FLAG_NONE));
284
285 // Read from MP 3, port 1.
286 buffer_size = static_cast<uint32_t>(sizeof(buffer));
287 EXPECT_EQ(MOJO_RESULT_OK,
288 mp_3->ReadMessage(1,
289 buffer, &buffer_size,
290 NULL, NULL,
291 MOJO_READ_MESSAGE_FLAG_NONE));
292 EXPECT_EQ(sizeof(hello), static_cast<size_t>(buffer_size));
293 EXPECT_EQ(0, strcmp(buffer, hello));
294
295 // Write: MP 0, port 0 -> MP 1, port 1 again.
296
297 waiter.Init();
298 EXPECT_EQ(MOJO_RESULT_OK,
299 mp_1->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_READABLE, 123));
300
301 EXPECT_EQ(MOJO_RESULT_OK,
302 mp_0->WriteMessage(0,
303 world, sizeof(world),
304 NULL, 0,
305 MOJO_WRITE_MESSAGE_FLAG_NONE));
306
307 EXPECT_EQ(123, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
308 mp_1->RemoveWaiter(1, &waiter);
309
310 // Make sure there's nothing on the other ports.
311 buffer_size = static_cast<uint32_t>(sizeof(buffer));
312 EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
313 mp_0->ReadMessage(0,
314 buffer, &buffer_size,
315 NULL, NULL,
316 MOJO_READ_MESSAGE_FLAG_NONE));
317 buffer_size = static_cast<uint32_t>(sizeof(buffer));
318 EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
319 mp_2->ReadMessage(0,
320 buffer, &buffer_size,
321 NULL, NULL,
322 MOJO_READ_MESSAGE_FLAG_NONE));
323 buffer_size = static_cast<uint32_t>(sizeof(buffer));
324 EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
325 mp_3->ReadMessage(1,
326 buffer, &buffer_size,
327 NULL, NULL,
328 MOJO_READ_MESSAGE_FLAG_NONE));
329
330 buffer_size = static_cast<uint32_t>(sizeof(buffer));
331 EXPECT_EQ(MOJO_RESULT_OK,
332 mp_1->ReadMessage(1,
333 buffer, &buffer_size,
334 NULL, NULL,
335 MOJO_READ_MESSAGE_FLAG_NONE));
336 EXPECT_EQ(sizeof(world), static_cast<size_t>(buffer_size));
337 EXPECT_EQ(0, strcmp(buffer, world));
338 }
339
340 } // namespace
341 } // namespace system
342 } // namespace mojo
OLDNEW
« base/compiler_specific.h ('K') | « mojo/system/raw_channel_win.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698