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::EpsilonDeadline()| 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 <stdint.h> | |
13 | |
14 #include "base/logging.h" | |
15 #include "base/memory/ref_counted.h" | |
16 #include "base/memory/scoped_vector.h" | |
17 #include "base/synchronization/lock.h" | |
18 #include "mojo/edk/system/test_utils.h" | |
19 #include "mojo/edk/system/waiter.h" | |
20 #include "mojo/edk/system/waiter_test_utils.h" | |
21 #include "mojo/public/cpp/system/macros.h" | |
22 #include "testing/gtest/include/gtest/gtest.h" | |
23 | |
24 namespace mojo { | |
25 namespace edk { | |
26 namespace { | |
27 | |
28 class MockSimpleDispatcher final : 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 Type::UNKNOWN; } | |
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 MOJO_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 uintptr_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::EpsilonDeadline()); | |
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::EpsilonDeadline()); | |
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, w.Wait(2 * test::EpsilonDeadline(), &context)); | |
153 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
154 EXPECT_EQ(3u, context); | |
155 hss = HandleSignalsState(); | |
156 d->RemoveAwakable(&w, &hss); | |
157 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | |
158 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
159 hss.satisfiable_signals); | |
160 | |
161 // Wait for zero time for writable when not writable (will time out). | |
162 w.Init(); | |
163 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
164 ASSERT_EQ(MOJO_RESULT_OK, | |
165 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); | |
166 stopwatch.Start(); | |
167 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); | |
168 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
169 hss = HandleSignalsState(); | |
170 d->RemoveAwakable(&w, &hss); | |
171 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
172 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
173 hss.satisfiable_signals); | |
174 | |
175 // Wait for non-zero, finite time for writable when not writable (will time | |
176 // out). | |
177 w.Init(); | |
178 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
179 ASSERT_EQ(MOJO_RESULT_OK, | |
180 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5, nullptr)); | |
181 stopwatch.Start(); | |
182 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, | |
183 w.Wait(2 * test::EpsilonDeadline(), nullptr)); | |
184 MojoDeadline elapsed = stopwatch.Elapsed(); | |
185 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); | |
186 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); | |
187 hss = HandleSignalsState(); | |
188 d->RemoveAwakable(&w, &hss); | |
189 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
190 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
191 hss.satisfiable_signals); | |
192 | |
193 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
194 } | |
195 | |
196 TEST(SimpleDispatcherTest, BasicUnsatisfiable) { | |
197 test::Stopwatch stopwatch; | |
198 | |
199 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
200 Waiter w; | |
201 uintptr_t context = 0; | |
202 HandleSignalsState hss; | |
203 | |
204 // Try adding a writable waiter when it can never be writable. | |
205 w.Init(); | |
206 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
207 d->SetSatisfiedSignals(0); | |
208 hss = HandleSignalsState(); | |
209 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
210 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); | |
211 EXPECT_EQ(0u, hss.satisfied_signals); | |
212 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | |
213 // Shouldn't need to remove the waiter (it was not added). | |
214 | |
215 // Wait (forever) for writable and then it becomes never writable. | |
216 w.Init(); | |
217 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | | |
218 MOJO_HANDLE_SIGNAL_WRITABLE); | |
219 ASSERT_EQ(MOJO_RESULT_OK, | |
220 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); | |
221 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
222 stopwatch.Start(); | |
223 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
224 w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
225 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
226 EXPECT_EQ(2u, context); | |
227 hss = HandleSignalsState(); | |
228 d->RemoveAwakable(&w, &hss); | |
229 EXPECT_EQ(0u, hss.satisfied_signals); | |
230 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | |
231 | |
232 // Wait for zero time for writable and then it becomes never writable. | |
233 w.Init(); | |
234 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | | |
235 MOJO_HANDLE_SIGNAL_WRITABLE); | |
236 ASSERT_EQ(MOJO_RESULT_OK, | |
237 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); | |
238 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
239 stopwatch.Start(); | |
240 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context)); | |
241 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
242 EXPECT_EQ(3u, context); | |
243 hss = HandleSignalsState(); | |
244 d->RemoveAwakable(&w, &hss); | |
245 EXPECT_EQ(0u, hss.satisfied_signals); | |
246 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | |
247 | |
248 // Wait for non-zero, finite time for writable and then it becomes never | |
249 // writable. | |
250 w.Init(); | |
251 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | | |
252 MOJO_HANDLE_SIGNAL_WRITABLE); | |
253 ASSERT_EQ(MOJO_RESULT_OK, | |
254 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); | |
255 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
256 stopwatch.Start(); | |
257 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
258 w.Wait(2 * test::EpsilonDeadline(), &context)); | |
259 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
260 EXPECT_EQ(4u, context); | |
261 hss = HandleSignalsState(); | |
262 d->RemoveAwakable(&w, &hss); | |
263 EXPECT_EQ(0u, hss.satisfied_signals); | |
264 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | |
265 | |
266 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
267 } | |
268 | |
269 TEST(SimpleDispatcherTest, BasicClosed) { | |
270 test::Stopwatch stopwatch; | |
271 | |
272 scoped_refptr<MockSimpleDispatcher> d; | |
273 Waiter w; | |
274 uintptr_t context = 0; | |
275 HandleSignalsState hss; | |
276 | |
277 // Try adding a writable waiter when the dispatcher has been closed. | |
278 d = new MockSimpleDispatcher(); | |
279 w.Init(); | |
280 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
281 hss = HandleSignalsState(); | |
282 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
283 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); | |
284 EXPECT_EQ(0u, hss.satisfied_signals); | |
285 EXPECT_EQ(0u, hss.satisfiable_signals); | |
286 // Shouldn't need to remove the waiter (it was not added). | |
287 | |
288 // Wait (forever) for writable and then the dispatcher is closed. | |
289 d = new MockSimpleDispatcher(); | |
290 w.Init(); | |
291 ASSERT_EQ(MOJO_RESULT_OK, | |
292 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); | |
293 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
294 stopwatch.Start(); | |
295 EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); | |
296 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
297 EXPECT_EQ(2u, context); | |
298 // Don't need to remove waiters from closed dispatchers. | |
299 | |
300 // Wait for zero time for writable and then the dispatcher is closed. | |
301 d = new MockSimpleDispatcher(); | |
302 w.Init(); | |
303 ASSERT_EQ(MOJO_RESULT_OK, | |
304 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); | |
305 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
306 stopwatch.Start(); | |
307 EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context)); | |
308 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
309 EXPECT_EQ(3u, context); | |
310 // Don't need to remove waiters from closed dispatchers. | |
311 | |
312 // Wait for non-zero, finite time for writable and then the dispatcher is | |
313 // closed. | |
314 d = new MockSimpleDispatcher(); | |
315 w.Init(); | |
316 ASSERT_EQ(MOJO_RESULT_OK, | |
317 d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); | |
318 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
319 stopwatch.Start(); | |
320 EXPECT_EQ(MOJO_RESULT_CANCELLED, | |
321 w.Wait(2 * test::EpsilonDeadline(), &context)); | |
322 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
323 EXPECT_EQ(4u, context); | |
324 // Don't need to remove waiters from closed dispatchers. | |
325 } | |
326 | |
327 #if defined(OS_WIN) | |
328 // http://crbug.com/396393 | |
329 #define MAYBE_BasicThreaded DISABLED_BasicThreaded | |
330 #else | |
331 #define MAYBE_BasicThreaded BasicThreaded | |
332 #endif | |
333 TEST(SimpleDispatcherTest, MAYBE_BasicThreaded) { | |
334 test::Stopwatch stopwatch; | |
335 bool did_wait; | |
336 MojoResult result; | |
337 uintptr_t context; | |
338 HandleSignalsState hss; | |
339 | |
340 // Wait for readable (already readable). | |
341 { | |
342 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
343 { | |
344 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
345 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
346 MOJO_DEADLINE_INDEFINITE, 1, &did_wait, &result, | |
347 &context, &hss); | |
348 stopwatch.Start(); | |
349 thread.Start(); | |
350 } // Joins the thread. | |
351 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. | |
352 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
353 } | |
354 EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline()); | |
355 EXPECT_FALSE(did_wait); | |
356 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result); | |
357 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
358 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
359 hss.satisfiable_signals); | |
360 | |
361 // Wait for readable and becomes readable after some time. | |
362 { | |
363 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
364 { | |
365 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
366 MOJO_DEADLINE_INDEFINITE, 2, &did_wait, &result, | |
367 &context, &hss); | |
368 stopwatch.Start(); | |
369 thread.Start(); | |
370 test::Sleep(2 * test::EpsilonDeadline()); | |
371 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
372 } // Joins the thread. | |
373 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
374 } | |
375 MojoDeadline elapsed = stopwatch.Elapsed(); | |
376 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); | |
377 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); | |
378 EXPECT_TRUE(did_wait); | |
379 EXPECT_EQ(MOJO_RESULT_OK, result); | |
380 EXPECT_EQ(2u, context); | |
381 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); | |
382 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
383 hss.satisfiable_signals); | |
384 | |
385 // Wait for readable and becomes never-readable after some time. | |
386 { | |
387 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
388 { | |
389 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
390 MOJO_DEADLINE_INDEFINITE, 3, &did_wait, &result, | |
391 &context, &hss); | |
392 stopwatch.Start(); | |
393 thread.Start(); | |
394 test::Sleep(2 * test::EpsilonDeadline()); | |
395 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_NONE); | |
396 } // Joins the thread. | |
397 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
398 } | |
399 elapsed = stopwatch.Elapsed(); | |
400 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); | |
401 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); | |
402 EXPECT_TRUE(did_wait); | |
403 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
404 EXPECT_EQ(3u, context); | |
405 EXPECT_EQ(0u, hss.satisfied_signals); | |
406 EXPECT_EQ(0u, hss.satisfiable_signals); | |
407 | |
408 // Wait for readable and dispatcher gets closed. | |
409 { | |
410 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
411 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
412 MOJO_DEADLINE_INDEFINITE, 4, &did_wait, &result, | |
413 &context, &hss); | |
414 stopwatch.Start(); | |
415 thread.Start(); | |
416 test::Sleep(2 * test::EpsilonDeadline()); | |
417 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
418 } // Joins the thread. | |
419 elapsed = stopwatch.Elapsed(); | |
420 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); | |
421 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); | |
422 EXPECT_TRUE(did_wait); | |
423 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | |
424 EXPECT_EQ(4u, context); | |
425 EXPECT_EQ(0u, hss.satisfied_signals); | |
426 EXPECT_EQ(0u, hss.satisfiable_signals); | |
427 | |
428 // Wait for readable and times out. | |
429 { | |
430 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
431 { | |
432 test::WaiterThread thread(d, MOJO_HANDLE_SIGNAL_READABLE, | |
433 2 * test::EpsilonDeadline(), 5, &did_wait, | |
434 &result, &context, &hss); | |
435 stopwatch.Start(); | |
436 thread.Start(); | |
437 test::Sleep(1 * test::EpsilonDeadline()); | |
438 // Not what we're waiting for. | |
439 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); | |
440 } // Joins the thread (after its wait times out). | |
441 // If we closed earlier, then probably we'd get a |MOJO_RESULT_CANCELLED|. | |
442 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
443 } | |
444 elapsed = stopwatch.Elapsed(); | |
445 EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline()); | |
446 EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline()); | |
447 EXPECT_TRUE(did_wait); | |
448 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result); | |
449 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | |
450 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | |
451 hss.satisfiable_signals); | |
452 } | |
453 | |
454 #if defined(OS_WIN) | |
455 // http://crbug.com/387124 | |
456 #define MAYBE_MultipleWaiters DISABLED_MultipleWaiters | |
457 #else | |
458 #define MAYBE_MultipleWaiters MultipleWaiters | |
459 #endif | |
460 TEST(SimpleDispatcherTest, MAYBE_MultipleWaiters) { | |
461 static const uint32_t kNumWaiters = 20; | |
462 | |
463 bool did_wait[kNumWaiters]; | |
464 MojoResult result[kNumWaiters]; | |
465 uintptr_t context[kNumWaiters]; | |
466 HandleSignalsState hss[kNumWaiters]; | |
467 | |
468 // All wait for readable and becomes readable after some time. | |
469 { | |
470 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
471 ScopedVector<test::WaiterThread> threads; | |
472 for (uint32_t i = 0; i < kNumWaiters; i++) { | |
473 threads.push_back(new test::WaiterThread( | |
474 d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, | |
475 &did_wait[i], &result[i], &context[i], &hss[i])); | |
476 threads.back()->Start(); | |
477 } | |
478 test::Sleep(2 * test::EpsilonDeadline()); | |
479 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
480 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
481 } // Joins the threads. | |
482 for (uint32_t i = 0; i < kNumWaiters; i++) { | |
483 EXPECT_TRUE(did_wait[i]) << i; | |
484 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
485 EXPECT_EQ(i, context[i]) << i; | |
486 // Since we closed before joining, we can't say much about what each thread | |
487 // saw as the state. | |
488 } | |
489 | |
490 // Some wait for readable, some for writable, and becomes readable after some | |
491 // time. | |
492 { | |
493 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
494 ScopedVector<test::WaiterThread> threads; | |
495 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
496 threads.push_back(new test::WaiterThread( | |
497 d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, | |
498 &did_wait[i], &result[i], &context[i], &hss[i])); | |
499 threads.back()->Start(); | |
500 } | |
501 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
502 threads.push_back(new test::WaiterThread( | |
503 d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i, | |
504 &did_wait[i], &result[i], &context[i], &hss[i])); | |
505 threads.back()->Start(); | |
506 } | |
507 test::Sleep(2 * test::EpsilonDeadline()); | |
508 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
509 // This will wake up the ones waiting to write. | |
510 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
511 } // Joins the threads. | |
512 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
513 EXPECT_TRUE(did_wait[i]) << i; | |
514 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
515 EXPECT_EQ(i, context[i]) << i; | |
516 // Since we closed before joining, we can't say much about what each thread | |
517 // saw as the state. | |
518 } | |
519 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
520 EXPECT_TRUE(did_wait[i]) << i; | |
521 EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]) << i; | |
522 EXPECT_EQ(i, context[i]) << i; | |
523 // Since we closed before joining, we can't say much about what each thread | |
524 // saw as the state. | |
525 } | |
526 | |
527 // Some wait for readable, some for writable, and becomes readable and | |
528 // never-writable after some time. | |
529 { | |
530 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
531 ScopedVector<test::WaiterThread> threads; | |
532 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
533 threads.push_back(new test::WaiterThread( | |
534 d, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE, i, | |
535 &did_wait[i], &result[i], &context[i], &hss[i])); | |
536 threads.back()->Start(); | |
537 } | |
538 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
539 threads.push_back(new test::WaiterThread( | |
540 d, MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_DEADLINE_INDEFINITE, i, | |
541 &did_wait[i], &result[i], &context[i], &hss[i])); | |
542 threads.back()->Start(); | |
543 } | |
544 test::Sleep(1 * test::EpsilonDeadline()); | |
545 d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
546 test::Sleep(1 * test::EpsilonDeadline()); | |
547 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
548 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
549 } // Joins the threads. | |
550 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
551 EXPECT_TRUE(did_wait[i]) << i; | |
552 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
553 EXPECT_EQ(i, context[i]) << i; | |
554 // Since we closed before joining, we can't say much about what each thread | |
555 // saw as the state. | |
556 } | |
557 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
558 EXPECT_TRUE(did_wait[i]) << i; | |
559 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]) << i; | |
560 EXPECT_EQ(i, context[i]) << i; | |
561 // Since we closed before joining, we can't say much about what each thread | |
562 // saw as the state. | |
563 } | |
564 | |
565 // Some wait for readable, some for writable, and becomes readable after some | |
566 // time. | |
567 { | |
568 scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher()); | |
569 ScopedVector<test::WaiterThread> threads; | |
570 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
571 threads.push_back(new test::WaiterThread( | |
572 d, MOJO_HANDLE_SIGNAL_READABLE, 3 * test::EpsilonDeadline(), i, | |
573 &did_wait[i], &result[i], &context[i], &hss[i])); | |
574 threads.back()->Start(); | |
575 } | |
576 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
577 threads.push_back(new test::WaiterThread( | |
578 d, MOJO_HANDLE_SIGNAL_WRITABLE, 1 * test::EpsilonDeadline(), i, | |
579 &did_wait[i], &result[i], &context[i], &hss[i])); | |
580 threads.back()->Start(); | |
581 } | |
582 test::Sleep(2 * test::EpsilonDeadline()); | |
583 d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); | |
584 // All those waiting for writable should have timed out. | |
585 EXPECT_EQ(MOJO_RESULT_OK, d->Close()); | |
586 } // Joins the threads. | |
587 for (uint32_t i = 0; i < kNumWaiters / 2; i++) { | |
588 EXPECT_TRUE(did_wait[i]) << i; | |
589 EXPECT_EQ(MOJO_RESULT_OK, result[i]) << i; | |
590 EXPECT_EQ(i, context[i]) << i; | |
591 // Since we closed before joining, we can't say much about what each thread | |
592 // saw as the state. | |
593 } | |
594 for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) { | |
595 EXPECT_TRUE(did_wait[i]) << i; | |
596 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]) << i; | |
597 // Since we closed before joining, we can't say much about what each thread | |
598 // saw as the state. | |
599 } | |
600 } | |
601 | |
602 // TODO(vtl): Stress test? | |
603 | |
604 } // namespace | |
605 } // namespace edk | |
606 } // namespace mojo | |
OLD | NEW |