1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "watchdog_interface_test.h"
17
18 #include <gtest/gtest.h>
19 #include <string>
20 #include <thread>
21
22 #include "directory_ex.h"
23 #include "file_ex.h"
24 #include "event_handler.h"
25 #include "ffrt_inner.h"
26 #include "watchdog.h"
27
28 using namespace testing::ext;
29 using namespace OHOS::AppExecFwk;
30 namespace OHOS {
31 namespace HiviewDFX {
32 class TestEventHandler : public EventHandler {
33 public:
TestEventHandler(const std::shared_ptr<EventRunner> & runner)34 explicit TestEventHandler(const std::shared_ptr<EventRunner> &runner)
35 : EventHandler(runner) {};
~TestEventHandler()36 ~TestEventHandler() {};
ProcessEvent(const InnerEvent::Pointer & event)37 void ProcessEvent(const InnerEvent::Pointer &event)
38 {
39 count++;
40 }
41 int count;
42 };
43
44 constexpr int PERIODICAL_TASK_TIME = 2000;
45 constexpr int TOTAL_WAIT_TIME = 11;
46 constexpr int EXPECT_RUN_TIMES = 5;
SetUpTestCase(void)47 void WatchdogInterfaceTest::SetUpTestCase(void)
48 {
49 }
50
TearDownTestCase(void)51 void WatchdogInterfaceTest::TearDownTestCase(void)
52 {
53 }
54
SetUp(void)55 void WatchdogInterfaceTest::SetUp(void)
56 {
57 }
58
TearDown(void)59 void WatchdogInterfaceTest::TearDown(void)
60 {
61 }
62
63 int g_ret = 0;
DoAddWatchThread()64 void WatchdogInterfaceTest::DoAddWatchThread()
65 {
66 auto runner = EventRunner::Create("test_thread");
67 auto handler = std::make_shared<TestEventHandler>(runner);
68 g_ret += Watchdog::GetInstance().AddThread("DoAddWatchThread", handler);
69 handler.reset();
70 }
71
Sleep(int second)72 static inline void Sleep(int second)
73 {
74 int left = second;
75 while (left > 0) {
76 left = sleep(left);
77 }
78 }
79
80 /**
81 * @tc.name: Watchdog handler checker with default timeout
82 * @tc.desc: Verify default timeout in handler checker interface
83 * @tc.type: FUNC
84 */
85 HWTEST_F(WatchdogInterfaceTest, WatchdogHandlerCheckerTest_001, TestSize.Level1)
86 {
87 /**
88 * @tc.steps: step1. post one task to handler
89 * @tc.expected: step1. post task successfully
90 */
91 constexpr int blockTime = 70;
__anon9420ee760102() 92 auto blockFunc = []() {
93 printf("before block 70s in %d\n", gettid());
94 Sleep(blockTime);
95 printf("after block 70s in %d\n", gettid());
96 };
97 auto runner = EventRunner::Create(true);
98 auto handler = std::make_shared<TestEventHandler>(runner);
99 bool ret = handler->PostTask(blockFunc, "Block70s", 0, EventQueue::Priority::LOW);
100 ASSERT_EQ(ret, true);
101
102 /**
103 * @tc.steps: step2. add handler to watchdog and check the hisysevent result
104 * @tc.expected: step2. add handler to watchdog successfully
105 */
__anon9420ee760202(const std::string &name, int waitState) 106 auto timeOutCallback = [](const std::string &name, int waitState) {
107 printf("TestBlock70s time out in %d, name is %s, waitState is %d\n", gettid(), name.c_str(), waitState);
108 };
109 int result = Watchdog::GetInstance().AddThread("TestBlock70s", handler, timeOutCallback);
110 ASSERT_EQ(result, 0);
111
112 /**
113 * @tc.steps: step3. sleep a while until timeout
114 * @tc.expected: step3. SERVICE_BLOCK event has been created and fired
115 */
116 Sleep(blockTime);
117 }
118
119 /**
120 * @tc.name: Watchdog handler checker with customized timeout
121 * @tc.desc: Verify customized timeout in handler checker interface
122 * @tc.type: FUNC
123 */
124 HWTEST_F(WatchdogInterfaceTest, WatchdogHandlerCheckerTest_002, TestSize.Level1)
125 {
126 /**
127 * @tc.steps: step1. post one task to handler
128 * @tc.expected: step1. post task successfully
129 */
130 constexpr int blockTime = 30;
131 constexpr int checkPeriod = 3000;
__anon9420ee760302() 132 auto blockFunc = []() {
133 printf("before block 30s in %d\n", gettid());
134 Sleep(blockTime);
135 printf("after block 30s in %d\n", gettid());
136 };
137 auto runner = EventRunner::Create(true);
138 auto handler = std::make_shared<TestEventHandler>(runner);
139 bool ret = handler->PostTask(blockFunc, "Block30", 0, EventQueue::Priority::LOW);
140 ASSERT_EQ(ret, true);
141
142 /**
143 * @tc.steps: step2. add handler to watchdog and check the hisysevent result
144 * @tc.expected: step2. add handler to watchdog successfully
145 */
__anon9420ee760402(const std::string &name, int waitState) 146 auto timeOutCallback = [](const std::string &name, int waitState) {
147 printf("TestBlock20 time out in %d, name is %s, waitState is %d\n", gettid(), name.c_str(), waitState);
148 };
149 int result = Watchdog::GetInstance().AddThread("TestBlock20", handler, timeOutCallback, checkPeriod);
150
__anon9420ee760502(const std::string &name, int waitState) 151 auto timeOutCallback1 = [](const std::string &name, int waitState) {
152 printf("TestBlock20_1 time out in %d, name is %s, waitState is %d\n", gettid(), name.c_str(), waitState);
153 };
154 int result2 = Watchdog::GetInstance().AddThread("TestBlock20_1", handler, timeOutCallback1, checkPeriod);
155 ASSERT_EQ(result, 0);
156 ASSERT_EQ(result2, 0);
157
158 /**
159 * @tc.steps: step3. sleep a while until timeout
160 * @tc.expected: step3. SERVICE_BLOCK event has been created and fired
161 */
162 Sleep(blockTime);
163 }
164
165 HWTEST_F(WatchdogInterfaceTest, WatchdogHandlerCheckerTest_003, TestSize.Level1)
166 {
167 constexpr int blockTime = 10;
168 constexpr int maxThread = 5;
169 std::vector<std::thread> threads(maxThread);
170 for (int i = 0; i < maxThread; i++) {
171 threads[i] = std::thread(&WatchdogInterfaceTest::DoAddWatchThread, this);
172 }
173
174 for (auto& th : threads) {
175 th.join();
176 }
177 ASSERT_EQ(g_ret, -4); // -4 : -1 * 4
178 Sleep(blockTime);
179 }
180
181 HWTEST_F(WatchdogInterfaceTest, WatchdogHandlerCheckerTest_004, TestSize.Level1)
182 {
183 constexpr int blockTime = 10;
184 constexpr int checkPeriod = 2000;
185 auto runner = EventRunner::Create("test_thread");
186 auto handler = std::make_shared<TestEventHandler>(runner);
187 int ret = Watchdog::GetInstance().AddThread("BLOCK2S", handler, checkPeriod);
188 ASSERT_EQ(ret, 0);
189
__anon9420ee760602() 190 auto taskFunc = []() { Sleep(blockTime); };
191 Watchdog::GetInstance().RunOneShotTask("block", taskFunc);
192 Sleep(blockTime);
193 }
194
195 /**
196 * @tc.name: Watchdog handler checker without timeout callback
197 * @tc.desc: Check whether SERVICE_BLOCK hisysevent is fired
198 * @tc.type: FUNC
199 */
200 HWTEST_F(WatchdogInterfaceTest, WatchdogHandlerCheckerTest_005, TestSize.Level1)
201 {
202 constexpr int blockTime = 5;
203 constexpr int checkPeriod = 3000;
__anon9420ee760702() 204 auto blockFunc = []() {
205 printf("before block 5s in %d\n", gettid());
206 Sleep(blockTime);
207 printf("after block 5s in %d\n", gettid());
208 };
209 auto runner = EventRunner::Create(true);
210 auto handler = std::make_shared<TestEventHandler>(runner);
211 bool ret = handler->PostTask(blockFunc, "Block10", 0, EventQueue::Priority::LOW);
212 ASSERT_EQ(ret, true);
213
214 int result = Watchdog::GetInstance().AddThread("HiCollieTestBlock10_0", handler, nullptr, checkPeriod);
215 int result2 = Watchdog::GetInstance().AddThread("HiCollieTestBlock10_2", handler, nullptr, checkPeriod);
216 ASSERT_EQ(result, 0);
217 ASSERT_EQ(result2, 0);
218
219 Sleep(blockTime);
220 }
221
222 HWTEST_F(WatchdogInterfaceTest, WatchdogHandlerCheckerTest_006, TestSize.Level1)
223 {
224 printf("WatchdogHandlerCheckerTest_007 begin\n");
225 Watchdog::GetInstance().InitFfrtWatchdog();
226 ffrt::queue* testQueue = new ffrt::queue("test_queue");
__anon9420ee760802null227 auto t = testQueue->submit_h([] {
228 ffrt::mutex lock;
229 lock.lock();
230 lock.unlock();
231 }, {});
232 testQueue->wait(t);
233 delete testQueue;
234 }
235
236 /**
237 * @tc.name: Watchdog thread run a oneshot task
238 * @tc.desc: Verify whether the task has been executed successfully
239 * @tc.type: FUNC
240 */
241 HWTEST_F(WatchdogInterfaceTest, WatchdogRunTaskTest_001, TestSize.Level1)
242 {
243 /**
244 * @tc.steps: step1. create 2 oneshot task and add to watchdog
245 * @tc.expected: step1. task has been executed
246 */
247 constexpr int oneshotTaskTime = 1;
248 constexpr int delayedTaskTime = 3;
249 constexpr int delayedTaskTimeMillisecond = 3000;
250 int task1Result = 0;
__anon9420ee760902() 251 auto task1Func = [&task1Result]() { task1Result = 1; };
252 int task2Result = 0;
__anon9420ee760a02() 253 auto task2Func = [&task2Result]() { task2Result = 1; };
254 Watchdog::GetInstance().RunOneShotTask("task1", task1Func);
255 Watchdog::GetInstance().RunOneShotTask("task2", task2Func);
256 Sleep(oneshotTaskTime);
257 ASSERT_EQ(task1Result, 1);
258 ASSERT_EQ(task2Result, 1);
259
260 /**
261 * @tc.steps: step2. create a delayed oneshot task and add to watchdog
262 * @tc.expected: step2. task has been executed
263 */
264 int delayedTaskResult = 0;
__anon9420ee760b02() 265 auto delayedTaskFunc = [&delayedTaskResult]() { delayedTaskResult = 1; };
266 Watchdog::GetInstance().RunOneShotTask("task3", delayedTaskFunc, delayedTaskTimeMillisecond);
267 ASSERT_EQ(delayedTaskResult, 0);
268 Sleep(oneshotTaskTime + delayedTaskTime);
269 ASSERT_EQ(delayedTaskResult, 1);
270 }
271
272 /**
273 * @tc.name: Watchdog thread run a periodical task
274 * @tc.desc: Verify whether the task has been executed successfully
275 * @tc.type: FUNC
276 */
277 HWTEST_F(WatchdogInterfaceTest, WatchdogRunTaskTest_002, TestSize.Level1)
278 {
279 /**
280 * @tc.steps: step1. create periodical task and add to watchdog
281 * @tc.expected: step1. task has been executed
282 */
283 int taskResult = 0;
__anon9420ee760c02() 284 auto taskFunc = [&taskResult]() { taskResult += 1; };
285 Watchdog::GetInstance().RunPeriodicalTask("periodicalTask", taskFunc, PERIODICAL_TASK_TIME);
286 Sleep(TOTAL_WAIT_TIME);
287 ASSERT_GT(taskResult, EXPECT_RUN_TIMES);
288 }
289
290 /**
291 * @tc.name: Watchdog thread run a periodical task and stop the watchdog
292 * @tc.desc: Verify whether the task has been executed
293 * @tc.type: FUNC
294 */
295 HWTEST_F(WatchdogInterfaceTest, WatchdogStopTest_001, TestSize.Level1)
296 {
297 /**
298 * @tc.steps: step1. create periodical task and add to watchdog
299 * @tc.expected: step1. task has not been executed
300 */
301 int taskResult = 0;
__anon9420ee760d02() 302 auto taskFunc = [&taskResult]() { taskResult += 1; };
303 Watchdog::GetInstance().RunPeriodicalTask("periodicalTask2", taskFunc, PERIODICAL_TASK_TIME);
304 ASSERT_EQ(taskResult, 0);
305 Watchdog::GetInstance().StopWatchdog();
306 Sleep(TOTAL_WAIT_TIME);
307 ASSERT_EQ(taskResult, 0);
308 }
309 } // namespace HiviewDFX
310 } // namespace OHOS
311