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/edk/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/edk/system/test_utils.h" | |
20 #include "mojo/edk/system/waiter.h" | |
21 #include "mojo/edk/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 Type GetType() const override { return kTypeUnknown; } | |
64 | |
65 private: | |
66 friend class base::RefCountedThreadSafe<MockSimpleDispatcher>; | |
67 ~MockSimpleDispatcher() override {} | |
68 | |
69 scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() | |
70 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 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->AddAwakable(&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->AddAwakable(&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->RemoveAwakable(&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->AddAwakable(&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->RemoveAwakable(&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->AddAwakable(&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->RemoveAwakable(&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->AddAwakable(&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->RemoveAwakable(&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->AddAwakable(&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->RemoveAwakable(&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->AddAwakable(&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->AddAwakable(&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->RemoveAwakable(&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->AddAwakable(&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->RemoveAwakable(&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->AddAwakable(&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->RemoveAwakable(&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->AddAwakable(&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->AddAwakable(&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->AddAwakable(&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->AddAwakable(&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, MOJO_HANDLE_SIGNAL_READABLE, | |
347 MOJO_DEADLINE_INDEFINITE, 1, &did_wait, &result, | |
348 &context, &hss); | |
349 stopwatch.Start(); | |
350 thread.Start(); | |
351 } // Joins the thread. | |
352 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. | |
353 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
354 } | |
355 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); | |
356 EXPECT_FALSE(did_wait); | |
357 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); | |
358 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
359 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
360 hss.satisfiable_signals); | |
361 | |
362 // Wait for readable and becomes readable after some time. | |
363 { | |
364 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
365 { | |
366 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
367 MOJO_DEADLINE_INDEFINITE, 2, &did_wait, &result, | |
368 &context, &hss); | |
369 stopwatch.Start(); | |
370 thread.Start(); | |
371 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
372 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
373 } // Joins the thread. | |
374 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
375 } | |
376 base::TimeDelta elapsed = stopwatch.Elapsed(); | |
377 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
378 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
379 EXPECT_TRUE(did_wait); | |
380 EXPECT_EQ(MOJO_RESULT_OK, result); | |
381 EXPECT_EQ(2u, context); | |
382 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
383 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
384 hss.satisfiable_signals); | |
385 | |
386 // Wait for readable and becomes never-readable after some time. | |
387 { | |
388 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
389 { | |
390 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
391 MOJO_DEADLINE_INDEFINITE, 3, &did_wait, &result, | |
392 &context, &hss); | |
393 stopwatch.Start(); | |
394 thread.Start(); | |
395 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
396 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE); | |
397 } // Joins the thread. | |
398 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
399 } | |
400 elapsed = stopwatch.Elapsed(); | |
401 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
402 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
403 EXPECT_TRUE(did_wait); | |
404 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
405 EXPECT_EQ(3u, context); | |
406 EXPECT_EQ(0u, hss.satisfied_signals); | |
407 EXPECT_EQ(0u, hss.satisfiable_signals); | |
408 | |
409 // Wait for readable and dispatcher gets closed. | |
410 { | |
411 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
412 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
413 MOJO_DEADLINE_INDEFINITE, 4, &did_wait, &result, | |
414 &context, &hss); | |
415 stopwatch.Start(); | |
416 thread.Start(); | |
417 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
418 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
419 } // Joins the thread. | |
420 elapsed = stopwatch.Elapsed(); | |
421 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
422 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
423 EXPECT_TRUE(did_wait); | |
424 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | |
425 EXPECT_EQ(4u, context); | |
426 EXPECT_EQ(0u, hss.satisfied_signals); | |
427 EXPECT_EQ(0u, hss.satisfiable_signals); | |
428 | |
429 // Wait for readable and times out. | |
430 { | |
431 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
432 { | |
433 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
434 2 * test::EpsilonTimeout().InMicroseconds(), 5, | |
435 &did_wait, &result, &context, &hss); | |
436 stopwatch.Start(); | |
437 thread.Start(); | |
438 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | |
439 // Not what we're waiting for. | |
440 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); | |
441 } // Joins the thread (after its wait times out). | |
442 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. | |
443 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
444 } | |
445 elapsed = stopwatch.Elapsed(); | |
446 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); | |
447 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); | |
448 EXPECT_TRUE(did_wait); | |
449 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result); | |
450 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | |
451 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
452 hss.satisfiable_signals); | |
453 } | |
454 | |
455 #if defined(OS_WIN) | |
456 // http://crbug.com/387124 | |
457 #define MAYBE_MultipleWaiters DISABLED_MultipleWaiters | |
458 #else | |
459 #define MAYBE_MultipleWaiters MultipleWaiters | |
460 #endif | |
461 TEST(SimpleDispatcherTest, MAYBE_MultipleWaiters) { | |
462 static const uint32_t kNumWaiters = 20; | |
463 | |
464 bool did_wait[kNumWaiters]; | |
465 MojoResult result[kNumWaiters]; | |
466 uint32_t context[kNumWaiters]; | |
467 HandleSignalsState hss[kNumWaiters]; | |
468 | |
469 // All wait for readable and becomes readable after some time. | |
470 { | |
471 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
472 ScopedVector<test::WaiterThread> threads; | |
473 for (uint32_t i = 0; i < kNumWaiters; i++) { | |
474 threads.push_back(new test::WaiterThread( | |
475 d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, | |
476 &did_wait[i], &result[i], &context[i], &hss[i])); | |
477 threads.back()->Start(); | |
478 } | |
479 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
480 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
481 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
482 } // Joins the threads. | |
483 for (uint32_t i = 0; i < kNumWaiters; i++) { | |
484 EXPECT_TRUE(did_wait[i]) << i; | |
485 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
486 EXPECT_EQ(i, context[i]) << i; | |
487 // Since we closed before joining, we can't say much about what each thread | |
488 // saw as the state. | |
489 } | |
490 | |
491 // Some wait for readable, some for writable, and becomes readable after some | |
492 // time. | |
493 { | |
494 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
495 ScopedVector<test::WaiterThread> threads; | |
496 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
497 threads.push_back(new test::WaiterThread( | |
498 d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, | |
499 &did_wait[i], &result[i], &context[i], &hss[i])); | |
500 threads.back()->Start(); | |
501 } | |
502 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
503 threads.push_back(new test::WaiterThread( | |
504 d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i, | |
505 &did_wait[i], &result[i], &context[i], &hss[i])); | |
506 threads.back()->Start(); | |
507 } | |
508 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
509 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
510 // This will wake up the ones waiting to write. | |
511 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
512 } // Joins the threads. | |
513 for (uint32_t i = 0; i < kNumWaiters / 2; 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 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
521 EXPECT_TRUE(did_wait[i]) << i; | |
522 EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]) << i; | |
523 EXPECT_EQ(i, context[i]) << i; | |
524 // Since we closed before joining, we can't say much about what each thread | |
525 // saw as the state. | |
526 } | |
527 | |
528 // Some wait for readable, some for writable, and becomes readable and | |
529 // never-writable after some time. | |
530 { | |
531 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
532 ScopedVector<test::WaiterThread> threads; | |
533 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
534 threads.push_back(new test::WaiterThread( | |
535 d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, | |
536 &did_wait[i], &result[i], &context[i], &hss[i])); | |
537 threads.back()->Start(); | |
538 } | |
539 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
540 threads.push_back(new test::WaiterThread( | |
541 d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i, | |
542 &did_wait[i], &result[i], &context[i], &hss[i])); | |
543 threads.back()->Start(); | |
544 } | |
545 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | |
546 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
547 base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); | |
548 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
549 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
550 } // Joins the threads. | |
551 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
552 EXPECT_TRUE(did_wait[i]) << i; | |
553 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
554 EXPECT_EQ(i, context[i]) << i; | |
555 // Since we closed before joining, we can't say much about what each thread | |
556 // saw as the state. | |
557 } | |
558 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
559 EXPECT_TRUE(did_wait[i]) << i; | |
560 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]) << i; | |
561 EXPECT_EQ(i, context[i]) << i; | |
562 // Since we closed before joining, we can't say much about what each thread | |
563 // saw as the state. | |
564 } | |
565 | |
566 // Some wait for readable, some for writable, and becomes readable after some | |
567 // time. | |
568 { | |
569 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
570 ScopedVector<test::WaiterThread> threads; | |
571 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
572 threads.push_back(new test::WaiterThread( | |
573 d, MOJO_HANDLE_SIGNAL_READABLE, | |
574 3 * test::EpsilonTimeout().InMicroseconds(), i, &did_wait[i], | |
575 &result[i], &context[i], &hss[i])); | |
576 threads.back()->Start(); | |
577 } | |
578 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
579 threads.push_back(new test::WaiterThread( | |
580 d, MOJO_HANDLE_SIGNAL_WRITABLE, | |
581 1 * test::EpsilonTimeout().InMicroseconds(), i, &did_wait[i], | |
582 &result[i], &context[i], &hss[i])); | |
583 threads.back()->Start(); | |
584 } | |
585 base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); | |
586 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
587 // All those waiting for writable should have timed out. | |
588 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
589 } // Joins the threads. | |
590 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
591 EXPECT_TRUE(did_wait[i]) << i; | |
592 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
593 EXPECT_EQ(i, context[i]) << i; | |
594 // Since we closed before joining, we can't say much about what each thread | |
595 // saw as the state. | |
596 } | |
597 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
598 EXPECT_TRUE(did_wait[i]) << i; | |
599 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]) << i; | |
600 // Since we closed before joining, we can't say much about what each thread | |
601 // saw as the state. | |
602 } | |
603 } | |
604 | |
605 // TODO(vtl): Stress test? | |
606 | |
607 } // namespace | |
608 } // namespace system | |
609 } // namespace mojo | |
OLD | NEW |