xref: /aosp_15_r20/external/pigweed/pw_async_fuchsia/fake_dispatcher_fixture_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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