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;
__anon2a7dc1ed0102() 92 auto blockFunc = []() {
93 printf("before block 70s in %d\n", getproctid());
94 Sleep(blockTime);
95 printf("after block 70s in %d\n", getproctid());
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 */
__anon2a7dc1ed0202(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", getproctid(), 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;
__anon2a7dc1ed0302() 132 auto blockFunc = []() {
133 printf("before block 30s in %d\n", getproctid());
134 Sleep(blockTime);
135 printf("after block 30s in %d\n", getproctid());
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 */
__anon2a7dc1ed0402(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", getproctid(), name.c_str(), waitState);
148 };
149 int result = Watchdog::GetInstance().AddThread("TestBlock20", handler, timeOutCallback, checkPeriod);
150
__anon2a7dc1ed0502(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", getproctid(), 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
__anon2a7dc1ed0602() 190 auto taskFunc = []() { Sleep(blockTime); };
191 Watchdog::GetInstance().RunOneShotTask("block", taskFunc);
192 Sleep(blockTime);
193 }
194
195 /**
196 * @tc.name: Watchdog add thread without timeout callback
197 * @tc.desc: Remove thread, not occurred SERVICE_BLOCK.
198 * @tc.type: FUNC
199 */
200 HWTEST_F(WatchdogInterfaceTest, Watchdog_RemoveTreadTest_001, TestSize.Level1)
201 {
202 constexpr int blockTime = 2;
203 constexpr int checkPeriod = 1000;
__anon2a7dc1ed0702() 204 auto blockFunc = []() {
205 printf("before block 2s in %d\n", getproctid());
206 Sleep(blockTime);
207 printf("after block 2s in %d\n", getproctid());
208 };
209 auto runner = EventRunner::Create(true);
210 auto handler = std::make_shared<TestEventHandler>(runner);
211 bool ret = handler->PostTask(blockFunc, "Block002", 0, EventQueue::Priority::LOW);
212 ASSERT_EQ(ret, true);
213
214 int result = Watchdog::GetInstance().AddThread("RemoveTest001", handler, nullptr, checkPeriod);
215 Watchdog::GetInstance().RemoveThread("RemoveTest001");
216 ASSERT_EQ(result, 0);
217 Sleep(blockTime);
218 result = Watchdog::GetInstance().AddThread("RemoveTest002", handler, nullptr, checkPeriod);
219 ASSERT_EQ(result, 0);
220 result = Watchdog::GetInstance().AddThread("RemoveTest003", handler, nullptr, checkPeriod);
221 ASSERT_EQ(result, 0);
222 Watchdog::GetInstance().RemoveThread("RemoveTest001");
223 }
224
225 /**
226 * @tc.name: Watchdog handler checker without timeout callback
227 * @tc.desc: Check whether SERVICE_BLOCK hisysevent is fired
228 * @tc.type: FUNC
229 */
230 HWTEST_F(WatchdogInterfaceTest, WatchdogHandlerCheckerTest_005, TestSize.Level1)
231 {
232 constexpr int blockTime = 5;
233 constexpr int checkPeriod = 3000;
__anon2a7dc1ed0802() 234 auto blockFunc = []() {
235 printf("before block 5s in %d\n", getproctid());
236 Sleep(blockTime);
237 printf("after block 5s in %d\n", getproctid());
238 };
239 auto runner = EventRunner::Create(true);
240 auto handler = std::make_shared<TestEventHandler>(runner);
241 bool ret = handler->PostTask(blockFunc, "Block10", 0, EventQueue::Priority::LOW);
242 ASSERT_EQ(ret, true);
243
244 int result = Watchdog::GetInstance().AddThread("HiCollieTestBlock10_0", handler, nullptr, checkPeriod);
245 int result2 = Watchdog::GetInstance().AddThread("HiCollieTestBlock10_2", handler, nullptr, checkPeriod);
246 ASSERT_EQ(result, 0);
247 ASSERT_EQ(result2, 0);
248
249 Sleep(blockTime);
250 }
251
252 HWTEST_F(WatchdogInterfaceTest, WatchdogHandlerCheckerTest_006, TestSize.Level1)
253 {
254 printf("WatchdogHandlerCheckerTest_007 begin\n");
255 Watchdog::GetInstance().InitFfrtWatchdog();
256 ffrt::queue* testQueue = new ffrt::queue("test_queue");
__anon2a7dc1ed0902null257 auto t = testQueue->submit_h([] {
258 ffrt::mutex lock;
259 lock.lock();
260 lock.unlock();
261 }, {});
262 testQueue->wait(t);
263 delete testQueue;
264 }
265
266 /**
267 * @tc.name: Watchdog thread run a oneshot task
268 * @tc.desc: Verify whether the task has been executed successfully
269 * @tc.type: FUNC
270 */
271 HWTEST_F(WatchdogInterfaceTest, WatchdogRunTaskTest_001, TestSize.Level1)
272 {
273 /**
274 * @tc.steps: step1. create 2 oneshot task and add to watchdog
275 * @tc.expected: step1. task has been executed
276 */
277 constexpr int oneshotTaskTime = 1;
278 constexpr int delayedTaskTime = 3;
279 constexpr int delayedTaskTimeMillisecond = 3000;
280 int task1Result = 0;
__anon2a7dc1ed0a02() 281 auto task1Func = [&task1Result]() { task1Result = 1; };
282 int task2Result = 0;
__anon2a7dc1ed0b02() 283 auto task2Func = [&task2Result]() { task2Result = 1; };
284 Watchdog::GetInstance().RunOneShotTask("task1", task1Func);
285 Watchdog::GetInstance().RunOneShotTask("task2", task2Func);
286 Sleep(oneshotTaskTime);
287 ASSERT_EQ(task1Result, 1);
288 ASSERT_EQ(task2Result, 1);
289
290 /**
291 * @tc.steps: step2. create a delayed oneshot task and add to watchdog
292 * @tc.expected: step2. task has been executed
293 */
294 int delayedTaskResult = 0;
__anon2a7dc1ed0c02() 295 auto delayedTaskFunc = [&delayedTaskResult]() { delayedTaskResult = 1; };
296 Watchdog::GetInstance().RunOneShotTask("task3", delayedTaskFunc, delayedTaskTimeMillisecond);
297 ASSERT_EQ(delayedTaskResult, 0);
298 Sleep(oneshotTaskTime + delayedTaskTime);
299 ASSERT_EQ(delayedTaskResult, 1);
300 }
301
302 /**
303 * @tc.name: Watchdog thread run a periodical task
304 * @tc.desc: Verify whether the task has been executed successfully
305 * @tc.type: FUNC
306 */
307 HWTEST_F(WatchdogInterfaceTest, WatchdogRunTaskTest_002, TestSize.Level1)
308 {
309 /**
310 * @tc.steps: step1. create periodical task and add to watchdog
311 * @tc.expected: step1. task has been executed
312 */
313 int taskResult = 0;
__anon2a7dc1ed0d02() 314 auto taskFunc = [&taskResult]() { taskResult += 1; };
315 Watchdog::GetInstance().RunPeriodicalTask("periodicalTask", taskFunc, PERIODICAL_TASK_TIME);
316 Sleep(TOTAL_WAIT_TIME);
317 ASSERT_GT(taskResult, EXPECT_RUN_TIMES);
318 }
319
320 /**
321 * @tc.name: Watchdog thread run a periodical task and stop the watchdog
322 * @tc.desc: Verify whether the task has been executed
323 * @tc.type: FUNC
324 */
325 HWTEST_F(WatchdogInterfaceTest, WatchdogStopTest_001, TestSize.Level1)
326 {
327 /**
328 * @tc.steps: step1. create periodical task and add to watchdog
329 * @tc.expected: step1. task has not been executed
330 */
331 int taskResult = 0;
__anon2a7dc1ed0e02() 332 auto taskFunc = [&taskResult]() { taskResult += 1; };
333 Watchdog::GetInstance().RunPeriodicalTask("periodicalTask2", taskFunc, PERIODICAL_TASK_TIME);
334 ASSERT_EQ(taskResult, 0);
335 Watchdog::GetInstance().StopWatchdog();
336 Sleep(TOTAL_WAIT_TIME);
337 }
338
339 /**
340 * @tc.name: Watchdog Set Or Get isAppDebug.
341 * @tc.desc: Verify isAppDebug is true
342 * @tc.type: FUNC
343 */
344 HWTEST_F(WatchdogInterfaceTest, WatchdogAppDebugTest_001, TestSize.Level1)
345 {
346 Watchdog::GetInstance().SetAppDebug(true);
347 ASSERT_TRUE(Watchdog::GetInstance().GetAppDebug());
348 }
349
350 /**
351 * @tc.name: Watchdog add thread without timeout callback
352 * @tc.desc: Occurred SERVICE_BLOCK.
353 * @tc.type: FUNC
354 */
355 HWTEST_F(WatchdogInterfaceTest, Watchdog_AddTreadTest_001, TestSize.Level1)
356 {
357 Watchdog::GetInstance().SetForeground(true);
358 Watchdog::GetInstance().SetBundleInfo("test", "1.1.0");
359 constexpr int blockTime = 2;
360 constexpr int checkPeriod = 1000;
__anon2a7dc1ed0f02() 361 auto blockFunc = []() {
362 printf("before block 2s in %d\n", getproctid());
363 Sleep(blockTime);
364 printf("after block 2s in %d\n", getproctid());
365 };
366 auto runner = EventRunner::Create(true);
367 auto handler = std::make_shared<TestEventHandler>(runner);
368 bool ret = handler->PostTask(blockFunc, "Block001", 0, EventQueue::Priority::LOW);
369 ASSERT_EQ(ret, true);
370
371 int result = Watchdog::GetInstance().AddThread("AddTreadTest_001", handler, nullptr, checkPeriod);
372 ASSERT_EQ(result, 0);
373
374 Sleep(blockTime);
375 }
376 } // namespace HiviewDFX
377 } // namespace OHOS
378