xref: /aosp_15_r20/system/chre/platform/linux/tests/task_manager_test.cc (revision 84e339476a462649f82315436d70fd732297a399)
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