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

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

Issue 23621056: Initial in-process implementation of some Mojo primitives. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: wip18.1 Created 7 years, 3 months 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
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 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
6 // heavily-loaded system). Sorry. |kEpsilonMicros| may be increased to increase
7 // tolerance and reduce observed flakiness.
8
9 #include "mojo/system/message_pipe_dispatcher.h"
10
11 #include "base/memory/ref_counted.h"
12 #include "base/threading/platform_thread.h" // For |Sleep()|.
13 #include "base/time/time.h"
14 #include "mojo/system/message_pipe.h"
15 #include "mojo/system/test_utils.h"
16 #include "mojo/system/waiter.h"
17 #include "mojo/system/waiter_test_utils.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace mojo {
21 namespace system {
22 namespace {
23
24 const int64_t kMicrosPerMs = 1000;
25 const int64_t kEpsilonMicros = 15 * kMicrosPerMs; // 15 ms.
26
27 TEST(MessagePipeDispatcherTest, Basic) {
28 test::Stopwatch stopwatch;
29 int32_t buffer[1];
30 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
31 uint32_t buffer_size;
32 int64_t elapsed_micros;
33
34 // Run this test both with |d_0| as port 0, |d_1| as port 1 and vice versa.
35 for (unsigned i = 0; i < 2; i++) {
36 scoped_refptr<MessagePipeDispatcher> d_0(new MessagePipeDispatcher());
37 scoped_refptr<MessagePipeDispatcher> d_1(new MessagePipeDispatcher());
38 {
39 scoped_refptr<MessagePipe> mp(new MessagePipe());
40 d_0->Init(mp, i); // 0, 1.
41 d_1->Init(mp, i ^ 1); // 1, 0.
42 }
43 Waiter w;
44
45 // Try adding a writable waiter when already writable.
46 w.Init();
47 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
48 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 0));
49 // Shouldn't need to remove the waiter (it was not added).
50
51 // Add a readable waiter to |d_0|, then make it readable (by writing to
52 // |d_1|), then wait.
53 w.Init();
54 EXPECT_EQ(MOJO_RESULT_OK,
55 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 1));
56 buffer[0] = 123456789;
57 EXPECT_EQ(MOJO_RESULT_OK,
58 d_1->WriteMessage(buffer, kBufferSize,
59 NULL, 0,
60 MOJO_WRITE_MESSAGE_FLAG_NONE));
61 stopwatch.Start();
62 EXPECT_EQ(1, w.Wait(MOJO_DEADLINE_INDEFINITE));
63 elapsed_micros = stopwatch.Elapsed();
64 EXPECT_LT(elapsed_micros, kEpsilonMicros);
65 d_0->RemoveWaiter(&w);
66
67 // Try adding a readable waiter when already readable (from above).
68 w.Init();
69 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
70 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 2));
71 // Shouldn't need to remove the waiter (it was not added).
72
73 // Make |d_0| no longer readable (by reading from it).
74 buffer[0] = 0;
75 buffer_size = kBufferSize;
76 EXPECT_EQ(MOJO_RESULT_OK,
77 d_0->ReadMessage(buffer, &buffer_size,
78 NULL, NULL,
79 MOJO_READ_MESSAGE_FLAG_NONE));
80 EXPECT_EQ(kBufferSize, buffer_size);
81 EXPECT_EQ(123456789, buffer[0]);
82
83 // Wait for zero time for readability on |d_0| (will time out).
84 w.Init();
85 EXPECT_EQ(MOJO_RESULT_OK,
86 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3));
87 stopwatch.Start();
88 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0));
89 elapsed_micros = stopwatch.Elapsed();
90 EXPECT_LT(elapsed_micros, kEpsilonMicros);
91 d_0->RemoveWaiter(&w);
92
93 // Wait for non-zero, finite time for readability on |d_0| (will time out).
94 w.Init();
95 EXPECT_EQ(MOJO_RESULT_OK,
96 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3));
97 stopwatch.Start();
98 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(2 * kEpsilonMicros));
99 elapsed_micros = stopwatch.Elapsed();
100 EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros);
101 EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros);
102 d_0->RemoveWaiter(&w);
103
104 EXPECT_EQ(MOJO_RESULT_OK, d_0->Close());
105 EXPECT_EQ(MOJO_RESULT_OK, d_1->Close());
106 }
107 }
108
109 // Test what happens when one end is closed (single-threaded test).
110 TEST(MessagePipeDispatcherTest, BasicClosed) {
111 int32_t buffer[1];
112 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
113 uint32_t buffer_size;
114
115 // Run this test both with |d_0| as port 0, |d_1| as port 1 and vice versa.
116 for (unsigned i = 0; i < 2; i++) {
117 scoped_refptr<MessagePipeDispatcher> d_0(new MessagePipeDispatcher());
118 scoped_refptr<MessagePipeDispatcher> d_1(new MessagePipeDispatcher());
119 {
120 scoped_refptr<MessagePipe> mp(new MessagePipe());
121 d_0->Init(mp, i); // 0, 1.
122 d_1->Init(mp, i ^ 1); // 1, 0.
123 }
124 Waiter w;
125
126 // Write (twice) to |d_1|.
127 buffer[0] = 123456789;
128 EXPECT_EQ(MOJO_RESULT_OK,
129 d_1->WriteMessage(buffer, kBufferSize,
130 NULL, 0,
131 MOJO_WRITE_MESSAGE_FLAG_NONE));
132 buffer[0] = 234567890;
133 EXPECT_EQ(MOJO_RESULT_OK,
134 d_1->WriteMessage(buffer, kBufferSize,
135 NULL, 0,
136 MOJO_WRITE_MESSAGE_FLAG_NONE));
137
138 // Try waiting for readable on |d_0|; should fail (already satisfied).
139 w.Init();
140 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
141 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 0));
142
143 // Close |d_1|.
144 EXPECT_EQ(MOJO_RESULT_OK, d_1->Close());
145
146 // Try waiting for readable on |d_0|; should fail (already satisfied).
147 w.Init();
148 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
149 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 1));
150
151 // Read from |d_0|.
152 buffer[0] = 0;
153 buffer_size = kBufferSize;
154 EXPECT_EQ(MOJO_RESULT_OK,
155 d_0->ReadMessage(buffer, &buffer_size,
156 NULL, NULL,
157 MOJO_READ_MESSAGE_FLAG_NONE));
158 EXPECT_EQ(kBufferSize, buffer_size);
159 EXPECT_EQ(123456789, buffer[0]);
160
161 // Try waiting for readable on |d_0|; should fail (already satisfied).
162 w.Init();
163 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
164 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 2));
165
166 // Read again from |d_0|.
167 buffer[0] = 0;
168 buffer_size = kBufferSize;
169 EXPECT_EQ(MOJO_RESULT_OK,
170 d_0->ReadMessage(buffer, &buffer_size,
171 NULL, NULL,
172 MOJO_READ_MESSAGE_FLAG_NONE));
173 EXPECT_EQ(kBufferSize, buffer_size);
174 EXPECT_EQ(234567890, buffer[0]);
175
176 // Try waiting for readable on |d_0|; should fail (unsatisfiable).
177 w.Init();
178 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
179 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3));
180
181 // Try waiting for writable on |d_0|; should fail (unsatisfiable).
182 w.Init();
183 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
184 d_0->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 4));
185
186 // Try reading from |d_0|; should fail (nothing to read).
187 buffer[0] = 0;
188 buffer_size = kBufferSize;
189 EXPECT_EQ(MOJO_RESULT_NOT_FOUND,
190 d_0->ReadMessage(buffer, &buffer_size,
191 NULL, NULL,
192 MOJO_READ_MESSAGE_FLAG_NONE));
193
194 // Try writing to |d_0|; should fail (other end closed).
195 buffer[0] = 345678901;
196 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
197 d_0->WriteMessage(buffer, kBufferSize,
198 NULL, 0,
199 MOJO_WRITE_MESSAGE_FLAG_NONE));
200
201 EXPECT_EQ(MOJO_RESULT_OK, d_0->Close());
202 }
203 }
204
205 TEST(MessagePipeDispatcherTest, BasicThreaded) {
206 test::Stopwatch stopwatch;
207 int32_t buffer[1];
208 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
209 uint32_t buffer_size;
210 bool did_wait;
211 MojoResult result;
212 int64_t elapsed_micros;
213
214 // Run this test both with |d_0| as port 0, |d_1| as port 1 and vice versa.
215 for (unsigned i = 0; i < 2; i++) {
216 scoped_refptr<MessagePipeDispatcher> d_0(new MessagePipeDispatcher());
217 scoped_refptr<MessagePipeDispatcher> d_1(new MessagePipeDispatcher());
218 {
219 scoped_refptr<MessagePipe> mp(new MessagePipe());
220 d_0->Init(mp, i); // 0, 1.
221 d_1->Init(mp, i ^ 1); // 1, 0.
222 }
223
224 // Wait for readable on |d_1|, which will become readable after some time.
225 {
226 test::WaiterThread thread(d_1,
227 MOJO_WAIT_FLAG_READABLE,
228 MOJO_DEADLINE_INDEFINITE,
229 0,
230 &did_wait, &result);
231 stopwatch.Start();
232 thread.Start();
233 base::PlatformThread::Sleep(
234 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros));
235 // Wake it up by writing to |d_0|.
236 buffer[0] = 123456789;
237 EXPECT_EQ(MOJO_RESULT_OK,
238 d_0->WriteMessage(buffer, kBufferSize,
239 NULL, 0,
240 MOJO_WRITE_MESSAGE_FLAG_NONE));
241 } // Joins the thread.
242 elapsed_micros = stopwatch.Elapsed();
243 EXPECT_TRUE(did_wait);
244 EXPECT_EQ(0, result);
245 EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros);
246 EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros);
247
248 // Now |d_1| is already readable. Try waiting for it again.
249 {
250 test::WaiterThread thread(d_1,
251 MOJO_WAIT_FLAG_READABLE,
252 MOJO_DEADLINE_INDEFINITE,
253 1,
254 &did_wait, &result);
255 stopwatch.Start();
256 thread.Start();
257 } // Joins the thread.
258 elapsed_micros = stopwatch.Elapsed();
259 EXPECT_FALSE(did_wait);
260 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
261 EXPECT_LT(elapsed_micros, kEpsilonMicros);
262
263 // Consume what we wrote to |d_0|.
264 buffer[0] = 0;
265 buffer_size = kBufferSize;
266 EXPECT_EQ(MOJO_RESULT_OK,
267 d_1->ReadMessage(buffer, &buffer_size,
268 NULL, NULL,
269 MOJO_READ_MESSAGE_FLAG_NONE));
270 EXPECT_EQ(kBufferSize, buffer_size);
271 EXPECT_EQ(123456789, buffer[0]);
272
273 // Wait for readable on |d_1| and close |d_0| after some time, which should
274 // cancel that wait.
275 {
276 test::WaiterThread thread(d_1,
277 MOJO_WAIT_FLAG_READABLE,
278 MOJO_DEADLINE_INDEFINITE,
279 0,
280 &did_wait, &result);
281 stopwatch.Start();
282 thread.Start();
283 base::PlatformThread::Sleep(
284 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros));
285 EXPECT_EQ(MOJO_RESULT_OK, d_0->Close());
286 } // Joins the thread.
287 elapsed_micros = stopwatch.Elapsed();
288 EXPECT_TRUE(did_wait);
289 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
290 EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros);
291 EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros);
292
293 EXPECT_EQ(MOJO_RESULT_OK, d_1->Close());
294 }
295
296 for (unsigned i = 0; i < 2; i++) {
297 scoped_refptr<MessagePipeDispatcher> d_0(new MessagePipeDispatcher());
298 scoped_refptr<MessagePipeDispatcher> d_1(new MessagePipeDispatcher());
299 {
300 scoped_refptr<MessagePipe> mp(new MessagePipe());
301 d_0->Init(mp, i); // 0, 1.
302 d_1->Init(mp, i ^ 1); // 1, 0.
303 }
304
305 // Wait for readable on |d_1| and close |d_1| after some time, which should
306 // cancel that wait.
307 {
308 test::WaiterThread thread(d_1,
309 MOJO_WAIT_FLAG_READABLE,
310 MOJO_DEADLINE_INDEFINITE,
311 0,
312 &did_wait, &result);
313 stopwatch.Start();
314 thread.Start();
315 base::PlatformThread::Sleep(
316 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros));
317 EXPECT_EQ(MOJO_RESULT_OK, d_1->Close());
318 } // Joins the thread.
319 elapsed_micros = stopwatch.Elapsed();
320 EXPECT_TRUE(did_wait);
321 EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
322 EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros);
323 EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros);
324
325 EXPECT_EQ(MOJO_RESULT_OK, d_0->Close());
326 }
327 }
328
329 // TODO(vtl): Actually read/write on threads?
330 // TODO(vtl): Stress test?
331
332 } // namespace
333 } // namespace system
334 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698