xref: /aosp_15_r20/external/pigweed/pw_async_fuchsia/dispatcher_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2024 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_async_fuchsia/dispatcher.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include <lib/async-testing/test_loop.h>
18*61c4878aSAndroid Build Coastguard Worker 
19*61c4878aSAndroid Build Coastguard Worker #include "pw_async_fuchsia/util.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
21*61c4878aSAndroid Build Coastguard Worker 
22*61c4878aSAndroid Build Coastguard Worker #define ASSERT_CANCELLED(status) ASSERT_EQ(Status::Cancelled(), status)
23*61c4878aSAndroid Build Coastguard Worker 
24*61c4878aSAndroid Build Coastguard Worker using namespace std::chrono_literals;
25*61c4878aSAndroid Build Coastguard Worker 
26*61c4878aSAndroid Build Coastguard Worker namespace pw::async_fuchsia {
27*61c4878aSAndroid Build Coastguard Worker 
28*61c4878aSAndroid Build Coastguard Worker class DispatcherFuchsiaTest : public ::testing::Test {
29*61c4878aSAndroid Build Coastguard Worker  public:
dispatcher()30*61c4878aSAndroid Build Coastguard Worker   async_dispatcher_t* dispatcher() { return loop_.dispatcher(); }
RunLoopUntilIdle()31*61c4878aSAndroid Build Coastguard Worker   void RunLoopUntilIdle() { loop_.RunUntilIdle(); }
RunLoopFor(zx::duration duration)32*61c4878aSAndroid Build Coastguard Worker   void RunLoopFor(zx::duration duration) { loop_.RunFor(duration); }
33*61c4878aSAndroid Build Coastguard Worker 
34*61c4878aSAndroid Build Coastguard Worker  private:
35*61c4878aSAndroid Build Coastguard Worker   ::async::TestLoop loop_;
36*61c4878aSAndroid Build Coastguard Worker };
37*61c4878aSAndroid Build Coastguard Worker 
TEST_F(DispatcherFuchsiaTest,TimeConversions)38*61c4878aSAndroid Build Coastguard Worker TEST_F(DispatcherFuchsiaTest, TimeConversions) {
39*61c4878aSAndroid Build Coastguard Worker   zx::time time{timespec{123, 456}};
40*61c4878aSAndroid Build Coastguard Worker   chrono::SystemClock::time_point tp =
41*61c4878aSAndroid Build Coastguard Worker       pw::async_fuchsia::ZxTimeToTimepoint(time);
42*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(tp.time_since_epoch(), 123s + 456ns);
43*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(pw::async_fuchsia::TimepointToZxTime(tp), time);
44*61c4878aSAndroid Build Coastguard Worker }
45*61c4878aSAndroid Build Coastguard Worker 
TEST_F(DispatcherFuchsiaTest,Basic)46*61c4878aSAndroid Build Coastguard Worker TEST_F(DispatcherFuchsiaTest, Basic) {
47*61c4878aSAndroid Build Coastguard Worker   FuchsiaDispatcher fuchsia_dispatcher(dispatcher());
48*61c4878aSAndroid Build Coastguard Worker 
49*61c4878aSAndroid Build Coastguard Worker   bool set = false;
50*61c4878aSAndroid Build Coastguard Worker   async::Task task([&set](async::Context& ctx, Status status) {
51*61c4878aSAndroid Build Coastguard Worker     PW_TEST_ASSERT_OK(status);
52*61c4878aSAndroid Build Coastguard Worker     set = true;
53*61c4878aSAndroid Build Coastguard Worker   });
54*61c4878aSAndroid Build Coastguard Worker   fuchsia_dispatcher.Post(task);
55*61c4878aSAndroid Build Coastguard Worker 
56*61c4878aSAndroid Build Coastguard Worker   RunLoopUntilIdle();
57*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(set);
58*61c4878aSAndroid Build Coastguard Worker }
59*61c4878aSAndroid Build Coastguard Worker 
TEST_F(DispatcherFuchsiaTest,DelayedTasks)60*61c4878aSAndroid Build Coastguard Worker TEST_F(DispatcherFuchsiaTest, DelayedTasks) {
61*61c4878aSAndroid Build Coastguard Worker   FuchsiaDispatcher fuchsia_dispatcher(dispatcher());
62*61c4878aSAndroid Build Coastguard Worker 
63*61c4878aSAndroid Build Coastguard Worker   int c = 0;
64*61c4878aSAndroid Build Coastguard Worker   async::Task first([&c](async::Context& ctx, Status status) {
65*61c4878aSAndroid Build Coastguard Worker     PW_TEST_ASSERT_OK(status);
66*61c4878aSAndroid Build Coastguard Worker     c = c * 10 + 1;
67*61c4878aSAndroid Build Coastguard Worker   });
68*61c4878aSAndroid Build Coastguard Worker   async::Task second([&c](async::Context& ctx, Status status) {
69*61c4878aSAndroid Build Coastguard Worker     PW_TEST_ASSERT_OK(status);
70*61c4878aSAndroid Build Coastguard Worker     c = c * 10 + 2;
71*61c4878aSAndroid Build Coastguard Worker   });
72*61c4878aSAndroid Build Coastguard Worker   async::Task third([&c](async::Context& ctx, Status status) {
73*61c4878aSAndroid Build Coastguard Worker     PW_TEST_ASSERT_OK(status);
74*61c4878aSAndroid Build Coastguard Worker     c = c * 10 + 3;
75*61c4878aSAndroid Build Coastguard Worker   });
76*61c4878aSAndroid Build Coastguard Worker 
77*61c4878aSAndroid Build Coastguard Worker   fuchsia_dispatcher.PostAfter(third, 20ms);
78*61c4878aSAndroid Build Coastguard Worker   fuchsia_dispatcher.PostAfter(first, 5ms);
79*61c4878aSAndroid Build Coastguard Worker   fuchsia_dispatcher.PostAfter(second, 10ms);
80*61c4878aSAndroid Build Coastguard Worker 
81*61c4878aSAndroid Build Coastguard Worker   RunLoopFor(zx::msec(25));
82*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(c, 123);
83*61c4878aSAndroid Build Coastguard Worker }
84*61c4878aSAndroid Build Coastguard Worker 
TEST_F(DispatcherFuchsiaTest,CancelTask)85*61c4878aSAndroid Build Coastguard Worker TEST_F(DispatcherFuchsiaTest, CancelTask) {
86*61c4878aSAndroid Build Coastguard Worker   FuchsiaDispatcher fuchsia_dispatcher(dispatcher());
87*61c4878aSAndroid Build Coastguard Worker 
88*61c4878aSAndroid Build Coastguard Worker   async::Task task([](async::Context& ctx, Status status) { FAIL(); });
89*61c4878aSAndroid Build Coastguard Worker   fuchsia_dispatcher.Post(task);
90*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(fuchsia_dispatcher.Cancel(task));
91*61c4878aSAndroid Build Coastguard Worker 
92*61c4878aSAndroid Build Coastguard Worker   RunLoopUntilIdle();
93*61c4878aSAndroid Build Coastguard Worker }
94*61c4878aSAndroid Build Coastguard Worker 
95*61c4878aSAndroid Build Coastguard Worker class DestructionChecker {
96*61c4878aSAndroid Build Coastguard Worker  public:
DestructionChecker(bool * flag)97*61c4878aSAndroid Build Coastguard Worker   explicit DestructionChecker(bool* flag) : flag_(flag) {}
DestructionChecker(DestructionChecker && other)98*61c4878aSAndroid Build Coastguard Worker   DestructionChecker(DestructionChecker&& other) {
99*61c4878aSAndroid Build Coastguard Worker     flag_ = other.flag_;
100*61c4878aSAndroid Build Coastguard Worker     other.flag_ = nullptr;
101*61c4878aSAndroid Build Coastguard Worker   }
~DestructionChecker()102*61c4878aSAndroid Build Coastguard Worker   ~DestructionChecker() {
103*61c4878aSAndroid Build Coastguard Worker     if (flag_) {
104*61c4878aSAndroid Build Coastguard Worker       *flag_ = true;
105*61c4878aSAndroid Build Coastguard Worker     }
106*61c4878aSAndroid Build Coastguard Worker   }
107*61c4878aSAndroid Build Coastguard Worker 
108*61c4878aSAndroid Build Coastguard Worker  private:
109*61c4878aSAndroid Build Coastguard Worker   bool* flag_;
110*61c4878aSAndroid Build Coastguard Worker };
111*61c4878aSAndroid Build Coastguard Worker 
TEST_F(DispatcherFuchsiaTest,HeapAllocatedTasks)112*61c4878aSAndroid Build Coastguard Worker TEST_F(DispatcherFuchsiaTest, HeapAllocatedTasks) {
113*61c4878aSAndroid Build Coastguard Worker   FuchsiaDispatcher fuchsia_dispatcher(dispatcher());
114*61c4878aSAndroid Build Coastguard Worker 
115*61c4878aSAndroid Build Coastguard Worker   int c = 0;
116*61c4878aSAndroid Build Coastguard Worker   for (int i = 0; i < 3; i++) {
117*61c4878aSAndroid Build Coastguard Worker     Post(&fuchsia_dispatcher, [&c](async::Context& ctx, Status status) {
118*61c4878aSAndroid Build Coastguard Worker       PW_TEST_ASSERT_OK(status);
119*61c4878aSAndroid Build Coastguard Worker       c++;
120*61c4878aSAndroid Build Coastguard Worker     });
121*61c4878aSAndroid Build Coastguard Worker   }
122*61c4878aSAndroid Build Coastguard Worker 
123*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(c, 0);
124*61c4878aSAndroid Build Coastguard Worker   RunLoopUntilIdle();
125*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(c, 3);
126*61c4878aSAndroid Build Coastguard Worker 
127*61c4878aSAndroid Build Coastguard Worker   // Test that the lambda is destroyed after being called.
128*61c4878aSAndroid Build Coastguard Worker   bool flag = false;
129*61c4878aSAndroid Build Coastguard Worker   Post(&fuchsia_dispatcher,
130*61c4878aSAndroid Build Coastguard Worker        [checker = DestructionChecker(&flag)](async::Context& ctx,
131*61c4878aSAndroid Build Coastguard Worker                                              Status status) {});
132*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(flag);
133*61c4878aSAndroid Build Coastguard Worker   RunLoopUntilIdle();
134*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(flag);
135*61c4878aSAndroid Build Coastguard Worker }
136*61c4878aSAndroid Build Coastguard Worker 
TEST_F(DispatcherFuchsiaTest,ChainedTasks)137*61c4878aSAndroid Build Coastguard Worker TEST_F(DispatcherFuchsiaTest, ChainedTasks) {
138*61c4878aSAndroid Build Coastguard Worker   FuchsiaDispatcher fuchsia_dispatcher(dispatcher());
139*61c4878aSAndroid Build Coastguard Worker 
140*61c4878aSAndroid Build Coastguard Worker   int c = 0;
141*61c4878aSAndroid Build Coastguard Worker 
142*61c4878aSAndroid Build Coastguard Worker   Post(&fuchsia_dispatcher, [&c](async::Context& ctx, Status status) {
143*61c4878aSAndroid Build Coastguard Worker     PW_TEST_ASSERT_OK(status);
144*61c4878aSAndroid Build Coastguard Worker     c++;
145*61c4878aSAndroid Build Coastguard Worker     Post(ctx.dispatcher, [&c](async::Context& ctx, Status status) {
146*61c4878aSAndroid Build Coastguard Worker       PW_TEST_ASSERT_OK(status);
147*61c4878aSAndroid Build Coastguard Worker       c++;
148*61c4878aSAndroid Build Coastguard Worker       Post(ctx.dispatcher, [&c](async::Context& ctx, Status status) {
149*61c4878aSAndroid Build Coastguard Worker         PW_TEST_ASSERT_OK(status);
150*61c4878aSAndroid Build Coastguard Worker         c++;
151*61c4878aSAndroid Build Coastguard Worker       });
152*61c4878aSAndroid Build Coastguard Worker     });
153*61c4878aSAndroid Build Coastguard Worker   });
154*61c4878aSAndroid Build Coastguard Worker 
155*61c4878aSAndroid Build Coastguard Worker   RunLoopUntilIdle();
156*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(c, 3);
157*61c4878aSAndroid Build Coastguard Worker }
158*61c4878aSAndroid Build Coastguard Worker 
159*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::async_fuchsia
160