xref: /aosp_15_r20/external/ot-br-posix/tests/gtest/test_task_runner.cpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1*4a64e381SAndroid Build Coastguard Worker /*
2*4a64e381SAndroid Build Coastguard Worker  *    Copyright (c) 2021, The OpenThread Authors.
3*4a64e381SAndroid Build Coastguard Worker  *    All rights reserved.
4*4a64e381SAndroid Build Coastguard Worker  *
5*4a64e381SAndroid Build Coastguard Worker  *    Redistribution and use in source and binary forms, with or without
6*4a64e381SAndroid Build Coastguard Worker  *    modification, are permitted provided that the following conditions are met:
7*4a64e381SAndroid Build Coastguard Worker  *    1. Redistributions of source code must retain the above copyright
8*4a64e381SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer.
9*4a64e381SAndroid Build Coastguard Worker  *    2. Redistributions in binary form must reproduce the above copyright
10*4a64e381SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer in the
11*4a64e381SAndroid Build Coastguard Worker  *       documentation and/or other materials provided with the distribution.
12*4a64e381SAndroid Build Coastguard Worker  *    3. Neither the name of the copyright holder nor the
13*4a64e381SAndroid Build Coastguard Worker  *       names of its contributors may be used to endorse or promote products
14*4a64e381SAndroid Build Coastguard Worker  *       derived from this software without specific prior written permission.
15*4a64e381SAndroid Build Coastguard Worker  *
16*4a64e381SAndroid Build Coastguard Worker  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*4a64e381SAndroid Build Coastguard Worker  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*4a64e381SAndroid Build Coastguard Worker  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*4a64e381SAndroid Build Coastguard Worker  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*4a64e381SAndroid Build Coastguard Worker  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*4a64e381SAndroid Build Coastguard Worker  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*4a64e381SAndroid Build Coastguard Worker  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*4a64e381SAndroid Build Coastguard Worker  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*4a64e381SAndroid Build Coastguard Worker  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*4a64e381SAndroid Build Coastguard Worker  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*4a64e381SAndroid Build Coastguard Worker  *    POSSIBILITY OF SUCH DAMAGE.
27*4a64e381SAndroid Build Coastguard Worker  */
28*4a64e381SAndroid Build Coastguard Worker 
29*4a64e381SAndroid Build Coastguard Worker #include <atomic>
30*4a64e381SAndroid Build Coastguard Worker #include <mutex>
31*4a64e381SAndroid Build Coastguard Worker #include <thread>
32*4a64e381SAndroid Build Coastguard Worker 
33*4a64e381SAndroid Build Coastguard Worker #include <gtest/gtest.h>
34*4a64e381SAndroid Build Coastguard Worker #include <unistd.h>
35*4a64e381SAndroid Build Coastguard Worker 
36*4a64e381SAndroid Build Coastguard Worker #include "common/task_runner.hpp"
37*4a64e381SAndroid Build Coastguard Worker 
TEST(TaskRunner,TestSingleThread)38*4a64e381SAndroid Build Coastguard Worker TEST(TaskRunner, TestSingleThread)
39*4a64e381SAndroid Build Coastguard Worker {
40*4a64e381SAndroid Build Coastguard Worker     int                   rval;
41*4a64e381SAndroid Build Coastguard Worker     int                   counter = 0;
42*4a64e381SAndroid Build Coastguard Worker     otbr::MainloopContext mainloop;
43*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner      taskRunner;
44*4a64e381SAndroid Build Coastguard Worker 
45*4a64e381SAndroid Build Coastguard Worker     mainloop.mMaxFd   = -1;
46*4a64e381SAndroid Build Coastguard Worker     mainloop.mTimeout = {10, 0};
47*4a64e381SAndroid Build Coastguard Worker 
48*4a64e381SAndroid Build Coastguard Worker     FD_ZERO(&mainloop.mReadFdSet);
49*4a64e381SAndroid Build Coastguard Worker     FD_ZERO(&mainloop.mWriteFdSet);
50*4a64e381SAndroid Build Coastguard Worker     FD_ZERO(&mainloop.mErrorFdSet);
51*4a64e381SAndroid Build Coastguard Worker 
52*4a64e381SAndroid Build Coastguard Worker     // Increase the `counter` to 3.
53*4a64e381SAndroid Build Coastguard Worker     taskRunner.Post([&]() {
54*4a64e381SAndroid Build Coastguard Worker         ++counter;
55*4a64e381SAndroid Build Coastguard Worker         taskRunner.Post([&]() {
56*4a64e381SAndroid Build Coastguard Worker             ++counter;
57*4a64e381SAndroid Build Coastguard Worker             taskRunner.Post([&]() { ++counter; });
58*4a64e381SAndroid Build Coastguard Worker         });
59*4a64e381SAndroid Build Coastguard Worker     });
60*4a64e381SAndroid Build Coastguard Worker 
61*4a64e381SAndroid Build Coastguard Worker     taskRunner.Update(mainloop);
62*4a64e381SAndroid Build Coastguard Worker     rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
63*4a64e381SAndroid Build Coastguard Worker                   &mainloop.mTimeout);
64*4a64e381SAndroid Build Coastguard Worker     EXPECT_EQ(1, rval);
65*4a64e381SAndroid Build Coastguard Worker 
66*4a64e381SAndroid Build Coastguard Worker     taskRunner.Process(mainloop);
67*4a64e381SAndroid Build Coastguard Worker     EXPECT_EQ(3, counter);
68*4a64e381SAndroid Build Coastguard Worker }
69*4a64e381SAndroid Build Coastguard Worker 
TEST(TaskRunner,TestTasksOrder)70*4a64e381SAndroid Build Coastguard Worker TEST(TaskRunner, TestTasksOrder)
71*4a64e381SAndroid Build Coastguard Worker {
72*4a64e381SAndroid Build Coastguard Worker     std::string           str;
73*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner      taskRunner;
74*4a64e381SAndroid Build Coastguard Worker     int                   rval;
75*4a64e381SAndroid Build Coastguard Worker     otbr::MainloopContext mainloop;
76*4a64e381SAndroid Build Coastguard Worker 
77*4a64e381SAndroid Build Coastguard Worker     taskRunner.Post([&]() { str.push_back('a'); });
78*4a64e381SAndroid Build Coastguard Worker     taskRunner.Post([&]() { str.push_back('b'); });
79*4a64e381SAndroid Build Coastguard Worker     taskRunner.Post([&]() { str.push_back('c'); });
80*4a64e381SAndroid Build Coastguard Worker 
81*4a64e381SAndroid Build Coastguard Worker     mainloop.mMaxFd   = -1;
82*4a64e381SAndroid Build Coastguard Worker     mainloop.mTimeout = {2, 0};
83*4a64e381SAndroid Build Coastguard Worker 
84*4a64e381SAndroid Build Coastguard Worker     FD_ZERO(&mainloop.mReadFdSet);
85*4a64e381SAndroid Build Coastguard Worker     FD_ZERO(&mainloop.mWriteFdSet);
86*4a64e381SAndroid Build Coastguard Worker     FD_ZERO(&mainloop.mErrorFdSet);
87*4a64e381SAndroid Build Coastguard Worker 
88*4a64e381SAndroid Build Coastguard Worker     taskRunner.Update(mainloop);
89*4a64e381SAndroid Build Coastguard Worker     rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
90*4a64e381SAndroid Build Coastguard Worker                   &mainloop.mTimeout);
91*4a64e381SAndroid Build Coastguard Worker     EXPECT_EQ(rval, 1);
92*4a64e381SAndroid Build Coastguard Worker 
93*4a64e381SAndroid Build Coastguard Worker     taskRunner.Process(mainloop);
94*4a64e381SAndroid Build Coastguard Worker 
95*4a64e381SAndroid Build Coastguard Worker     // Make sure the tasks are executed in the order of posting.
96*4a64e381SAndroid Build Coastguard Worker     EXPECT_STREQ("abc", str.c_str());
97*4a64e381SAndroid Build Coastguard Worker }
98*4a64e381SAndroid Build Coastguard Worker 
TEST(TaskRunner,TestMultipleThreads)99*4a64e381SAndroid Build Coastguard Worker TEST(TaskRunner, TestMultipleThreads)
100*4a64e381SAndroid Build Coastguard Worker {
101*4a64e381SAndroid Build Coastguard Worker     std::atomic<int>         counter{0};
102*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner         taskRunner;
103*4a64e381SAndroid Build Coastguard Worker     std::vector<std::thread> threads;
104*4a64e381SAndroid Build Coastguard Worker 
105*4a64e381SAndroid Build Coastguard Worker     // Increase the `counter` to 10 in separate threads.
106*4a64e381SAndroid Build Coastguard Worker     for (size_t i = 0; i < 10; ++i)
107*4a64e381SAndroid Build Coastguard Worker     {
108*4a64e381SAndroid Build Coastguard Worker         threads.emplace_back([&]() { taskRunner.Post([&]() { ++counter; }); });
109*4a64e381SAndroid Build Coastguard Worker     }
110*4a64e381SAndroid Build Coastguard Worker 
111*4a64e381SAndroid Build Coastguard Worker     while (counter.load() < 10)
112*4a64e381SAndroid Build Coastguard Worker     {
113*4a64e381SAndroid Build Coastguard Worker         int                   rval;
114*4a64e381SAndroid Build Coastguard Worker         otbr::MainloopContext mainloop;
115*4a64e381SAndroid Build Coastguard Worker 
116*4a64e381SAndroid Build Coastguard Worker         mainloop.mMaxFd   = -1;
117*4a64e381SAndroid Build Coastguard Worker         mainloop.mTimeout = {10, 0};
118*4a64e381SAndroid Build Coastguard Worker 
119*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mReadFdSet);
120*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mWriteFdSet);
121*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mErrorFdSet);
122*4a64e381SAndroid Build Coastguard Worker 
123*4a64e381SAndroid Build Coastguard Worker         taskRunner.Update(mainloop);
124*4a64e381SAndroid Build Coastguard Worker         rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
125*4a64e381SAndroid Build Coastguard Worker                       &mainloop.mTimeout);
126*4a64e381SAndroid Build Coastguard Worker         EXPECT_EQ(1, rval);
127*4a64e381SAndroid Build Coastguard Worker 
128*4a64e381SAndroid Build Coastguard Worker         taskRunner.Process(mainloop);
129*4a64e381SAndroid Build Coastguard Worker     }
130*4a64e381SAndroid Build Coastguard Worker 
131*4a64e381SAndroid Build Coastguard Worker     for (auto &th : threads)
132*4a64e381SAndroid Build Coastguard Worker     {
133*4a64e381SAndroid Build Coastguard Worker         th.join();
134*4a64e381SAndroid Build Coastguard Worker     }
135*4a64e381SAndroid Build Coastguard Worker 
136*4a64e381SAndroid Build Coastguard Worker     EXPECT_EQ(10, counter.load());
137*4a64e381SAndroid Build Coastguard Worker }
138*4a64e381SAndroid Build Coastguard Worker 
TEST(TaskRunner,TestPostAndWait)139*4a64e381SAndroid Build Coastguard Worker TEST(TaskRunner, TestPostAndWait)
140*4a64e381SAndroid Build Coastguard Worker {
141*4a64e381SAndroid Build Coastguard Worker     std::atomic<int>         total{0};
142*4a64e381SAndroid Build Coastguard Worker     std::atomic<int>         counter{0};
143*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner         taskRunner;
144*4a64e381SAndroid Build Coastguard Worker     std::vector<std::thread> threads;
145*4a64e381SAndroid Build Coastguard Worker 
146*4a64e381SAndroid Build Coastguard Worker     // Increase the `counter` to 10 in separate threads and accumulate the total value.
147*4a64e381SAndroid Build Coastguard Worker     for (size_t i = 0; i < 10; ++i)
148*4a64e381SAndroid Build Coastguard Worker     {
149*4a64e381SAndroid Build Coastguard Worker         threads.emplace_back([&]() { total += taskRunner.PostAndWait<int>([&]() { return ++counter; }); });
150*4a64e381SAndroid Build Coastguard Worker     }
151*4a64e381SAndroid Build Coastguard Worker 
152*4a64e381SAndroid Build Coastguard Worker     while (counter.load() < 10)
153*4a64e381SAndroid Build Coastguard Worker     {
154*4a64e381SAndroid Build Coastguard Worker         int                   rval;
155*4a64e381SAndroid Build Coastguard Worker         otbr::MainloopContext mainloop;
156*4a64e381SAndroid Build Coastguard Worker 
157*4a64e381SAndroid Build Coastguard Worker         mainloop.mMaxFd   = -1;
158*4a64e381SAndroid Build Coastguard Worker         mainloop.mTimeout = {10, 0};
159*4a64e381SAndroid Build Coastguard Worker 
160*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mReadFdSet);
161*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mWriteFdSet);
162*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mErrorFdSet);
163*4a64e381SAndroid Build Coastguard Worker 
164*4a64e381SAndroid Build Coastguard Worker         taskRunner.Update(mainloop);
165*4a64e381SAndroid Build Coastguard Worker         rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
166*4a64e381SAndroid Build Coastguard Worker                       &mainloop.mTimeout);
167*4a64e381SAndroid Build Coastguard Worker         EXPECT_EQ(1, rval);
168*4a64e381SAndroid Build Coastguard Worker 
169*4a64e381SAndroid Build Coastguard Worker         taskRunner.Process(mainloop);
170*4a64e381SAndroid Build Coastguard Worker     }
171*4a64e381SAndroid Build Coastguard Worker 
172*4a64e381SAndroid Build Coastguard Worker     for (auto &th : threads)
173*4a64e381SAndroid Build Coastguard Worker     {
174*4a64e381SAndroid Build Coastguard Worker         th.join();
175*4a64e381SAndroid Build Coastguard Worker     }
176*4a64e381SAndroid Build Coastguard Worker 
177*4a64e381SAndroid Build Coastguard Worker     EXPECT_EQ(55, total);
178*4a64e381SAndroid Build Coastguard Worker     EXPECT_EQ(10, counter.load());
179*4a64e381SAndroid Build Coastguard Worker }
180*4a64e381SAndroid Build Coastguard Worker 
TEST(TaskRunner,TestDelayedTasks)181*4a64e381SAndroid Build Coastguard Worker TEST(TaskRunner, TestDelayedTasks)
182*4a64e381SAndroid Build Coastguard Worker {
183*4a64e381SAndroid Build Coastguard Worker     std::atomic<int>         counter{0};
184*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner         taskRunner;
185*4a64e381SAndroid Build Coastguard Worker     std::vector<std::thread> threads;
186*4a64e381SAndroid Build Coastguard Worker 
187*4a64e381SAndroid Build Coastguard Worker     // Increase the `counter` to 10 in separate threads.
188*4a64e381SAndroid Build Coastguard Worker     for (size_t i = 0; i < 10; ++i)
189*4a64e381SAndroid Build Coastguard Worker     {
190*4a64e381SAndroid Build Coastguard Worker         threads.emplace_back([&]() { taskRunner.Post(std::chrono::milliseconds(10), [&]() { ++counter; }); });
191*4a64e381SAndroid Build Coastguard Worker     }
192*4a64e381SAndroid Build Coastguard Worker 
193*4a64e381SAndroid Build Coastguard Worker     while (counter.load() < 10)
194*4a64e381SAndroid Build Coastguard Worker     {
195*4a64e381SAndroid Build Coastguard Worker         int                   rval;
196*4a64e381SAndroid Build Coastguard Worker         otbr::MainloopContext mainloop;
197*4a64e381SAndroid Build Coastguard Worker 
198*4a64e381SAndroid Build Coastguard Worker         mainloop.mMaxFd   = -1;
199*4a64e381SAndroid Build Coastguard Worker         mainloop.mTimeout = {2, 0};
200*4a64e381SAndroid Build Coastguard Worker 
201*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mReadFdSet);
202*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mWriteFdSet);
203*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mErrorFdSet);
204*4a64e381SAndroid Build Coastguard Worker 
205*4a64e381SAndroid Build Coastguard Worker         taskRunner.Update(mainloop);
206*4a64e381SAndroid Build Coastguard Worker         rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
207*4a64e381SAndroid Build Coastguard Worker                       &mainloop.mTimeout);
208*4a64e381SAndroid Build Coastguard Worker         EXPECT_TRUE(rval >= 0 || errno == EINTR);
209*4a64e381SAndroid Build Coastguard Worker 
210*4a64e381SAndroid Build Coastguard Worker         taskRunner.Process(mainloop);
211*4a64e381SAndroid Build Coastguard Worker     }
212*4a64e381SAndroid Build Coastguard Worker 
213*4a64e381SAndroid Build Coastguard Worker     for (auto &th : threads)
214*4a64e381SAndroid Build Coastguard Worker     {
215*4a64e381SAndroid Build Coastguard Worker         th.join();
216*4a64e381SAndroid Build Coastguard Worker     }
217*4a64e381SAndroid Build Coastguard Worker 
218*4a64e381SAndroid Build Coastguard Worker     EXPECT_EQ(10, counter.load());
219*4a64e381SAndroid Build Coastguard Worker }
220*4a64e381SAndroid Build Coastguard Worker 
TEST(TaskRunner,TestDelayedTasksOrder)221*4a64e381SAndroid Build Coastguard Worker TEST(TaskRunner, TestDelayedTasksOrder)
222*4a64e381SAndroid Build Coastguard Worker {
223*4a64e381SAndroid Build Coastguard Worker     std::string      str;
224*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner taskRunner;
225*4a64e381SAndroid Build Coastguard Worker 
226*4a64e381SAndroid Build Coastguard Worker     taskRunner.Post(std::chrono::milliseconds(10), [&]() { str.push_back('a'); });
227*4a64e381SAndroid Build Coastguard Worker     taskRunner.Post(std::chrono::milliseconds(9), [&]() { str.push_back('b'); });
228*4a64e381SAndroid Build Coastguard Worker     taskRunner.Post(std::chrono::milliseconds(10), [&]() { str.push_back('c'); });
229*4a64e381SAndroid Build Coastguard Worker 
230*4a64e381SAndroid Build Coastguard Worker     while (str.size() < 3)
231*4a64e381SAndroid Build Coastguard Worker     {
232*4a64e381SAndroid Build Coastguard Worker         int                   rval;
233*4a64e381SAndroid Build Coastguard Worker         otbr::MainloopContext mainloop;
234*4a64e381SAndroid Build Coastguard Worker 
235*4a64e381SAndroid Build Coastguard Worker         mainloop.mMaxFd   = -1;
236*4a64e381SAndroid Build Coastguard Worker         mainloop.mTimeout = {2, 0};
237*4a64e381SAndroid Build Coastguard Worker 
238*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mReadFdSet);
239*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mWriteFdSet);
240*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mErrorFdSet);
241*4a64e381SAndroid Build Coastguard Worker 
242*4a64e381SAndroid Build Coastguard Worker         taskRunner.Update(mainloop);
243*4a64e381SAndroid Build Coastguard Worker         rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
244*4a64e381SAndroid Build Coastguard Worker                       &mainloop.mTimeout);
245*4a64e381SAndroid Build Coastguard Worker         EXPECT_TRUE(rval >= 0 || errno == EINTR);
246*4a64e381SAndroid Build Coastguard Worker 
247*4a64e381SAndroid Build Coastguard Worker         taskRunner.Process(mainloop);
248*4a64e381SAndroid Build Coastguard Worker     }
249*4a64e381SAndroid Build Coastguard Worker 
250*4a64e381SAndroid Build Coastguard Worker     // Make sure that tasks with smaller delay are executed earlier.
251*4a64e381SAndroid Build Coastguard Worker     EXPECT_STREQ("bac", str.c_str());
252*4a64e381SAndroid Build Coastguard Worker }
253*4a64e381SAndroid Build Coastguard Worker 
TEST(TaskRunner,TestCancelDelayedTasks)254*4a64e381SAndroid Build Coastguard Worker TEST(TaskRunner, TestCancelDelayedTasks)
255*4a64e381SAndroid Build Coastguard Worker {
256*4a64e381SAndroid Build Coastguard Worker     std::string              str;
257*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner         taskRunner;
258*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner::TaskId tid1, tid2, tid3, tid4, tid5;
259*4a64e381SAndroid Build Coastguard Worker 
260*4a64e381SAndroid Build Coastguard Worker     tid1 = taskRunner.Post(std::chrono::milliseconds(10), [&]() { str.push_back('a'); });
261*4a64e381SAndroid Build Coastguard Worker     tid2 = taskRunner.Post(std::chrono::milliseconds(20), [&]() { str.push_back('b'); });
262*4a64e381SAndroid Build Coastguard Worker     tid3 = taskRunner.Post(std::chrono::milliseconds(30), [&]() { str.push_back('c'); });
263*4a64e381SAndroid Build Coastguard Worker     tid4 = taskRunner.Post(std::chrono::milliseconds(40), [&]() { str.push_back('d'); });
264*4a64e381SAndroid Build Coastguard Worker     tid5 = taskRunner.Post(std::chrono::milliseconds(50), [&]() { str.push_back('e'); });
265*4a64e381SAndroid Build Coastguard Worker 
266*4a64e381SAndroid Build Coastguard Worker     EXPECT_TRUE(0 < tid1);
267*4a64e381SAndroid Build Coastguard Worker     EXPECT_TRUE(tid1 < tid2);
268*4a64e381SAndroid Build Coastguard Worker     EXPECT_TRUE(tid2 < tid3);
269*4a64e381SAndroid Build Coastguard Worker     EXPECT_TRUE(tid3 < tid4);
270*4a64e381SAndroid Build Coastguard Worker     EXPECT_TRUE(tid4 < tid5);
271*4a64e381SAndroid Build Coastguard Worker 
272*4a64e381SAndroid Build Coastguard Worker     taskRunner.Cancel(tid2);
273*4a64e381SAndroid Build Coastguard Worker 
274*4a64e381SAndroid Build Coastguard Worker     taskRunner.Post(std::chrono::milliseconds(10), [&]() { taskRunner.Cancel(tid3); });
275*4a64e381SAndroid Build Coastguard Worker     std::thread t([&]() {
276*4a64e381SAndroid Build Coastguard Worker         usleep(20);
277*4a64e381SAndroid Build Coastguard Worker         taskRunner.Cancel(tid4);
278*4a64e381SAndroid Build Coastguard Worker     });
279*4a64e381SAndroid Build Coastguard Worker 
280*4a64e381SAndroid Build Coastguard Worker     while (str.size() < 2)
281*4a64e381SAndroid Build Coastguard Worker     {
282*4a64e381SAndroid Build Coastguard Worker         int                   rval;
283*4a64e381SAndroid Build Coastguard Worker         otbr::MainloopContext mainloop;
284*4a64e381SAndroid Build Coastguard Worker 
285*4a64e381SAndroid Build Coastguard Worker         mainloop.mMaxFd   = -1;
286*4a64e381SAndroid Build Coastguard Worker         mainloop.mTimeout = {2, 0};
287*4a64e381SAndroid Build Coastguard Worker 
288*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mReadFdSet);
289*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mWriteFdSet);
290*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mErrorFdSet);
291*4a64e381SAndroid Build Coastguard Worker 
292*4a64e381SAndroid Build Coastguard Worker         taskRunner.Update(mainloop);
293*4a64e381SAndroid Build Coastguard Worker         rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
294*4a64e381SAndroid Build Coastguard Worker                       &mainloop.mTimeout);
295*4a64e381SAndroid Build Coastguard Worker         EXPECT_TRUE(rval >= 0 || errno == EINTR);
296*4a64e381SAndroid Build Coastguard Worker 
297*4a64e381SAndroid Build Coastguard Worker         taskRunner.Process(mainloop);
298*4a64e381SAndroid Build Coastguard Worker     }
299*4a64e381SAndroid Build Coastguard Worker 
300*4a64e381SAndroid Build Coastguard Worker     // Make sure the delayed task was not executed.
301*4a64e381SAndroid Build Coastguard Worker     EXPECT_STREQ("ae", str.c_str());
302*4a64e381SAndroid Build Coastguard Worker 
303*4a64e381SAndroid Build Coastguard Worker     // Make sure it's fine to cancel expired task IDs.
304*4a64e381SAndroid Build Coastguard Worker     taskRunner.Cancel(tid1);
305*4a64e381SAndroid Build Coastguard Worker     taskRunner.Cancel(tid2);
306*4a64e381SAndroid Build Coastguard Worker     t.join();
307*4a64e381SAndroid Build Coastguard Worker }
308*4a64e381SAndroid Build Coastguard Worker 
TEST(TaskRunner,TestAllAPIs)309*4a64e381SAndroid Build Coastguard Worker TEST(TaskRunner, TestAllAPIs)
310*4a64e381SAndroid Build Coastguard Worker {
311*4a64e381SAndroid Build Coastguard Worker     std::atomic<int>         counter{0};
312*4a64e381SAndroid Build Coastguard Worker     otbr::TaskRunner         taskRunner;
313*4a64e381SAndroid Build Coastguard Worker     std::vector<std::thread> threads;
314*4a64e381SAndroid Build Coastguard Worker 
315*4a64e381SAndroid Build Coastguard Worker     // Increase the `counter` to 30 in separate threads.
316*4a64e381SAndroid Build Coastguard Worker     for (size_t i = 0; i < 10; ++i)
317*4a64e381SAndroid Build Coastguard Worker     {
318*4a64e381SAndroid Build Coastguard Worker         threads.emplace_back([&]() { taskRunner.Post([&]() { ++counter; }); });
319*4a64e381SAndroid Build Coastguard Worker         threads.emplace_back([&]() { taskRunner.Post(std::chrono::milliseconds(10), [&]() { ++counter; }); });
320*4a64e381SAndroid Build Coastguard Worker         threads.emplace_back([&]() { taskRunner.PostAndWait<int>([&]() { return ++counter; }); });
321*4a64e381SAndroid Build Coastguard Worker     }
322*4a64e381SAndroid Build Coastguard Worker 
323*4a64e381SAndroid Build Coastguard Worker     while (counter.load() < 30)
324*4a64e381SAndroid Build Coastguard Worker     {
325*4a64e381SAndroid Build Coastguard Worker         int                   rval;
326*4a64e381SAndroid Build Coastguard Worker         otbr::MainloopContext mainloop;
327*4a64e381SAndroid Build Coastguard Worker 
328*4a64e381SAndroid Build Coastguard Worker         mainloop.mMaxFd   = -1;
329*4a64e381SAndroid Build Coastguard Worker         mainloop.mTimeout = {2, 0};
330*4a64e381SAndroid Build Coastguard Worker 
331*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mReadFdSet);
332*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mWriteFdSet);
333*4a64e381SAndroid Build Coastguard Worker         FD_ZERO(&mainloop.mErrorFdSet);
334*4a64e381SAndroid Build Coastguard Worker 
335*4a64e381SAndroid Build Coastguard Worker         taskRunner.Update(mainloop);
336*4a64e381SAndroid Build Coastguard Worker         rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
337*4a64e381SAndroid Build Coastguard Worker                       &mainloop.mTimeout);
338*4a64e381SAndroid Build Coastguard Worker         EXPECT_TRUE(rval >= 0 || errno == EINTR);
339*4a64e381SAndroid Build Coastguard Worker 
340*4a64e381SAndroid Build Coastguard Worker         taskRunner.Process(mainloop);
341*4a64e381SAndroid Build Coastguard Worker     }
342*4a64e381SAndroid Build Coastguard Worker 
343*4a64e381SAndroid Build Coastguard Worker     for (auto &th : threads)
344*4a64e381SAndroid Build Coastguard Worker     {
345*4a64e381SAndroid Build Coastguard Worker         th.join();
346*4a64e381SAndroid Build Coastguard Worker     }
347*4a64e381SAndroid Build Coastguard Worker 
348*4a64e381SAndroid Build Coastguard Worker     EXPECT_EQ(30, counter.load());
349*4a64e381SAndroid Build Coastguard Worker }
350