2 * Copyright (c) 2021, The OpenThread Authors.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include "common/task_runner.hpp"
35 #include <CppUTest/TestHarness.h>
37 TEST_GROUP(TaskRunner){};
39 TEST(TaskRunner, TestSingleThread)
43 otSysMainloopContext mainloop;
44 otbr::TaskRunner taskRunner;
47 mainloop.mTimeout = {10, 0};
49 FD_ZERO(&mainloop.mReadFdSet);
50 FD_ZERO(&mainloop.mWriteFdSet);
51 FD_ZERO(&mainloop.mErrorFdSet);
53 // Increase the `counter` to 3.
54 taskRunner.Post([&]() {
56 taskRunner.Post([&]() {
58 taskRunner.Post([&]() { ++counter; });
62 taskRunner.UpdateFdSet(mainloop);
63 rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
67 taskRunner.Process(mainloop);
68 CHECK_EQUAL(3, counter);
71 TEST(TaskRunner, TestMultipleThreads)
73 std::atomic<int> counter{0};
74 otbr::TaskRunner taskRunner;
75 std::vector<std::thread> threads;
77 // Increase the `counter` to 10 in separate threads.
78 for (size_t i = 0; i < 10; ++i)
80 threads.emplace_back([&]() { taskRunner.Post([&]() { ++counter; }); });
83 while (counter.load() < 10)
86 otSysMainloopContext mainloop;
89 mainloop.mTimeout = {10, 0};
91 FD_ZERO(&mainloop.mReadFdSet);
92 FD_ZERO(&mainloop.mWriteFdSet);
93 FD_ZERO(&mainloop.mErrorFdSet);
95 taskRunner.UpdateFdSet(mainloop);
96 rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
100 taskRunner.Process(mainloop);
103 for (auto &th : threads)
108 CHECK_EQUAL(10, counter.load());
111 TEST(TaskRunner, TestPostAndWait)
113 std::atomic<int> total{0};
114 std::atomic<int> counter{0};
115 otbr::TaskRunner taskRunner;
116 std::vector<std::thread> threads;
118 // Increase the `counter` to 10 in separate threads and accumulate the total value.
119 for (size_t i = 0; i < 10; ++i)
121 threads.emplace_back([&]() { total += taskRunner.PostAndWait<int>([&]() { return ++counter; }); });
124 while (counter.load() < 10)
127 otSysMainloopContext mainloop;
129 mainloop.mMaxFd = -1;
130 mainloop.mTimeout = {10, 0};
132 FD_ZERO(&mainloop.mReadFdSet);
133 FD_ZERO(&mainloop.mWriteFdSet);
134 FD_ZERO(&mainloop.mErrorFdSet);
136 taskRunner.UpdateFdSet(mainloop);
137 rval = select(mainloop.mMaxFd + 1, &mainloop.mReadFdSet, &mainloop.mWriteFdSet, &mainloop.mErrorFdSet,
139 CHECK_EQUAL(1, rval);
141 taskRunner.Process(mainloop);
144 for (auto &th : threads)
149 CHECK_EQUAL(55, total);
150 CHECK_EQUAL(10, counter.load());