1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_async/fake_dispatcher_fixture.h"
16
17 #include "pw_async_fuchsia/dispatcher.h"
18 #include "pw_unit_test/framework.h"
19
20 #define ASSERT_CANCELLED(status) ASSERT_EQ(Status::Cancelled(), status)
21
22 using namespace std::chrono_literals;
23
24 namespace pw::async_fuchsia {
25 namespace {
26
27 using FakeDispatcherFuchsiaFixture = async::test::FakeDispatcherFixture;
28
TEST_F(FakeDispatcherFuchsiaFixture,PostTasks)29 TEST_F(FakeDispatcherFuchsiaFixture, PostTasks) {
30 int c = 0;
31 auto inc_count = [&c](async::Context& /*ctx*/, Status status) {
32 PW_TEST_ASSERT_OK(status);
33 ++c;
34 };
35
36 async::Task task(inc_count);
37 dispatcher().Post(task);
38
39 ASSERT_EQ(c, 0);
40 RunUntilIdle();
41 ASSERT_EQ(c, 1);
42 }
43
TEST_F(FakeDispatcherFuchsiaFixture,DelayedTasks)44 TEST_F(FakeDispatcherFuchsiaFixture, DelayedTasks) {
45 int c = 0;
46 async::Task first([&c](async::Context& ctx, Status status) {
47 PW_TEST_ASSERT_OK(status);
48 c = c * 10 + 1;
49 });
50 async::Task second([&c](async::Context& ctx, Status status) {
51 PW_TEST_ASSERT_OK(status);
52 c = c * 10 + 2;
53 });
54 async::Task third([&c](async::Context& ctx, Status status) {
55 PW_TEST_ASSERT_OK(status);
56 c = c * 10 + 3;
57 });
58
59 dispatcher().PostAfter(third, 20ms);
60 dispatcher().PostAfter(first, 5ms);
61 dispatcher().PostAfter(second, 10ms);
62
63 RunFor(25ms);
64 EXPECT_EQ(c, 123);
65 }
66
TEST_F(FakeDispatcherFuchsiaFixture,CancelTask)67 TEST_F(FakeDispatcherFuchsiaFixture, CancelTask) {
68 async::Task task([](async::Context& ctx, Status status) { FAIL(); });
69 dispatcher().Post(task);
70 EXPECT_TRUE(dispatcher().Cancel(task));
71
72 RunUntilIdle();
73 }
74
TEST_F(FakeDispatcherFuchsiaFixture,HeapAllocatedTasks)75 TEST_F(FakeDispatcherFuchsiaFixture, HeapAllocatedTasks) {
76 int c = 0;
77 for (int i = 0; i < 3; i++) {
78 Post(&dispatcher(), [&c](async::Context& ctx, Status status) {
79 PW_TEST_ASSERT_OK(status);
80 c++;
81 });
82 }
83
84 RunUntilIdle();
85 EXPECT_EQ(c, 3);
86 }
87
TEST_F(FakeDispatcherFuchsiaFixture,ChainedTasks)88 TEST_F(FakeDispatcherFuchsiaFixture, ChainedTasks) {
89 int c = 0;
90
91 Post(&dispatcher(), [&c](async::Context& ctx, Status status) {
92 PW_TEST_ASSERT_OK(status);
93 c++;
94 Post(ctx.dispatcher, [&c](async::Context& ctx, Status status) {
95 PW_TEST_ASSERT_OK(status);
96 c++;
97 Post(ctx.dispatcher, [&c](async::Context& ctx, Status status) {
98 PW_TEST_ASSERT_OK(status);
99 c++;
100 });
101 });
102 });
103
104 RunUntilIdle();
105 EXPECT_EQ(c, 3);
106 }
107
TEST_F(FakeDispatcherFuchsiaFixture,DestroyLoopInsideTask)108 TEST_F(FakeDispatcherFuchsiaFixture, DestroyLoopInsideTask) {
109 int c = 0;
110 auto inc_count = [&c](async::Context& ctx, Status status) {
111 ASSERT_CANCELLED(status);
112 ++c;
113 };
114
115 // These tasks are never executed and cleaned up in DestroyLoop().
116 async::Task task0(inc_count), task1(inc_count);
117 dispatcher().PostAfter(task0, 20ms);
118 dispatcher().PostAfter(task1, 21ms);
119
120 async::Task stop_task([&c](async::Context& ctx, Status status) {
121 PW_TEST_ASSERT_OK(status);
122 ++c;
123 static_cast<async::test::FakeDispatcher*>(ctx.dispatcher)->RequestStop();
124 // Stop has been requested; now drive the Dispatcher so it destroys the
125 // loop.
126 static_cast<async::test::FakeDispatcher*>(ctx.dispatcher)->RunUntilIdle();
127 });
128 dispatcher().Post(stop_task);
129
130 RunUntilIdle();
131 EXPECT_EQ(c, 3);
132 }
133
134 } // namespace
135 } // namespace pw::async_fuchsia
136