1 /*
2 * Copyright (C) 2022 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 <chrono>
18 #include <cmath>
19 #include <mutex>
20 #include <optional>
21
22 #include "gtest/gtest.h"
23
24 #include "chre/platform/linux/task_util/task_manager.h"
25
26 namespace {
27
TEST(TaskManager,FlushTasksCanBeCalledMultipleTimes)28 TEST(TaskManager, FlushTasksCanBeCalledMultipleTimes) {
29 chre::TaskManager taskManager;
30
31 constexpr uint32_t numCallsToFlush = 50;
32 for (uint32_t i = 0; i < numCallsToFlush; ++i) {
33 taskManager.flushTasks();
34 }
35 }
36
TEST(TaskManager,MultipleNonRepeatingTasksAreExecuted)37 TEST(TaskManager, MultipleNonRepeatingTasksAreExecuted) {
38 uint32_t counter = 0;
39 std::mutex mutex;
40 std::condition_variable condVar;
41 chre::TaskManager taskManager;
42
43 constexpr uint32_t numTasks = 50;
44 auto incrementFunc = [&mutex, &condVar, &counter]() {
45 {
46 std::unique_lock<std::mutex> lock(mutex);
47 ++counter;
48 }
49
50 condVar.notify_all();
51 };
52 for (uint32_t i = 0; i < numTasks; ++i) {
53 std::optional<uint32_t> taskId =
54 taskManager.addTask(incrementFunc,
55 /* intervalOrDelay */ std::chrono::nanoseconds(0));
56 EXPECT_TRUE(taskId.has_value());
57 }
58
59 std::unique_lock<std::mutex> lock(mutex);
60 condVar.wait(lock, [&counter]() { return counter >= numTasks; });
61 taskManager.flushTasks();
62 EXPECT_EQ(counter, numTasks);
63 }
64
TEST(TaskManager,RepeatingAndOneShotTasksCanExecuteTogether)65 TEST(TaskManager, RepeatingAndOneShotTasksCanExecuteTogether) {
66 uint32_t counter = 0;
67 std::mutex mutex;
68 std::condition_variable condVar;
69 chre::TaskManager taskManager;
70
71 constexpr uint32_t numTasks = 50;
72 auto incrementFunc = [&mutex, &condVar, &counter]() {
73 {
74 std::unique_lock<std::mutex> lock(mutex);
75 ++counter;
76 }
77
78 condVar.notify_all();
79 };
80 for (uint32_t i = 0; i < numTasks; ++i) {
81 std::optional<uint32_t> taskId =
82 taskManager.addTask(incrementFunc,
83 /* intervalOrDelay */ std::chrono::nanoseconds(0));
84 EXPECT_TRUE(taskId.has_value());
85 }
86
87 constexpr std::chrono::nanoseconds interval(50);
88 std::optional<uint32_t> taskId = taskManager.addTask(incrementFunc, interval);
89 ASSERT_TRUE(taskId.has_value());
90
91 constexpr uint32_t taskRepeatTimesMax = 5;
92 std::unique_lock<std::mutex> lock(mutex);
93 condVar.wait(
94 lock, [&counter]() { return counter >= numTasks + taskRepeatTimesMax; });
95 EXPECT_TRUE(taskManager.cancelTask(taskId.value()));
96 taskManager.flushTasks();
97 EXPECT_GE(counter, numTasks + taskRepeatTimesMax);
98 }
99
TEST(TaskManager,TasksCanBeFlushedEvenIfNotCancelled)100 TEST(TaskManager, TasksCanBeFlushedEvenIfNotCancelled) {
101 uint32_t counter = 0;
102 std::mutex mutex;
103 std::condition_variable condVar;
104 chre::TaskManager taskManager;
105
106 constexpr uint32_t numTasks = 50;
107 auto incrementFunc = [&mutex, &condVar, &counter]() {
108 {
109 std::unique_lock<std::mutex> lock(mutex);
110 ++counter;
111 }
112
113 condVar.notify_all();
114 };
115 for (uint32_t i = 0; i < numTasks; ++i) {
116 std::optional<uint32_t> taskId =
117 taskManager.addTask(incrementFunc,
118 /* intervalOrDelay */ std::chrono::nanoseconds(0));
119 EXPECT_TRUE(taskId.has_value());
120 }
121
122 constexpr std::chrono::nanoseconds interval(50);
123 std::optional<uint32_t> taskId = taskManager.addTask(incrementFunc, interval);
124 ASSERT_TRUE(taskId.has_value());
125
126 constexpr uint32_t taskRepeatTimesMax = 5;
127 std::unique_lock<std::mutex> lock(mutex);
128 condVar.wait(
129 lock, [&counter]() { return counter >= numTasks + taskRepeatTimesMax; });
130 taskManager.flushTasks();
131 EXPECT_GE(counter, numTasks + taskRepeatTimesMax);
132 }
133
TEST(TaskManager,StopTaskCanBeCalledMultipleTimes)134 TEST(TaskManager, StopTaskCanBeCalledMultipleTimes) {
135 uint32_t counter = 0;
136 std::mutex mutex;
137 std::condition_variable condVar;
138 chre::TaskManager taskManager;
139
140 constexpr uint32_t numTasks = 50;
141 auto incrementFunc = [&mutex, &condVar, &counter]() {
142 {
143 std::unique_lock<std::mutex> lock(mutex);
144 ++counter;
145 }
146
147 condVar.notify_all();
148 };
149 for (uint32_t i = 0; i < numTasks; ++i) {
150 std::optional<uint32_t> taskId =
151 taskManager.addTask(incrementFunc,
152 /* intervalOrDelay */ std::chrono::nanoseconds(0));
153 EXPECT_TRUE(taskId.has_value());
154 }
155
156 std::unique_lock<std::mutex> lock(mutex);
157 condVar.wait(lock, [&counter]() { return counter >= numTasks; });
158 EXPECT_EQ(counter, numTasks);
159
160 taskManager.flushAndStop();
161 taskManager.flushAndStop();
162 taskManager.flushAndStop();
163 }
164
TEST(TaskManager,StopTaskCanBeCalledOnNewTaskManager)165 TEST(TaskManager, StopTaskCanBeCalledOnNewTaskManager) {
166 chre::TaskManager taskManager;
167 taskManager.flushAndStop();
168 taskManager.flushAndStop();
169 taskManager.flushAndStop();
170 }
171
172 } // namespace
173