OLD | NEW |
| (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. |test::EpsilonTimeout()| may be increased to | |
7 // increase tolerance and reduce observed flakiness (though doing so reduces the | |
8 // meaningfulness of the test). | |
9 | |
10 #include "mojo/system/simple_dispatcher.h" | |
11 | |
12 #include "base/logging.h" | |
13 #include "base/macros.h" | |
14 #include "base/memory/ref_counted.h" | |
15 #include "base/memory/scoped_vector.h" | |
16 #include "base/synchronization/lock.h" | |
17 #include "base/threading/platform_thread.h" // For |Sleep()|. | |
18 #include "base/time/time.h" | |
19 #include "mojo/system/test_utils.h" | |
20 #include "mojo/system/waiter.h" | |
21 #include "mojo/system/waiter_test_utils.h" | |
22 #include "testing/gtest/include/gtest/gtest.h" | |
23 | |
24 namespace mojo { | |
25 namespace system { | |
26 namespace { | |
27 | |
28 class MockSimpleDispatcher : public SimpleDispatcher { | |
29 public: | |
30 MockSimpleDispatcher() | |
31 : state_(MOJO_HANDLE_SIGNAL_NONE, | |
32 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE) {} | |
33 | |
34 void SetSatisfiedSignals(MojoHandleSignals new_satisfied_signals) { | |
35 base::AutoLock locker(lock()); | |
36 | |
37 // Any new signals that are set should be satisfiable. | |
38 CHECK_EQ(new_satisfied_signals & ~state_.satisfied_signals, | |
39 new_satisfied_signals & ~state_.satisfied_signals & | |
40 state_.satisfiable_signals); | |
41 | |
42 if (new_satisfied_signals == state_.satisfied_signals) | |
43 return; | |
44 | |
45 state_.satisfied_signals = new_satisfied_signals; | |
46 HandleSignalsStateChangedNoLock(); | |
47 } | |
48 | |
49 void SetSatisfiableSignals(MojoHandleSignals new_satisfiable_signals) { | |
50 base::AutoLock locker(lock()); | |
51 | |
52 // Satisfied implies satisfiable. | |
53 CHECK_EQ(new_satisfiable_signals & state_.satisfied_signals, | |
54 state_.satisfied_signals); | |
55 | |
56 if (new_satisfiable_signals == state_.satisfiable_signals) | |
57 return; | |
58 | |
59 state_.satisfiable_signals = new_satisfiable_signals; | |
60 HandleSignalsStateChangedNoLock(); | |
61 } | |
62 | |
63 virtual Type GetType() const override { return kTypeUnknown; } | |
64 | |
65 private: | |
66 friend class base::RefCountedThreadSafe<MockSimpleDispatcher>; | |
67 virtual ~MockSimpleDispatcher() {} | |
68 | |
69 virtual scoped_refptr<Dispatcher> | |
70 CreateEquivalentDispatcherAndCloseImplNoLock() override { | |
71 scoped_refptr<MockSimpleDispatcher> rv(new MockSimpleDispatcher()); | |
72 rv->state_ = state_; | |
73 return scoped_refptr<Dispatcher>(rv.get()); | |
74 } | |
75 | |
76 // |Dispatcher| override: | |
77 virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const override { | |
78 lock().AssertAcquired(); | |
79 return state_; | |
80 } | |
81 | |
82 // Protected by |lock()|: | |
83 HandleSignalsState state_; | |
84 | |
85 DISALLOW_COPY_AND_ASSIGN(MockSimpleDispatcher); | |
86 }; | |
87 | |
88 #if defined(OS_WIN) | |
89 // http://crbug.com/396404 | |
90 #define MAYBE_Basic DISABLED_Basic | |
91 #else | |
92 #define MAYBE_Basic Basic | |
93 #endif | |
94 TEST(SimpleDispatcherTest, MAYBE_Basic) { | |
95 test::Stopwatch stopwatch; | |
96 | |
97 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
98 Waiter w; | |
99 uint32_t context = 0; | |
100 HandleSignalsState hss; | |
101 | |
102 // Try adding a readable waiter when already readable. | |
103 w.Init(); | |
104 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
105 hss = HandleSignalsState(); | |
106 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, | |
107 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); | |
108 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
109 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
110 hss.satisfiable_signals); | |
111 // Shouldn't need to remove the waiter (it was not added). | |
112 | |
113 // Wait (forever) for writable when already writable. | |
114 w.Init(); | |
115 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
116 ASSERT_EQ(MOJO_RESULT_OK, | |
117 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, nullptr)); | |
118 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); | |
119 stopwatch.Start(); | |
120 EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
121 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
122 EXPECT_EQ(1u, context); | |
123 hss = HandleSignalsState(); | |
124 d->RemoveWaiter(&w, &hss); | |
125 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | |
126 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
127 hss.satisfiable_signals); | |
128 | |
129 // Wait for zero time for writable when already writable. | |
130 w.Init(); | |
131 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
132 ASSERT_EQ(MOJO_RESULT_OK, | |
133 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); | |
134 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); | |
135 stopwatch.Start(); | |
136 EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, &context)); | |
137 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
138 EXPECT_EQ(2u, context); | |
139 hss = HandleSignalsState(); | |
140 d->RemoveWaiter(&w, &hss); | |
141 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | |
142 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
143 hss.satisfiable_signals); | |
144 | |
145 // Wait for non-zero, finite time for writable when already writable. | |
146 w.Init(); | |
147 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
148 ASSERT_EQ(MOJO_RESULT_OK, | |
149 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); | |
150 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); | |
151 stopwatch.Start(); | |
152 EXPECT_EQ(MOJO_RESULT_OK, | |
153 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context)); | |
154 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
155 EXPECT_EQ(3u, context); | |
156 hss = HandleSignalsState(); | |
157 d->RemoveWaiter(&w, &hss); | |
158 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | |
159 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
160 hss.satisfiable_signals); | |
161 | |
162 // Wait for zero time for writable when not writable (will time out). | |
163 w.Init(); | |
164 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
165 ASSERT_EQ(MOJO_RESULT_OK, | |
166 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); | |
167 stopwatch.Start(); | |
168 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); | |
169 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
170 hss = HandleSignalsState(); | |
171 d->RemoveWaiter(&w, &hss); | |
172 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
173 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
174 hss.satisfiable_signals); | |
175 | |
176 // Wait for non-zero, finite time for writable when not writable (will time | |
177 // out). | |
178 w.Init(); | |
179 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
180 ASSERT_EQ(MOJO_RESULT_OK, | |
181 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5, nullptr)); | |
182 stopwatch.Start(); | |
183 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, | |
184 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), nullptr)); | |
185 base::TimeDelta elapsed = stopwatch.Elapsed(); | |
186 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
187 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
188 hss = HandleSignalsState(); | |
189 d->RemoveWaiter(&w, &hss); | |
190 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
191 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
192 hss.satisfiable_signals); | |
193 | |
194 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
195 } | |
196 | |
197 TEST(SimpleDispatcherTest, BasicUnsatisfiable) { | |
198 test::Stopwatch stopwatch; | |
199 | |
200 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
201 Waiter w; | |
202 uint32_t context = 0; | |
203 HandleSignalsState hss; | |
204 | |
205 // Try adding a writable waiter when it can never be writable. | |
206 w.Init(); | |
207 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
208 d->SetSatisfiedSignals(0); | |
209 hss = HandleSignalsState(); | |
210 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
211 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); | |
212 EXPECT_EQ(0u, hss.satisfied_signals); | |
213 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | |
214 // Shouldn't need to remove the waiter (it was not added). | |
215 | |
216 // Wait (forever) for writable and then it becomes never writable. | |
217 w.Init(); | |
218 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | | |
219 MOJO_HANDLE_SIGNAL_WRITABLE); | |
220 ASSERT_EQ(MOJO_RESULT_OK, | |
221 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); | |
222 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
223 stopwatch.Start(); | |
224 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
225 w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
226 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
227 EXPECT_EQ(2u, context); | |
228 hss = HandleSignalsState(); | |
229 d->RemoveWaiter(&w, &hss); | |
230 EXPECT_EQ(0u, hss.satisfied_signals); | |
231 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | |
232 | |
233 // Wait for zero time for writable and then it becomes never writable. | |
234 w.Init(); | |
235 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | | |
236 MOJO_HANDLE_SIGNAL_WRITABLE); | |
237 ASSERT_EQ(MOJO_RESULT_OK, | |
238 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); | |
239 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
240 stopwatch.Start(); | |
241 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context)); | |
242 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
243 EXPECT_EQ(3u, context); | |
244 hss = HandleSignalsState(); | |
245 d->RemoveWaiter(&w, &hss); | |
246 EXPECT_EQ(0u, hss.satisfied_signals); | |
247 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | |
248 | |
249 // Wait for non-zero, finite time for writable and then it becomes never | |
250 // writable. | |
251 w.Init(); | |
252 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | | |
253 MOJO_HANDLE_SIGNAL_WRITABLE); | |
254 ASSERT_EQ(MOJO_RESULT_OK, | |
255 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); | |
256 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
257 stopwatch.Start(); | |
258 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
259 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context)); | |
260 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
261 EXPECT_EQ(4u, context); | |
262 hss = HandleSignalsState(); | |
263 d->RemoveWaiter(&w, &hss); | |
264 EXPECT_EQ(0u, hss.satisfied_signals); | |
265 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | |
266 | |
267 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
268 } | |
269 | |
270 TEST(SimpleDispatcherTest, BasicClosed) { | |
271 test::Stopwatch stopwatch; | |
272 | |
273 scoped_refptr<MockSimpleDispatcher> d; | |
274 Waiter w; | |
275 uint32_t context = 0; | |
276 HandleSignalsState hss; | |
277 | |
278 // Try adding a writable waiter when the dispatcher has been closed. | |
279 d = new MockSimpleDispatcher(); | |
280 w.Init(); | |
281 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
282 hss = HandleSignalsState(); | |
283 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
284 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); | |
285 EXPECT_EQ(0u, hss.satisfied_signals); | |
286 EXPECT_EQ(0u, hss.satisfiable_signals); | |
287 // Shouldn't need to remove the waiter (it was not added). | |
288 | |
289 // Wait (forever) for writable and then the dispatcher is closed. | |
290 d = new MockSimpleDispatcher(); | |
291 w.Init(); | |
292 ASSERT_EQ(MOJO_RESULT_OK, | |
293 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); | |
294 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
295 stopwatch.Start(); | |
296 EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
297 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
298 EXPECT_EQ(2u, context); | |
299 // Don't need to remove waiters from closed dispatchers. | |
300 | |
301 // Wait for zero time for writable and then the dispatcher is closed. | |
302 d = new MockSimpleDispatcher(); | |
303 w.Init(); | |
304 ASSERT_EQ(MOJO_RESULT_OK, | |
305 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); | |
306 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
307 stopwatch.Start(); | |
308 EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context)); | |
309 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
310 EXPECT_EQ(3u, context); | |
311 // Don't need to remove waiters from closed dispatchers. | |
312 | |
313 // Wait for non-zero, finite time for writable and then the dispatcher is | |
314 // closed. | |
315 d = new MockSimpleDispatcher(); | |
316 w.Init(); | |
317 ASSERT_EQ(MOJO_RESULT_OK, | |
318 d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); | |
319 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
320 stopwatch.Start(); | |
321 EXPECT_EQ(MOJO_RESULT_CANCELLED, | |
322 w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context)); | |
323 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
324 EXPECT_EQ(4u, context); | |
325 // Don't need to remove waiters from closed dispatchers. | |
326 } | |
327 | |
328 #if defined(OS_WIN) | |
329 // http://crbug.com/396393 | |
330 #define MAYBE_BasicThreaded DISABLED_BasicThreaded | |
331 #else | |
332 #define MAYBE_BasicThreaded BasicThreaded | |
333 #endif | |
334 TEST(SimpleDispatcherTest, MAYBE_BasicThreaded) { | |
335 test::Stopwatch stopwatch; | |
336 bool did_wait; | |
337 MojoResult result; | |
338 uint32_t context; | |
339 HandleSignalsState hss; | |
340 | |
341 // Wait for readable (already readable). | |
342 { | |
343 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
344 { | |
345 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
346 test::WaiterThread thread(d, | |
347 MOJO_HANDLE_SIGNAL_READABLE, | |
348 MOJO_DEADLINE_INDEFINITE, | |
349 1, | |
350 &did_wait, | |
351 &result, | |
352 &context, | |
353 &hss); | |
354 stopwatch.Start(); | |
355 thread.Start(); | |
356 } // Joins the thread. | |
357 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. | |
358 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
359 } | |
360 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
361 EXPECT_FALSE(did_wait); | |
362 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); | |
363 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
364 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
365 hss.satisfiable_signals); | |
366 | |
367 // Wait for readable and becomes readable after some time. | |
368 { | |
369 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
370 { | |
371 test::WaiterThread thread(d, | |
372 MOJO_HANDLE_SIGNAL_READABLE, | |
373 MOJO_DEADLINE_INDEFINITE, | |
374 2, | |
375 &did_wait, | |
376 &result, | |
377 &context, | |
378 &hss); | |
379 stopwatch.Start(); | |
380 thread.Start(); | |
381 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
382 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
383 } // Joins the thread. | |
384 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
385 } | |
386 base::TimeDelta elapsed = stopwatch.Elapsed(); | |
387 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
388 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
389 EXPECT_TRUE(did_wait); | |
390 EXPECT_EQ(MOJO_RESULT_OK, result); | |
391 EXPECT_EQ(2u, context); | |
392 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
393 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
394 hss.satisfiable_signals); | |
395 | |
396 // Wait for readable and becomes never-readable after some time. | |
397 { | |
398 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
399 { | |
400 test::WaiterThread thread(d, | |
401 MOJO_HANDLE_SIGNAL_READABLE, | |
402 MOJO_DEADLINE_INDEFINITE, | |
403 3, | |
404 &did_wait, | |
405 &result, | |
406 &context, | |
407 &hss); | |
408 stopwatch.Start(); | |
409 thread.Start(); | |
410 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
411 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE); | |
412 } // Joins the thread. | |
413 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
414 } | |
415 elapsed = stopwatch.Elapsed(); | |
416 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
417 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
418 EXPECT_TRUE(did_wait); | |
419 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
420 EXPECT_EQ(3u, context); | |
421 EXPECT_EQ(0u, hss.satisfied_signals); | |
422 EXPECT_EQ(0u, hss.satisfiable_signals); | |
423 | |
424 // Wait for readable and dispatcher gets closed. | |
425 { | |
426 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
427 test::WaiterThread thread(d, | |
428 MOJO_HANDLE_SIGNAL_READABLE, | |
429 MOJO_DEADLINE_INDEFINITE, | |
430 4, | |
431 &did_wait, | |
432 &result, | |
433 &context, | |
434 &hss); | |
435 stopwatch.Start(); | |
436 thread.Start(); | |
437 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
438 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
439 } // Joins the thread. | |
440 elapsed = stopwatch.Elapsed(); | |
441 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
442 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
443 EXPECT_TRUE(did_wait); | |
444 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | |
445 EXPECT_EQ(4u, context); | |
446 EXPECT_EQ(0u, hss.satisfied_signals); | |
447 EXPECT_EQ(0u, hss.satisfiable_signals); | |
448 | |
449 // Wait for readable and times out. | |
450 { | |
451 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
452 { | |
453 test::WaiterThread thread(d, | |
454 MOJO_HANDLE_SIGNAL_READABLE, | |
455 2 * test::EpsilonTimeout().InMicroseconds(), | |
456 5, | |
457 &did_wait, | |
458 &result, | |
459 &context, | |
460 &hss); | |
461 stopwatch.Start(); | |
462 thread.Start(); | |
463 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | |
464 // Not what we're waiting for. | |
465 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); | |
466 } // Joins the thread (after its wait times out). | |
467 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. | |
468 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
469 } | |
470 elapsed = stopwatch.Elapsed(); | |
471 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
472 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
473 EXPECT_TRUE(did_wait); | |
474 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result); | |
475 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | |
476 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
477 hss.satisfiable_signals); | |
478 } | |
479 | |
480 #if defined(OS_WIN) | |
481 // http://crbug.com/387124 | |
482 #define MAYBE_MultipleWaiters DISABLED_MultipleWaiters | |
483 #else | |
484 #define MAYBE_MultipleWaiters MultipleWaiters | |
485 #endif | |
486 TEST(SimpleDispatcherTest, MAYBE_MultipleWaiters) { | |
487 static const uint32_t kNumWaiters = 20; | |
488 | |
489 bool did_wait[kNumWaiters]; | |
490 MojoResult result[kNumWaiters]; | |
491 uint32_t context[kNumWaiters]; | |
492 HandleSignalsState hss[kNumWaiters]; | |
493 | |
494 // All wait for readable and becomes readable after some time. | |
495 { | |
496 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
497 ScopedVector<test::WaiterThread> threads; | |
498 for (uint32_t i = 0; i < kNumWaiters; i++) { | |
499 threads.push_back(new test::WaiterThread(d, | |
500 MOJO_HANDLE_SIGNAL_READABLE, | |
501 MOJO_DEADLINE_INDEFINITE, | |
502 i, | |
503 &did_wait[i], | |
504 &result[i], | |
505 &context[i], | |
506 &hss[i])); | |
507 threads.back()->Start(); | |
508 } | |
509 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
510 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
511 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
512 } // Joins the threads. | |
513 for (uint32_t i = 0; i < kNumWaiters; i++) { | |
514 EXPECT_TRUE(did_wait[i]) << i; | |
515 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
516 EXPECT_EQ(i, context[i]) << i; | |
517 // Since we closed before joining, we can't say much about what each thread | |
518 // saw as the state. | |
519 } | |
520 | |
521 // Some wait for readable, some for writable, and becomes readable after some | |
522 // time. | |
523 { | |
524 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
525 ScopedVector<test::WaiterThread> threads; | |
526 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
527 threads.push_back(new test::WaiterThread(d, | |
528 MOJO_HANDLE_SIGNAL_READABLE, | |
529 MOJO_DEADLINE_INDEFINITE, | |
530 i, | |
531 &did_wait[i], | |
532 &result[i], | |
533 &context[i], | |
534 &hss[i])); | |
535 threads.back()->Start(); | |
536 } | |
537 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
538 threads.push_back(new test::WaiterThread(d, | |
539 MOJO_HANDLE_SIGNAL_WRITABLE, | |
540 MOJO_DEADLINE_INDEFINITE, | |
541 i, | |
542 &did_wait[i], | |
543 &result[i], | |
544 &context[i], | |
545 &hss[i])); | |
546 threads.back()->Start(); | |
547 } | |
548 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
549 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
550 // This will wake up the ones waiting to write. | |
551 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
552 } // Joins the threads. | |
553 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
554 EXPECT_TRUE(did_wait[i]) << i; | |
555 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
556 EXPECT_EQ(i, context[i]) << i; | |
557 // Since we closed before joining, we can't say much about what each thread | |
558 // saw as the state. | |
559 } | |
560 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
561 EXPECT_TRUE(did_wait[i]) << i; | |
562 EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]) << i; | |
563 EXPECT_EQ(i, context[i]) << i; | |
564 // Since we closed before joining, we can't say much about what each thread | |
565 // saw as the state. | |
566 } | |
567 | |
568 // Some wait for readable, some for writable, and becomes readable and | |
569 // never-writable after some time. | |
570 { | |
571 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
572 ScopedVector<test::WaiterThread> threads; | |
573 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
574 threads.push_back(new test::WaiterThread(d, | |
575 MOJO_HANDLE_SIGNAL_READABLE, | |
576 MOJO_DEADLINE_INDEFINITE, | |
577 i, | |
578 &did_wait[i], | |
579 &result[i], | |
580 &context[i], | |
581 &hss[i])); | |
582 threads.back()->Start(); | |
583 } | |
584 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
585 threads.push_back(new test::WaiterThread(d, | |
586 MOJO_HANDLE_SIGNAL_WRITABLE, | |
587 MOJO_DEADLINE_INDEFINITE, | |
588 i, | |
589 &did_wait[i], | |
590 &result[i], | |
591 &context[i], | |
592 &hss[i])); | |
593 threads.back()->Start(); | |
594 } | |
595 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | |
596 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
597 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | |
598 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
599 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
600 } // Joins the threads. | |
601 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
602 EXPECT_TRUE(did_wait[i]) << i; | |
603 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
604 EXPECT_EQ(i, context[i]) << i; | |
605 // Since we closed before joining, we can't say much about what each thread | |
606 // saw as the state. | |
607 } | |
608 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
609 EXPECT_TRUE(did_wait[i]) << i; | |
610 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]) << i; | |
611 EXPECT_EQ(i, context[i]) << i; | |
612 // Since we closed before joining, we can't say much about what each thread | |
613 // saw as the state. | |
614 } | |
615 | |
616 // Some wait for readable, some for writable, and becomes readable after some | |
617 // time. | |
618 { | |
619 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
620 ScopedVector<test::WaiterThread> threads; | |
621 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
622 threads.push_back( | |
623 new test::WaiterThread(d, | |
624 MOJO_HANDLE_SIGNAL_READABLE, | |
625 3 * test::EpsilonTimeout().InMicroseconds(), | |
626 i, | |
627 &did_wait[i], | |
628 &result[i], | |
629 &context[i], | |
630 &hss[i])); | |
631 threads.back()->Start(); | |
632 } | |
633 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
634 threads.push_back( | |
635 new test::WaiterThread(d, | |
636 MOJO_HANDLE_SIGNAL_WRITABLE, | |
637 1 * test::EpsilonTimeout().InMicroseconds(), | |
638 i, | |
639 &did_wait[i], | |
640 &result[i], | |
641 &context[i], | |
642 &hss[i])); | |
643 threads.back()->Start(); | |
644 } | |
645 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
646 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
647 // All those waiting for writable should have timed out. | |
648 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
649 } // Joins the threads. | |
650 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
651 EXPECT_TRUE(did_wait[i]) << i; | |
652 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
653 EXPECT_EQ(i, context[i]) << i; | |
654 // Since we closed before joining, we can't say much about what each thread | |
655 // saw as the state. | |
656 } | |
657 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
658 EXPECT_TRUE(did_wait[i]) << i; | |
659 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]) << i; | |
660 // Since we closed before joining, we can't say much about what each thread | |
661 // saw as the state. | |
662 } | |
663 } | |
664 | |
665 // TODO(vtl): Stress test? | |
666 | |
667 } // namespace | |
668 } // namespace system | |
669 } // namespace mojo | |
OLD | NEW |