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