1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <broadcastradio-utils/WorkerThread.h>
18 #include <gtest/gtest.h>
19
20 namespace {
21
22 using namespace std::chrono_literals;
23
24 using android::WorkerThread;
25
26 using std::atomic;
27 using std::chrono::time_point;
28 using std::chrono::steady_clock;
29 using std::is_sorted;
30 using std::lock_guard;
31 using std::mutex;
32 using std::this_thread::sleep_for;
33 using std::vector;
34
35 #define ASSERT_EQ_WITH_TOLERANCE(val1, val2, tolerance) \
36 ASSERT_LE((val1) - (tolerance), (val2)); \
37 ASSERT_GE((val1) + (tolerance), (val2));
38
TEST(WorkerThreadTest,oneTask)39 TEST(WorkerThreadTest, oneTask) {
40 atomic<bool> executed(false);
41 atomic<time_point<steady_clock>> stop;
42 WorkerThread thread;
43
44 auto start = steady_clock::now();
45 thread.schedule(
46 [&]() {
47 stop = steady_clock::now();
48 executed = true;
49 },
50 100ms);
51
52 sleep_for(150ms);
53
54 ASSERT_TRUE(executed);
55 auto delta = stop.load() - start;
56 ASSERT_EQ_WITH_TOLERANCE(delta, 100ms, 50ms);
57 }
58
TEST(WorkerThreadTest,cancelSecond)59 TEST(WorkerThreadTest, cancelSecond) {
60 atomic<bool> executed1(false);
61 atomic<bool> executed2(false);
62 WorkerThread thread;
63
64 thread.schedule([&]() { executed2 = true; }, 100ms);
65 thread.schedule([&]() { executed1 = true; }, 25ms);
66
67 sleep_for(50ms);
68 thread.cancelAll();
69 sleep_for(100ms);
70
71 ASSERT_TRUE(executed1);
72 ASSERT_FALSE(executed2);
73 }
74
TEST(WorkerThreadTest,executeInOrder)75 TEST(WorkerThreadTest, executeInOrder) {
76 mutex mut;
77 vector<int> order;
78 WorkerThread thread;
79
80 thread.schedule(
81 [&]() {
82 lock_guard<mutex> lk(mut);
83 order.push_back(0);
84 },
85 50ms);
86
87 thread.schedule(
88 [&]() {
89 lock_guard<mutex> lk(mut);
90 order.push_back(4);
91 },
92 400ms);
93
94 thread.schedule(
95 [&]() {
96 lock_guard<mutex> lk(mut);
97 order.push_back(1);
98 },
99 100ms);
100
101 thread.schedule(
102 [&]() {
103 lock_guard<mutex> lk(mut);
104 order.push_back(3);
105 },
106 300ms);
107
108 thread.schedule(
109 [&]() {
110 lock_guard<mutex> lk(mut);
111 order.push_back(2);
112 },
113 200ms);
114
115 sleep_for(500ms);
116
117 ASSERT_EQ(5u, order.size());
118 ASSERT_TRUE(is_sorted(order.begin(), order.end()));
119 }
120
TEST(WorkerThreadTest,dontExecuteAfterDestruction)121 TEST(WorkerThreadTest, dontExecuteAfterDestruction) {
122 atomic<bool> executed1(false);
123 atomic<bool> executed2(false);
124 {
125 WorkerThread thread;
126
127 thread.schedule([&]() { executed2 = true; }, 100ms);
128 thread.schedule([&]() { executed1 = true; }, 25ms);
129
130 sleep_for(50ms);
131 }
132 sleep_for(100ms);
133
134 ASSERT_TRUE(executed1);
135 ASSERT_FALSE(executed2);
136 }
137
138 } // anonymous namespace
139