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