• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 <atomic>
17 #include <cerrno>
18 #include <thread>
19 
20 #include <sys/prctl.h>
21 
22 #include "event_handler.h"
23 #include "event_runner.h"
24 
25 #include <gtest/gtest.h>
26 
27 using namespace testing::ext;
28 using namespace OHOS;
29 using namespace OHOS::AppExecFwk;
30 
31 static const uint32_t HAS_EVENT_ID = 100;
32 static const int64_t HAS_EVENT_PARAM = 1000;
33 bool isSetLogger = false;
34 
35 /**
36  * Wait until task is executed.
37  *
38  * @param f task we post.
39  * @param handler handler we use to post task.
40  * @param taskCalled flag to record whether task is executed.
41  */
42 template<typename F>
WaitUntilTaskCalled(F const & f,const std::shared_ptr<EventHandler> & handler,const std::atomic<bool> & taskCalled)43 static void WaitUntilTaskCalled(F const &f, const std::shared_ptr<EventHandler> &handler, const std::atomic<bool> &taskCalled)
44 {
45     const uint32_t maxRetryCount = 1000;
46     const uint32_t sleepTime = 1000;
47     uint32_t count = 0;
48     if (handler->PostTask(f)) {
49         while (!taskCalled.load()) {
50             ++count;
51             // if delay more than 1 second, break
52             if (count >= maxRetryCount) {
53                 break;
54             }
55 
56             usleep(sleepTime);
57         }
58     }
59 }
60 
61 /**
62  * Create runner with name.
63  *
64  * @param handler handler we use to post task.
65  * @param threadName name of thread we set.
66  */
CreateRunnerWithName(const std::shared_ptr<EventHandler> & handler,const std::string & threadName)67 static void CreateRunnerWithName(const std::shared_ptr<EventHandler> &handler, const std::string &threadName)
68 {
69     std::atomic<bool> sameThreadName(false);
70     std::atomic<bool> taskCalled(false);
71     auto f = [&sameThreadName, &taskCalled, &threadName]() {
72         const size_t MAX_THREAD_NAME_SIZE = 16;
73         char thisThreadName[MAX_THREAD_NAME_SIZE + 1];
74 
75         // Get current thread name and compare with the specified one.
76         int32_t ret = prctl(PR_GET_NAME, thisThreadName);
77         if (ret == 0) {
78             thisThreadName[MAX_THREAD_NAME_SIZE] = '\0';
79             sameThreadName.store(threadName == thisThreadName);
80         }
81 
82         taskCalled.store(true);
83     };
84 
85     WaitUntilTaskCalled(f, handler, taskCalled);
86 
87     auto called = taskCalled.load();
88     EXPECT_TRUE(called);
89     auto sameThread = sameThreadName.load();
90     EXPECT_TRUE(sameThread);
91 }
92 
93 class LibEventHandlerEventRunnerTest : public testing::Test {
94 public:
95     static void SetUpTestCase(void);
96     static void TearDownTestCase(void);
97     void SetUp();
98     void TearDown();
99 };
100 
101 class LoggerTest : public Logger {
102 public:
103     /**
104      * Processes the content of a specified string.
105      * @param message the content of a specified string.
106      */
Log(const std::string & line)107     void Log(const std::string &line)
108     {
109         isSetLogger = true;
110         GTEST_LOG_(INFO) << line;
111     };
~LoggerTest()112     virtual ~LoggerTest()
113     {}
114 };
115 
SetUpTestCase(void)116 void LibEventHandlerEventRunnerTest::SetUpTestCase(void)
117 {}
118 
TearDownTestCase(void)119 void LibEventHandlerEventRunnerTest::TearDownTestCase(void)
120 {}
121 
SetUp(void)122 void LibEventHandlerEventRunnerTest::SetUp(void)
123 {}
124 
TearDown(void)125 void LibEventHandlerEventRunnerTest::TearDown(void)
126 {}
127 
128 /*
129  * @tc.name: CreateAndRun001
130  * @tc.desc: create eventrunner and run eventrunner in asynchronous thread
131  * @tc.type: FUNC
132  */
133 HWTEST_F(LibEventHandlerEventRunnerTest, CreateAndRun001, TestSize.Level1)
134 {
135     /**
136      * @tc.setup: init handler and task.
137      */
138     auto handler = std::make_shared<EventHandler>(EventRunner::Create());
139     std::atomic<bool> taskCalled(false);
__anoneef966d50202() 140     auto f = [&taskCalled]() { taskCalled.store(true); };
141 
142     /**
143      * @tc.steps: step1. post task and wait until the task is executed.
144      * @tc.expected: step1. the task has been executed and has not timed out.
145      */
146     WaitUntilTaskCalled(f, handler, taskCalled);
147     auto called = taskCalled.load();
148     EXPECT_TRUE(called);
149 }
150 
151 /*
152  * @tc.name: CreateAndRun002
153  * @tc.desc: create eventrunner and run eventrunner in synchronous thread
154  * @tc.type: FUNC
155  */
156 HWTEST_F(LibEventHandlerEventRunnerTest, CreateAndRun002, TestSize.Level1)
157 {
158     /**
159      * @tc.setup: init handler and runner, runner is not deposit, init task to stop runner.
160      */
161     auto runner = EventRunner::Create(false);
162     auto handler = std::make_shared<EventHandler>(runner);
__anoneef966d50302() 163     auto f = [&runner]() { runner->Stop(); };
164 
165     /**
166      * @tc.steps: step1. post task and run the runner .
167      * @tc.expected: step1. start runner success.
168      */
169     ErrCode result = EVENT_HANDLER_ERR_RUNNER_NO_PERMIT;
170     if (handler->PostTask(f)) {
171         result = runner->Run();
172     }
173 
174     EXPECT_EQ(ERR_OK, result);
175 }
176 
177 /*
178  * @tc.name: CreateAndRun003
179  * @tc.desc: create eventrunner and run eventrunner in asynchronous thread with threadname
180  * @tc.type: FUNC
181  */
182 HWTEST_F(LibEventHandlerEventRunnerTest, CreateAndRun003, TestSize.Level1)
183 {
184     /**
185      * @tc.setup: init handler and init runner with thread name.
186      */
187     std::string threadName("threadName");
188     auto handler = std::make_shared<EventHandler>(EventRunner::Create(threadName));
189 
190     /**
191      * @tc.steps: step1. post task to compare whether the runner thread name is the same as we set.
192      * @tc.expected: step1. runner thread name is the same.
193      */
194     CreateRunnerWithName(handler, threadName);
195 }
196 
197 /*
198  * @tc.name: CreateAndRun004
199  * @tc.desc: create eventrunner and run eventrunner in asynchronous thread with const
200              char* type threadname
201  * @tc.type: FUNC
202  */
203 HWTEST_F(LibEventHandlerEventRunnerTest, CreateAndRun004, TestSize.Level1)
204 {
205     /**
206      * @tc.setup: init handler and init runner with  with const char* type threadname.
207      */
208     auto handler = std::make_shared<EventHandler>(EventRunner::Create("threadName"));
209 
210     /**
211      * @tc.steps: step1. post task to compare whether the runner thread name is the same as we set.
212      * @tc.expected: step1. runner thread name is the same.
213      */
214     CreateRunnerWithName(handler, "threadName");
215 }
216 
217 /*
218  * @tc.name: CreateAndRun005
219  * @tc.desc: execute Run() function from one EventRunner multi times
220  * @tc.type: FUNC
221  */
222 HWTEST_F(LibEventHandlerEventRunnerTest, CreateAndRun005, TestSize.Level1)
223 {
224     /**
225      * @tc.setup: init handler and runner, init a task to stop runner.
226      */
227     const int64_t DELAY_TIME = 30;
228     auto runner = EventRunner::Create(false);
229     auto handler = std::make_shared<EventHandler>(runner);
__anoneef966d50402() 230     auto mainTask = [&runner]() { runner->Stop(); };
231 
232     /**
233      * @tc.steps: step1. post delay task to start runner then new a thread to start the same runner again.
234      * @tc.expected: step1. return runner is already running error.
235      */
__anoneef966d50502() 236     auto f = [&runner]() {
237         usleep(10000);
238         auto runResult = runner->Run();
239         EXPECT_EQ(EVENT_HANDLER_ERR_RUNNER_ALREADY, runResult);
240     };
241     handler->PostTask(mainTask, DELAY_TIME);
242     std::thread newThread(f);
243     newThread.detach();
244     runner->Run();
245 }
246 
247 /*
248  * @tc.name: Stop001
249  * @tc.desc: stop eventrunner in synchronous thread
250  * @tc.type: FUNC
251  */
252 HWTEST_F(LibEventHandlerEventRunnerTest, Stop001, TestSize.Level1)
253 {
254     /**
255      * @tc.setup: init handler and runner, runner is not deposit, init a task to stop runner.
256      */
257     auto runner = EventRunner::Create(false);
258     auto handler = std::make_shared<EventHandler>(runner);
259     ErrCode result = EVENT_HANDLER_ERR_RUNNER_NO_PERMIT;
__anoneef966d50602() 260     auto f = [&result, runner]() { result = runner->Stop(); };
261 
262     /**
263      * @tc.steps: step1. post task and start runner, check whether the runner
264      *            is stopped successfully in synchronous thread.
265      * @tc.expected: step1. runner is stopped successfully.
266      */
267     if (handler->PostTask(f)) {
268         runner->Run();
269     }
270 
271     EXPECT_EQ(ERR_OK, result);
272 }
273 
274 /*
275  * @tc.name: Stop002
276  * @tc.desc: stop eventrunner in asynchronous thread
277  * @tc.type: FUNC
278  */
279 HWTEST_F(LibEventHandlerEventRunnerTest, Stop002, TestSize.Level1)
280 {
281     /**
282      * @tc.setup: init handler and runner, runner is deposit.
283      */
284     auto runner = EventRunner::Create();
285 
286     /**
287      * @tc.steps: step1. call run() and stop() of runner.
288      * @tc.expected: step1. runner do not allow us to start or stop is manually when it is in asynchronous thread.
289      */
290     auto runResult = runner->Run();
291     auto stopResult = runner->Stop();
292     EXPECT_EQ(EVENT_HANDLER_ERR_RUNNER_NO_PERMIT, runResult);
293     EXPECT_EQ(EVENT_HANDLER_ERR_RUNNER_NO_PERMIT, stopResult);
294 }
295 
296 /*
297  * @tc.name: Stop003
298  * @tc.desc: execute Stop() function from one EventRunner multi times
299  * @tc.type: FUNC
300  */
301 HWTEST_F(LibEventHandlerEventRunnerTest, Stop003, TestSize.Level1)
302 {
303     /**
304      * @tc.setup: init handler and runner, runner is not deposit,  init a task to stop runner.
305      */
306     auto runner = EventRunner::Create(false);
307     auto handler = std::make_shared<EventHandler>(runner);
__anoneef966d50702() 308     auto task = [&runner]() { runner->Stop(); };
309 
310     /**
311      * @tc.steps: step1. post the stop stop task then run the runner, then stop runner again.
312      * @tc.expected: step1. stop() could be called multi times.
313      */
314     handler->PostTask(task);
315     runner->Run();
316     usleep(10000);
317     auto stopResult = runner->Stop();
318     EXPECT_EQ(ERR_OK, stopResult);
319 }
320 
321 /*
322  * @tc.name: Current001
323  * @tc.desc: start a runner, use Current() to get the running runner then compare
324  * @tc.type: FUNC
325  */
326 HWTEST_F(LibEventHandlerEventRunnerTest, Current001, TestSize.Level1)
327 {
328     /**
329      * @tc.setup: init handler and runner, runner is not deposit.
330      */
331     auto runner = EventRunner::Create(false);
332     auto handler = std::make_shared<EventHandler>(runner);
333 
334     /**
335      * @tc.steps: step1. post a task to compare the current running runner and the runner the handler binded to.
336      * @tc.expected: step1. the current running runner is the same runner we run the task.
337      */
__anoneef966d50802() 338     auto f = [&runner]() {
339         auto currentRunner = EventRunner::Current();
340         EXPECT_EQ(currentRunner, runner);
341         runner->Stop();
342     };
343     handler->PostTask(f);
344     runner->Run();
345 }
346 
347 /*
348  * @tc.name: SetLogger001
349  * @tc.desc: check SetLogger001 success
350  * @tc.type: FUNC
351  */
352 HWTEST_F(LibEventHandlerEventRunnerTest, SetLogger001, TestSize.Level1)
353 {
354     /**
355      * @tc.setup: init handler and runner
356      */
357     auto runner = EventRunner::Create(true);
358     auto handler = std::make_shared<EventHandler>(runner);
359     auto event = InnerEvent::Get(HAS_EVENT_ID, HAS_EVENT_PARAM);
__anoneef966d50902() 360     auto task = []() {; };
361     /**
362      * @tc.steps: step1. send event
363      * @tc.expected: step1. SetLogger success
364      */
365     std::shared_ptr<LoggerTest> logtest = std::make_shared<LoggerTest>();
366     runner->SetLogger(logtest);
367     handler->SendEvent(event, EventQueue::Priority::LOW);
368     handler->PostTask(task, "task1");
369     handler->PostTask(task);
370     usleep(100 * 1000);
371     EXPECT_TRUE(isSetLogger);
372 }
373