1 // Copyright 2018 The Fuchsia 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 #include <fbl/array.h>
6 #include <fbl/function.h>
7 #include <lib/async-testutils/test_loop.h>
8 #include <lib/async/cpp/task.h>
9 #include <lib/async/cpp/time.h>
10 #include <lib/async/cpp/wait.h>
11 #include <lib/async/default.h>
12 #include <lib/zx/event.h>
13 #include <lib/zx/time.h>
14 #include <unittest/unittest.h>
15 #include <zircon/syscalls.h>
16
17 #include <memory>
18 #include <utility>
19
20 namespace {
21
22 // Initializes |wait| to wait on |event| to call |closure| once |trigger| is
23 // signaled.
InitWait(async::Wait * wait,fbl::Closure closure,const zx::event & event,zx_signals_t trigger)24 void InitWait(async::Wait* wait, fbl::Closure closure, const zx::event& event,
25 zx_signals_t trigger) {
26 wait->set_handler(
27 [closure = std::move(closure)] (async_dispatcher_t*, async::Wait*,
28 zx_status_t,
29 const zx_packet_signal_t*) {
30 closure();
31 });
32 wait->set_object(event.get());
33 wait->set_trigger(trigger);
34 }
35
36
DefaultDispatcherIsSetAndUnset()37 bool DefaultDispatcherIsSetAndUnset() {
38 BEGIN_TEST;
39
40 EXPECT_NULL(async_get_default_dispatcher());
41 {
42 async::TestLoop loop;;
43 EXPECT_EQ(loop.dispatcher(), async_get_default_dispatcher());
44 }
45 EXPECT_NULL(async_get_default_dispatcher());
46
47 END_TEST;
48 }
49
FakeClockTimeIsCorrect()50 bool FakeClockTimeIsCorrect() {
51 BEGIN_TEST;
52
53 async::TestLoop loop;
54
55 EXPECT_EQ(0, loop.Now().get());
56 EXPECT_EQ(0, async::Now(loop.dispatcher()).get());
57
58 loop.RunUntilIdle();
59 EXPECT_EQ(0, loop.Now().get());
60 EXPECT_EQ(0, async::Now(loop.dispatcher()).get());
61
62 loop.RunFor(zx::nsec(1));
63 EXPECT_EQ(1, loop.Now().get());
64 EXPECT_EQ(1, async::Now(loop.dispatcher()).get());
65
66 loop.RunUntil(zx::time() + zx::nsec(3));
67 EXPECT_EQ(3, loop.Now().get());
68 EXPECT_EQ(3, async::Now(loop.dispatcher()).get());
69
70 loop.RunFor(zx::nsec(7));
71 EXPECT_EQ(10, loop.Now().get());
72 EXPECT_EQ(10, async::Now(loop.dispatcher()).get());
73
74 loop.RunUntil(zx::time() + zx::nsec(12));
75 EXPECT_EQ(12, loop.Now().get());
76 EXPECT_EQ(12, async::Now(loop.dispatcher()).get());
77
78 // t = 12, so nothing should happen in trying to reset the clock to t = 10.
79 loop.RunUntil(zx::time() + zx::nsec(10));
80 EXPECT_EQ(12, loop.Now().get());
81 EXPECT_EQ(12, async::Now(loop.dispatcher()).get());
82
83 END_TEST;
84 }
85
TasksAreDispatched()86 bool TasksAreDispatched() {
87 BEGIN_TEST;
88
89 async::TestLoop loop;
90 bool called = false;
91 async::PostDelayedTask(loop.dispatcher(), [&called] { called = true; }, zx::sec(2));
92
93 // t = 1: nothing should happen.
94 loop.RunFor(zx::sec(1));
95 EXPECT_FALSE(called);
96
97 // t = 2: task should be dispatched.
98 loop.RunFor(zx::sec(1));
99 EXPECT_TRUE(called);
100
101 called = false;
102 async::PostTask(loop.dispatcher(), [&called] { called = true; });
103 loop.RunUntilIdle();
104 EXPECT_TRUE(called);
105
106 END_TEST;
107 }
108
SameDeadlinesDispatchInPostingOrder()109 bool SameDeadlinesDispatchInPostingOrder() {
110 BEGIN_TEST;
111
112 async::TestLoop loop;
113 bool calledA = false;
114 bool calledB = false;
115
116 async::PostTask(loop.dispatcher(), [&] {
117 EXPECT_FALSE(calledB);
118 calledA = true;
119 });
120 async::PostTask(loop.dispatcher(), [&] {
121 EXPECT_TRUE(calledA);
122 calledB = true;
123 });
124
125 loop.RunUntilIdle();
126 EXPECT_TRUE(calledA);
127 EXPECT_TRUE(calledB);
128
129 calledA = false;
130 calledB = false;
131 async::PostDelayedTask(
132 loop.dispatcher(),
133 [&] {
134 EXPECT_FALSE(calledB);
135 calledA = true;
136 },
137 zx::sec(5));
138 async::PostDelayedTask(
139 loop.dispatcher(),
140 [&] {
141 EXPECT_TRUE(calledA);
142 calledB = true;
143 },
144 zx::sec(5));
145
146 loop.RunFor(zx::sec(5));
147 EXPECT_TRUE(calledA);
148 EXPECT_TRUE(calledB);
149
150 END_TEST;
151 }
152
153 // Test tasks that post tasks.
NestedTasksAreDispatched()154 bool NestedTasksAreDispatched() {
155 BEGIN_TEST;
156
157 async::TestLoop loop;
158 bool called = false;
159
160 async::PostTask(loop.dispatcher(), [&] {
161 async::PostDelayedTask(
162 loop.dispatcher(),
163 [&] {
164 async::PostDelayedTask(
165 loop.dispatcher(),
166 [&] { called = true; },
167 zx::min(25));
168 },
169 zx::min(35));
170 });
171
172 loop.RunFor(zx::hour(1));
173 EXPECT_TRUE(called);
174
175 END_TEST;
176 }
177
TimeIsCorrectWhileDispatching()178 bool TimeIsCorrectWhileDispatching() {
179 BEGIN_TEST;
180
181 async::TestLoop loop;
182 bool called = false;
183
184 async::PostTask(loop.dispatcher(), [&] {
185 EXPECT_EQ(0, loop.Now().get());
186
187 async::PostDelayedTask(
188 loop.dispatcher(),
189 [&] {
190 EXPECT_EQ(10, loop.Now().get());
191 async::PostDelayedTask(
192 loop.dispatcher(),
193 [&] {
194 EXPECT_EQ(15, loop.Now().get());
195 async::PostTask(loop.dispatcher(), [&] {
196 EXPECT_EQ(15, loop.Now().get());
197 called = true;
198 });
199 },
200 zx::nsec(5));
201 },
202 zx::nsec(10));
203 });
204
205 loop.RunFor(zx::nsec(15));
206 EXPECT_TRUE(called);
207
208 END_TEST;
209 }
210
TasksAreCanceled()211 bool TasksAreCanceled() {
212 BEGIN_TEST;
213
214 async::TestLoop loop;
215 bool calledA = false;
216 bool calledB = false;
217 bool calledC = false;
218
219 async::TaskClosure taskA([&calledA] { calledA = true; });
220 async::TaskClosure taskB([&calledB] { calledB = true; });
221 async::TaskClosure taskC([&calledC] { calledC = true; });
222
223 ASSERT_EQ(ZX_OK, taskA.Post(loop.dispatcher()));
224 ASSERT_EQ(ZX_OK, taskB.Post(loop.dispatcher()));
225 ASSERT_EQ(ZX_OK, taskC.Post(loop.dispatcher()));
226
227 ASSERT_EQ(ZX_OK, taskA.Cancel());
228 ASSERT_EQ(ZX_OK, taskC.Cancel());
229
230 loop.RunUntilIdle();
231
232 EXPECT_FALSE(calledA);
233 EXPECT_TRUE(calledB);
234 EXPECT_FALSE(calledC);
235
236 END_TEST;
237 }
238
TimeIsAdvanced()239 bool TimeIsAdvanced() {
240 BEGIN_TEST;
241 async::TestLoop loop;
242
243 bool called = false;
244 async::TaskClosure task([&called] { called = true; });
245 auto time1 = async::Now(loop.dispatcher());
246
247 ASSERT_EQ(ZX_OK, task.PostDelayed(loop.dispatcher(), zx::duration(1)));
248
249 loop.RunUntilIdle();
250
251 EXPECT_FALSE(called);
252 EXPECT_EQ(time1.get(), async::Now(loop.dispatcher()).get());
253
254 loop.AdvanceTimeByEpsilon();
255
256 auto time2 = async::Now(loop.dispatcher());
257
258 EXPECT_FALSE(called);
259 EXPECT_GT(time2.get(), time1.get());
260
261 loop.RunUntilIdle();
262
263 EXPECT_TRUE(called);
264 EXPECT_EQ(time2.get(), async::Now(loop.dispatcher()).get());
265
266 END_TEST;
267 }
268
WaitsAreDispatched()269 bool WaitsAreDispatched() {
270 BEGIN_TEST;
271
272 async::TestLoop loop;
273 async::Wait wait;
274 zx::event event;
275 bool called = false;
276
277 ASSERT_EQ(ZX_OK, zx::event::create(0u, &event));
278 InitWait(&wait, [&called] { called = true; }, event, ZX_USER_SIGNAL_0);
279 ASSERT_EQ(ZX_OK, wait.Begin(loop.dispatcher()));
280
281 // |wait| has not yet been triggered.
282 loop.RunUntilIdle();
283 EXPECT_FALSE(called);
284
285 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_1));
286
287 // |wait| will only be triggered by |ZX_USER_SIGNAL_0|.
288 loop.RunUntilIdle();
289 EXPECT_FALSE(called);
290
291 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_0));
292
293 loop.RunUntilIdle();
294 EXPECT_TRUE(called);
295
296 END_TEST;
297 }
298
299 // Test waits that trigger waits.
NestedWaitsAreDispatched()300 bool NestedWaitsAreDispatched() {
301 BEGIN_TEST;
302
303 async::TestLoop loop;
304 zx::event event;
305 async::Wait waitA;
306 async::Wait waitB;
307 async::Wait waitC;
308 bool calledA = false;
309 bool calledB = false;
310 bool calledC = false;
311
312 ASSERT_EQ(ZX_OK, zx::event::create(0u, &event));
313 InitWait(
314 &waitA,
315 [&] {
316 InitWait(
317 &waitB,
318 [&] {
319 InitWait(&waitC, [&] { calledC = true; }, event, ZX_USER_SIGNAL_2);
320 waitC.Begin(loop.dispatcher());
321 calledB = true;
322 },
323 event,
324 ZX_USER_SIGNAL_1);
325 waitB.Begin(loop.dispatcher());
326 calledA = true;
327 },
328 event,
329 ZX_USER_SIGNAL_0);
330
331 ASSERT_EQ(ZX_OK, waitA.Begin(loop.dispatcher()));
332
333 loop.RunUntilIdle();
334 EXPECT_FALSE(calledA);
335 EXPECT_FALSE(calledB);
336 EXPECT_FALSE(calledC);
337
338 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_0));
339
340 loop.RunUntilIdle();
341 EXPECT_TRUE(calledA);
342 EXPECT_FALSE(calledB);
343 EXPECT_FALSE(calledC);
344
345 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_1));
346
347 loop.RunUntilIdle();
348 EXPECT_TRUE(calledA);
349 EXPECT_TRUE(calledB);
350 EXPECT_FALSE(calledC);
351
352 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_2));
353
354 loop.RunUntilIdle();
355 EXPECT_TRUE(calledA);
356 EXPECT_TRUE(calledB);
357 EXPECT_TRUE(calledC);
358
359 END_TEST;
360 }
361
WaitsAreCanceled()362 bool WaitsAreCanceled() {
363 BEGIN_TEST;
364
365 async::TestLoop loop;
366 zx::event event;
367 async::Wait waitA;
368 async::Wait waitB;
369 async::Wait waitC;
370 bool calledA = false;
371 bool calledB = false;
372 bool calledC = false;
373
374 ASSERT_EQ(ZX_OK, zx::event::create(0u, &event));
375
376 InitWait(&waitA, [&calledA] { calledA = true; }, event, ZX_USER_SIGNAL_0);
377 InitWait(&waitB, [&calledB] { calledB = true; }, event, ZX_USER_SIGNAL_0);
378 InitWait(&waitC, [&calledC] { calledC = true; }, event, ZX_USER_SIGNAL_0);
379
380 ASSERT_EQ(ZX_OK, waitA.Begin(loop.dispatcher()));
381 ASSERT_EQ(ZX_OK, waitB.Begin(loop.dispatcher()));
382 ASSERT_EQ(ZX_OK, waitC.Begin(loop.dispatcher()));
383
384 ASSERT_EQ(ZX_OK, waitA.Cancel());
385 ASSERT_EQ(ZX_OK, waitC.Cancel());
386 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_0));
387
388 loop.RunUntilIdle();
389 EXPECT_FALSE(calledA);
390 EXPECT_TRUE(calledB);
391 EXPECT_FALSE(calledC);
392
393 END_TEST;
394 }
395
396 // Test a task that begins a wait to post a task.
NestedTasksAndWaitsAreDispatched()397 bool NestedTasksAndWaitsAreDispatched() {
398 BEGIN_TEST;
399
400 async::TestLoop loop;
401 zx::event event;
402 async::Wait wait;
403 bool wait_begun = false;
404 bool wait_dispatched = false;
405 bool inner_task_dispatched = false;
406
407 ASSERT_EQ(ZX_OK, zx::event::create(0u, &event));
408 InitWait(
409 &wait,
410 [&] {
411 async::PostDelayedTask(loop.dispatcher(),
412 [&] { inner_task_dispatched = true; },
413 zx::min(2));
414 wait_dispatched = true;
415 },
416 event,
417 ZX_USER_SIGNAL_0);
418 async::PostDelayedTask(loop.dispatcher(),
419 [&] {
420 wait.Begin(loop.dispatcher());
421 wait_begun = true;
422 },
423 zx::min(3));
424
425 loop.RunFor(zx::min(3));
426 EXPECT_TRUE(wait_begun);
427 EXPECT_FALSE(wait_dispatched);
428 EXPECT_FALSE(inner_task_dispatched);
429
430 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_0));
431
432 loop.RunUntilIdle();
433 EXPECT_TRUE(wait_begun);
434 EXPECT_TRUE(wait_dispatched);
435 EXPECT_FALSE(inner_task_dispatched);
436
437 loop.RunFor(zx::min(2));
438 EXPECT_TRUE(wait_begun);
439 EXPECT_TRUE(wait_dispatched);
440 EXPECT_TRUE(inner_task_dispatched);
441
442 END_TEST;
443 }
444
TasksAreDispatchedOnManyLoops()445 bool TasksAreDispatchedOnManyLoops() {
446 BEGIN_TEST;
447
448 async::TestLoop loop;
449 auto loopA = loop.StartNewLoop();
450 auto loopB = loop.StartNewLoop();
451 auto loopC = loop.StartNewLoop();
452
453 bool called = false;
454 bool calledA = false;
455 bool calledB = false;
456 bool calledC = false;
457 async::TaskClosure taskC([&calledC] { calledC = true; });
458
459 async::PostTask(loopB->dispatcher(), [&calledB] { calledB = true; });
460 async::PostDelayedTask(loop.dispatcher(), [&called] { called = true; }, zx::sec(1));
461 ASSERT_EQ(ZX_OK, taskC.PostDelayed(loopC->dispatcher(), zx::sec(1)));
462 async::PostDelayedTask(loopA->dispatcher(), [&calledA] { calledA = true; }, zx::sec(2));
463
464 loop.RunUntilIdle();
465 EXPECT_FALSE(called);
466 EXPECT_FALSE(calledA);
467 EXPECT_TRUE(calledB);
468 EXPECT_FALSE(calledC);
469
470 taskC.Cancel();
471 loop.RunFor(zx::sec(1));
472 EXPECT_TRUE(called);
473 EXPECT_FALSE(calledA);
474 EXPECT_TRUE(calledB);
475 EXPECT_FALSE(calledC);
476
477 loop.RunFor(zx::sec(1));
478 EXPECT_TRUE(called);
479 EXPECT_TRUE(calledA);
480 EXPECT_TRUE(calledB);
481 EXPECT_FALSE(calledC);
482
483 END_TEST;
484 }
485
WaitsAreDispatchedOnManyLoops()486 bool WaitsAreDispatchedOnManyLoops() {
487 BEGIN_TEST;
488
489 async::TestLoop loop;
490 auto loopA = loop.StartNewLoop();
491 auto loopB = loop.StartNewLoop();
492 auto loopC = loop.StartNewLoop();
493 async::Wait wait;
494 async::Wait waitA;
495 async::Wait waitB;
496 async::Wait waitC;
497 bool called = false;
498 bool calledA = false;
499 bool calledB = false;
500 bool calledC = false;
501 zx::event event;
502
503 ASSERT_EQ(ZX_OK, zx::event::create(0u, &event));
504
505 InitWait(&wait, [&called] { called = true; }, event, ZX_USER_SIGNAL_0);
506 InitWait(&waitA, [&calledA] { calledA = true; }, event, ZX_USER_SIGNAL_0);
507 InitWait(&waitB, [&calledB] { calledB = true; }, event, ZX_USER_SIGNAL_0);
508 InitWait(&waitC, [&calledC] { calledC = true; }, event, ZX_USER_SIGNAL_0);
509
510 ASSERT_EQ(ZX_OK, wait.Begin(loop.dispatcher()));
511 ASSERT_EQ(ZX_OK, waitA.Begin(loopA->dispatcher()));
512 ASSERT_EQ(ZX_OK, waitB.Begin(loopB->dispatcher()));
513 ASSERT_EQ(ZX_OK, waitC.Begin(loopC->dispatcher()));
514
515 ASSERT_EQ(ZX_OK, waitB.Cancel());
516 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_0));
517
518 loop.RunUntilIdle();
519 EXPECT_TRUE(called);
520 EXPECT_TRUE(calledA);
521 EXPECT_FALSE(calledB);
522 EXPECT_TRUE(calledC);
523
524 END_TEST;
525 }
526
527
528 // Populates |order| with the order in which two tasks and two waits on four
529 // loops were dispatched, given a |loop|.
DetermineDispatchOrder(std::unique_ptr<async::TestLoop> loop,int (* order)[4])530 bool DetermineDispatchOrder(std::unique_ptr<async::TestLoop> loop, int (*order)[4]) {
531 BEGIN_HELPER;
532
533 auto loopA = loop->StartNewLoop();
534 auto loopB = loop->StartNewLoop();
535 auto loopC = loop->StartNewLoop();
536 async::Wait wait;
537 async::Wait waitB;
538 zx::event event;
539 int i = 0;
540
541 ASSERT_EQ(ZX_OK, zx::event::create(0u, &event));
542
543 InitWait(&wait, [&] { (*order)[0] = ++i; }, event, ZX_USER_SIGNAL_0);
544 async::PostTask(loopA->dispatcher(), [&] { (*order)[1] = ++i; });
545 InitWait(&waitB, [&] { (*order)[2] = ++i; }, event, ZX_USER_SIGNAL_0);
546 async::PostTask(loopC->dispatcher(), [&] { (*order)[3] = ++i; });
547
548 ASSERT_EQ(ZX_OK, wait.Begin(loop->dispatcher()));
549 ASSERT_EQ(ZX_OK, waitB.Begin(loopB->dispatcher()));
550 ASSERT_EQ(ZX_OK, event.signal(0u, ZX_USER_SIGNAL_0));
551
552 loop->RunUntilIdle();
553
554 EXPECT_EQ(4, i);
555 EXPECT_NE(0, (*order)[0]);
556 EXPECT_NE(0, (*order)[1]);
557 EXPECT_NE(0, (*order)[2]);
558 EXPECT_NE(0, (*order)[3]);
559
560 END_HELPER;
561 }
562
SeedTestLoopWithEnv(uint32_t random_seed,std::unique_ptr<async::TestLoop> * loop)563 bool SeedTestLoopWithEnv(uint32_t random_seed, std::unique_ptr<async::TestLoop>* loop) {
564 BEGIN_HELPER;
565
566 char buf[12];
567 snprintf(buf, sizeof(buf), "%u", random_seed);
568 EXPECT_EQ(0, setenv("TEST_LOOP_RANDOM_SEED", buf, 1));
569 *loop = std::make_unique<async::TestLoop>();
570 EXPECT_EQ(0, unsetenv("TEST_LOOP_RANDOM_SEED"));
571
572 END_HELPER;
573 }
574
DispatchOrderIsDeterministicFor(uint32_t random_seed)575 bool DispatchOrderIsDeterministicFor(uint32_t random_seed) {
576 BEGIN_HELPER;
577
578 int expected_order[4] = {0, 0, 0, 0};
579 std::unique_ptr<async::TestLoop> loop;
580
581 EXPECT_TRUE(SeedTestLoopWithEnv(random_seed, &loop));
582 EXPECT_TRUE(DetermineDispatchOrder(std::move(loop), &expected_order));
583
584 for (int i = 0; i < 5; ++i) {
585 for (int j = 0; j < 2; j++) {
586 int actual_order[4] = {0, 0, 0, 0};
587 if (j == 0) {
588 EXPECT_TRUE(SeedTestLoopWithEnv(random_seed, &loop));
589 } else {
590 loop = std::make_unique<async::TestLoop>(random_seed);
591 }
592 EXPECT_TRUE(DetermineDispatchOrder(std::move(loop), &actual_order));
593 EXPECT_EQ(expected_order[0], actual_order[0]);
594 EXPECT_EQ(expected_order[1], actual_order[1]);
595 EXPECT_EQ(expected_order[2], actual_order[2]);
596 EXPECT_EQ(expected_order[3], actual_order[3]);
597 }
598 }
599
600 END_HELPER;
601 }
602
603
DispatchOrderIsDeterministic()604 bool DispatchOrderIsDeterministic() {
605 BEGIN_TEST;
606
607 EXPECT_TRUE(DispatchOrderIsDeterministicFor(1));
608 EXPECT_TRUE(DispatchOrderIsDeterministicFor(43));
609 EXPECT_TRUE(DispatchOrderIsDeterministicFor(893));
610 EXPECT_TRUE(DispatchOrderIsDeterministicFor(39408));
611 EXPECT_TRUE(DispatchOrderIsDeterministicFor(844018));
612 EXPECT_TRUE(DispatchOrderIsDeterministicFor(83018299));
613 EXPECT_TRUE(DispatchOrderIsDeterministicFor(3213));
614 EXPECT_TRUE(DispatchOrderIsDeterministicFor(139133113));
615 EXPECT_TRUE(DispatchOrderIsDeterministicFor(1323234373));
616
617 END_TEST;
618 }
619
620 } // namespace
621
622 BEGIN_TEST_CASE(SingleLoopTests)
623 RUN_TEST(DefaultDispatcherIsSetAndUnset)
624 RUN_TEST(FakeClockTimeIsCorrect)
625 RUN_TEST(TasksAreDispatched)
626 RUN_TEST(SameDeadlinesDispatchInPostingOrder)
627 RUN_TEST(NestedTasksAreDispatched)
628 RUN_TEST(TimeIsCorrectWhileDispatching)
629 RUN_TEST(TasksAreCanceled)
630 RUN_TEST(TimeIsAdvanced)
631 RUN_TEST(WaitsAreDispatched)
632 RUN_TEST(NestedWaitsAreDispatched)
633 RUN_TEST(WaitsAreCanceled)
634 RUN_TEST(NestedTasksAndWaitsAreDispatched)
635 END_TEST_CASE(SingleLoopTests)
636
637 BEGIN_TEST_CASE(MultiLoopTests)
638 RUN_TEST(TasksAreDispatchedOnManyLoops)
639 RUN_TEST(WaitsAreDispatchedOnManyLoops)
640 RUN_TEST(DispatchOrderIsDeterministic)
641 END_TEST_CASE(MultiLoopTests)
642