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