• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 #include "event_loop_test.h"
16 
17 #include <cinttypes>
18 #include <ctime>
19 #include <fstream>
20 #include <iostream>
21 #include <limits>
22 #include <thread>
23 
24 #include <gtest/gtest.h>
25 #include <sys/inotify.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 
30 #include "audit.h"
31 #include "event_loop.h"
32 #include "pipeline.h"
33 
34 using namespace testing::ext;
35 using namespace OHOS::HiviewDFX;
36 namespace OHOS {
37 namespace HiviewDFX {
SetUp()38 void EventLoopTest::SetUp()
39 {
40     /**
41      * @tc.setup: create an event loop and multiple event handlers
42      */
43     if (currentLooper_ != nullptr) {
44         currentLooper_->StopLoop();
45         currentLooper_.reset();
46     }
47 
48     mkdir("/data/log", S_IRWXU | S_IRWXG);
49     const ::testing::TestInfo * const info = ::testing::UnitTest::GetInstance()->current_test_info();
50     printf("We are in test %s of test case %s.\n", info->name(), info->test_case_name());
51     currentLooper_ = std::make_shared<EventLoop>(info->test_case_name());
52     currentLooper_->StartLoop();
53 }
54 
TearDown()55 void EventLoopTest::TearDown()
56 {
57     /**
58      * @tc.teardown: destroy the event loop we have created
59      */
60     if (currentLooper_ != nullptr) {
61         currentLooper_->StopLoop();
62         currentLooper_.reset();
63     }
64 }
65 
OnEvent(std::shared_ptr<Event> & event)66 bool RealEventHandler::OnEvent(std::shared_ptr<Event>& event)
67 {
68     printf("OnEvent id:%d sender:%s pid:%d time:%" PRId64 ". index:%d\n", event->eventId_, event->sender_.c_str(),
69            gettid(), static_cast<int64_t>(time(nullptr)), event->what_);
70     lastProcessId_ = event->eventId_;
71     if ((event->what_ % 10) == 0) { // 10 : add delay in processing some event
72         usleep(100); // 100 : 100us
73     }
74     processedEventCount_++;
75     pid_ = getpid();
76     receivedEventNo_.push_back(event->what_);
77     return true;
78 }
79 
DoTask()80 void RealEventHandler::DoTask()
81 {
82     printf("RealEventHandler::DoTask pid:%d time:%" PRId64 ".\n", gettid(), static_cast<int64_t>(time(nullptr)));
83     processedEventCount_++;
84 }
85 
OnEvent(std::shared_ptr<Event> & event)86 bool OverheadCalculateEventHandler::OnEvent(std::shared_ptr<Event>& event)
87 {
88     auto cost = clock() - event->createTime_;
89     totalDeliverOverHead_ += cost;
90     processedEventCount_++;
91     return true;
92 }
93 
OnFileDescriptorEvent(int fd,int type)94 bool DataFileEventReader::OnFileDescriptorEvent(int fd, int type)
95 {
96     printf("DataFileEventReader::OnEvent id:%d  inotifyFd_:%d\n", fd, inotifyFd_);
97     const int bufSize = 2048;
98     char buffer[bufSize] = {0};
99     char *offset = nullptr;
100     struct inotify_event *event = nullptr;
101     if (inotifyFd_ <= 0) {
102         printf("Invalid inotify fd:%d", inotifyFd_);
103         return false;
104     }
105 
106     int len = read(inotifyFd_, buffer, bufSize);
107     if (len <= 0) {
108         printf("failed to read event");
109         return false;
110     }
111     offset = buffer;
112     event = reinterpret_cast<struct inotify_event *>(buffer);
113     while ((reinterpret_cast<char *>(event) - buffer) < len) {
114         for (const auto &it : fileMap_) {
115             if (it.second != event->wd) {
116                 printf("fail to find check point: %d", event->wd);
117                 continue;
118             }
119 
120             std::string filePath = it.first;
121             printf("handle file event in %s \n", filePath.c_str());
122         }
123 
124         int tmpLen = sizeof(struct inotify_event) + event->len;
125         event = reinterpret_cast<struct inotify_event *>(offset + tmpLen);
126         offset += tmpLen;
127     }
128     return false;
129 }
130 
GetPollFd()131 int32_t DataFileEventReader::GetPollFd()
132 {
133     if (inotifyFd_ > 0) {
134         return inotifyFd_;
135     }
136 
137     inotifyFd_ = inotify_init();
138     if (inotifyFd_ == -1) {
139         printf("failed to init inotify: %s \n", strerror(errno));
140         return -1;
141     }
142 
143     // create file
144     FILE *targetLogFile = fopen(EVENT_LOG_PATH.c_str(), "w+");
145     if (targetLogFile != nullptr) {
146         fclose(targetLogFile);
147     }
148 
149     int wd = inotify_add_watch(inotifyFd_, EVENT_LOG_PATH.c_str(), IN_CLOSE_WRITE | IN_MOVED_TO);
150     if (wd < 0) {
151         printf("failed to add watch entry : %s \n", strerror(errno));
152         close(inotifyFd_);
153         inotifyFd_ = -1;
154         return -1;
155     }
156     fileMap_[EVENT_LOG_PATH] = wd;
157     return inotifyFd_;
158 }
159 
GetPollType()160 int32_t DataFileEventReader::GetPollType()
161 {
162     return EPOLLIN;
163 }
164 
165 /**
166  * @tc.name: EventLoopStartAndStopTest001
167  * @tc.desc: start the event loop and stop the event loop
168  * @tc.type: FUNC
169  * @tc.require: AR000DPTSU
170  */
171 HWTEST_F(EventLoopTest, StartAndStopTest001, TestSize.Level3)
172 {
173     /**
174      * @tc.steps: step1. create event handler
175      */
176     auto eventhandler1 = std::make_shared<RealEventHandler>();
177     auto event1 = std::make_shared<Event>("test1");
178     currentLooper_->AddEvent(eventhandler1, event1, nullptr);
179     /**
180      * @tc.expected: step1. fetch the thread id of the event loop
181      */
182     int curPid = getpid();
183     EXPECT_NE(curPid, eventhandler1->pid_);
184 }
185 
186 /**
187  * @tc.name: EventLoopEventProcessTest001
188  * @tc.desc: send multiple events to event loop
189  * @tc.type: FUNC
190  * @tc.require: AR000DPTSU
191  */
192 HWTEST_F(EventLoopTest, EventLoopEventProcessTest001, TestSize.Level3)
193 {
194     /**
195      * @tc.steps: step1. create event handler and events
196      */
197     auto eventhandler1 = std::make_shared<RealEventHandler>();
198     auto eventhandler2 = std::make_shared<RealEventHandler>();
199     auto eventhandler3 = std::make_shared<RealEventHandler>();
200     auto eventhandler4 = std::make_shared<RealEventHandler>();
201 
202     auto event1 = std::make_shared<Event>("test1");
203     auto event2 = std::make_shared<Event>("test2");
204     auto event3 = std::make_shared<Event>("test3");
205     auto event4 = std::make_shared<Event>("test4");
206     auto event5 = std::make_shared<Event>("test5");
207     auto event6 = std::make_shared<Event>("test6");
208     auto event7 = std::make_shared<Event>("test7");
209 
210     currentLooper_->AddEvent(eventhandler1, event1, nullptr);
211     currentLooper_->AddEvent(eventhandler2, event2, nullptr);
212     currentLooper_->AddEvent(eventhandler3, event3, nullptr);
213     currentLooper_->AddEvent(eventhandler4, event4, nullptr);
214     currentLooper_->AddEvent(eventhandler1, event5, nullptr);
215     currentLooper_->AddEvent(eventhandler4, event6, nullptr);
216     currentLooper_->AddEvent(eventhandler1, event7, nullptr);
217     sleep(2);
218 
219     /**
220      * @tc.expected: step1. the event has been processed
221      */
222     EXPECT_EQ(3, eventhandler1->processedEventCount_);
223     EXPECT_EQ(1, eventhandler2->processedEventCount_);
224     EXPECT_EQ(1, eventhandler3->processedEventCount_);
225     EXPECT_EQ(2, eventhandler4->processedEventCount_);
226 }
227 
228 /**
229  * @tc.name: EventLoopEventProcessTest002
230  * @tc.desc: Add Fd callback and check the result from fd
231  * @tc.type: FUNC
232  * @tc.require: AR000DPTSU
233  */
234 HWTEST_F(EventLoopTest, EventLoopEventProcessTest002, TestSize.Level3)
235 {
236     /**
237      * @tc.steps: step1. create a timer event and send to target
238      */
239     auto eventReader = std::make_shared<DataFileEventReader>();
240     auto res = currentLooper_->AddFileDescriptorEventCallback("test1", eventReader);
241     EXPECT_TRUE(res);
242 
243     auto eventhandler1 = std::make_shared<RealEventHandler>();
244     auto event1 = std::make_shared<Event>("test1");
245     auto event2 = std::make_shared<Event>("test2");
246     auto event3 = std::make_shared<Event>("test3");
247 
248     currentLooper_->AddEvent(eventhandler1, event1, nullptr);
249     currentLooper_->AddEvent(eventhandler1, event2, nullptr);
250     currentLooper_->AddEvent(eventhandler1, event3, nullptr);
251 
252     std::ofstream testFile;
253     testFile.open(DataFileEventReader::EVENT_LOG_PATH);
254     testFile << "Writing this to a file.\n";
255     testFile.close();
256 
257     sleep(1);
258     testFile.open(DataFileEventReader::EVENT_LOG_PATH);
259     testFile << "Writing this to a file.\n";
260     testFile.close();
261     sleep(1);
262     testFile.open(DataFileEventReader::EVENT_LOG_PATH);
263     testFile << "Writing this to a file.\n";
264     testFile.close();
265     sleep(1);
266 
267     /**
268      * @tc.expected: step1. the event has been processed
269      */
270     EXPECT_EQ(3, eventhandler1->processedEventCount_);
271 
272     res = currentLooper_->RemoveFileDescriptorEventCallback("test1");
273     EXPECT_TRUE(res);
274     res = currentLooper_->RemoveFileDescriptorEventCallback("invalid");
275     EXPECT_FALSE(res);
276 
277     currentLooper_->StopLoop();
278     res = currentLooper_->AddFileDescriptorEventCallback("test1", eventReader);
279     EXPECT_FALSE(res);
280 }
281 
282 /**
283  * @tc.name: EventLoopEventProcessTest003
284  * @tc.desc: Exec period event
285  * @tc.type: FUNC
286  * @tc.require: AR000DPTSU
287  */
288 HWTEST_F(EventLoopTest, EventLoopEventProcessTest003, TestSize.Level3)
289 {
290     /**
291      * @tc.steps: step1. create a timer event and send to target
292      */
293     auto eventhandler1 = std::make_shared<RealEventHandler>();
294     auto event1 = std::make_shared<Event>("test1");
295     currentLooper_->AddTimerEvent(eventhandler1, event1, nullptr, 2, true);
296     sleep(9); // 9 = 4(num of event) * 2(delay) + 1(free)
297     /**
298      * @tc.expected: step1. the event has been processed
299      */
300     EXPECT_EQ(4, eventhandler1->processedEventCount_);
301 }
302 
303 /**
304  * @tc.name: EventLoopEventProcessTest004
305  * @tc.desc: Exec period task
306  * @tc.type: FUNC
307  * @tc.require: AR000DPTSU
308  */
309 HWTEST_F(EventLoopTest, EventLoopEventProcessTest004, TestSize.Level3)
310 {
311     /**
312      * @tc.steps: step1. create a timer event and send to target
313      */
314     auto eventhandler1 = std::make_shared<RealEventHandler>();
315     auto task = std::bind(&RealEventHandler::DoTask, eventhandler1.get());
316     currentLooper_->AddTimerEvent(nullptr, nullptr, task, 2, true);
317     printf("On Main Thread:%d \n", gettid());
318     sleep(9);
319     /**
320      * @tc.expected: step1. the event has been processed
321      */
322     EXPECT_EQ(4, eventhandler1->processedEventCount_);
323 }
324 
325 /**
326  * @tc.name: EventLoopEventProcessTest005
327  * @tc.desc: Exec period task and remove it
328  * @tc.type: FUNC
329  * @tc.require: AR000DPTSU
330  */
331 HWTEST_F(EventLoopTest, EventLoopEventProcessTest005, TestSize.Level3)
332 {
333     /**
334      * @tc.steps: step1. create a timer event and send to target
335      */
336     auto eventhandler1 = std::make_shared<RealEventHandler>();
337     auto task = std::bind(&RealEventHandler::DoTask, eventhandler1.get());
338     auto seqId = currentLooper_->AddTimerEvent(nullptr, nullptr, task, 2, true);
339     printf("On Main Thread:%d \n", gettid());
340     sleep(5);
341     currentLooper_->RemoveEvent(seqId);
342     sleep(5);
343     /**
344      * @tc.expected: step1. the event has been processed
345      */
346     EXPECT_EQ(2, eventhandler1->processedEventCount_);
347 }
348 
349 /**
350  * @tc.name: EventLoopEventProcessTest006
351  * @tc.desc: Exec timer event and remove it
352  * @tc.type: FUNC
353  * @tc.require: AR000DPTSU
354  */
355 HWTEST_F(EventLoopTest, EventLoopEventProcessTest006, TestSize.Level3)
356 {
357     /**
358      * @tc.steps: step1. create a timer event and send to target
359      */
360     auto eventhandler1 = std::make_shared<RealEventHandler>();
361     auto event1 = std::make_shared<Event>("test1");
362     currentLooper_->AddTimerEvent(eventhandler1, event1, nullptr, 2, false);
363     sleep(3);
364     EXPECT_EQ(1, eventhandler1->processedEventCount_);
365     auto event2 = std::make_shared<Event>("test2");
366     auto seq = currentLooper_->AddTimerEvent(eventhandler1, event2, nullptr, 2, false);
367     sleep(1);
368     currentLooper_->RemoveEvent(seq);
369     sleep(2);
370     EXPECT_EQ(1, eventhandler1->processedEventCount_);
371 
372     // invalid interval
373     uint64_t interval = std::numeric_limits<uint64_t>::max() - 1;
374     auto event3 = std::make_shared<Event>("test3");
375     auto res = currentLooper_->AddTimerEvent(eventhandler1, event3, nullptr, interval, false);
376     EXPECT_EQ(res, -1);
377 }
378 
379 /**
380  * @tc.name: EventLoopOverheadTest001
381  * @tc.desc: send an event and check the deliver cost
382  * @tc.type: FUNC
383  * @tc.require: AR000DPTSU
384  */
385 HWTEST_F(EventLoopTest, EventLoopOverheadTest001, TestSize.Level3)
386 {
387     /**
388      * @tc.steps: step1. create a handler and event
389      * @tc.steps: step2. calculate event deliver overhead
390      */
391     auto overheadCounter = std::make_shared<OverheadCalculateEventHandler>();
392     const int totalTestCount = 100;
393     for (int i = 0; i < totalTestCount; i++) {
394         auto event = std::make_shared<Event>("test");
395         event->createTime_ = clock();
396         currentLooper_->AddEvent(overheadCounter, event, nullptr);
397     }
398     sleep(10);
399     printf("TotalDeliverOverHeadCost:%" PRIu64 ".\n", overheadCounter->totalDeliverOverHead_);
400     printf("TotalProcessEventCount:%" PRIu64 ".\n", overheadCounter->processedEventCount_);
401     printf("EventTransferOverhead:%" PRIu64 ".\n",
402         overheadCounter->totalDeliverOverHead_/overheadCounter->processedEventCount_);
403 }
404 
405 /**
406  * @tc.name: EventLoopEventOrderTest001
407  * @tc.desc: send 1000 events and check the receiving order
408  * @tc.type: FUNC
409  * @tc.require: AR000DPTSU
410  */
411 HWTEST_F(EventLoopTest, EventLoopEventOrderTest001, TestSize.Level3)
412 {
413     /**
414      * @tc.steps: step1. create a handler and 1000 events in a loop
415      * @tc.steps: step2. check the received order
416      */
417     auto eventhandler = std::make_shared<RealEventHandler>();
418     const uint16_t totalTestCount = 1000;
419     for (uint16_t i = 0; i < totalTestCount; i++) {
420         auto event = std::make_shared<Event>("testevent");
421         event->what_ = i;
422         currentLooper_->AddEvent(eventhandler, event, nullptr);
423     }
424     sleep(10); // 10: sleep 10 seconds
425     ASSERT_EQ(eventhandler->receivedEventNo_.size(), totalTestCount);
426     for (uint16_t i = 0; i < totalTestCount; i++) {
427         ASSERT_EQ(eventhandler->receivedEventNo_[i], i);
428     }
429 }
430 
431 /**
432  * @tc.name: EventLoopWrongInputParamsTest001
433  * @tc.desc: pass invalid params to add event interface
434  * @tc.type: FUNC
435  * @tc.require: AR000DPTSU
436  */
437 HWTEST_F(EventLoopTest, EventLoopWrongInputParamsTest001, TestSize.Level3)
438 {
439     /**
440      * @tc.steps: step1. pass invalid params to add event interface
441      * @tc.steps: step2. check the return future
442      */
443     auto result0 = currentLooper_->AddEventForResult(nullptr, nullptr);
444     ASSERT_EQ(result0.get(), false);
445 
446     auto eventhandler = std::make_shared<RealEventHandler>();
447     auto result1 = currentLooper_->AddEventForResult(eventhandler, nullptr);
448     ASSERT_EQ(result1.get(), false);
449 
450     auto event = std::make_shared<Event>("testevent");
451     auto result2 = currentLooper_->AddEventForResult(eventhandler, event);
452     ASSERT_EQ(result2.get(), true);
453 }
454 
455 /**
456  * @tc.name: EventLoopEventAuditTest001
457  * @tc.desc: Test audit function.
458  * @tc.type: FUNC
459  * @tc.require: issueI642OH
460  */
461 HWTEST_F(EventLoopTest, EventLoopEventAuditTest001, TestSize.Level3)
462 {
463     /**
464      * @tc.steps: step1. open the audit function.
465      * @tc.steps: step2. create pipeline event.
466      * @tc.steps: step3. add event to the handler.
467      */
468     Audit::GetInstance().Init(true);
469     EXPECT_TRUE(Audit::GetInstance().IsEnabled());
470     Event event("test");
471     auto pipelineEvent = std::make_shared<PipelineEvent>(event);
472     EXPECT_TRUE(pipelineEvent->isPipeline_);
473     auto eventhandler = std::make_shared<RealEventHandler>();
474     auto res1 = currentLooper_->AddEvent(eventhandler, pipelineEvent, nullptr);
475     sleep(2);
476     EXPECT_NE(0, res1);
477     EXPECT_EQ(1, eventhandler->processedEventCount_);
478 
479     auto res2 = currentLooper_->AddEventForResult(eventhandler, pipelineEvent);
480     sleep(2);
481     ASSERT_EQ(res2.get(), true);
482     EXPECT_EQ(2, eventhandler->processedEventCount_);
483 
484     res1 = currentLooper_->AddTimerEvent(eventhandler, pipelineEvent, nullptr, 1, false);
485     sleep(3);
486     EXPECT_NE(0, res1);
487     EXPECT_EQ(3, eventhandler->processedEventCount_);
488 
489     currentLooper_->StopLoop();
490     res1 = currentLooper_->AddEvent(eventhandler, pipelineEvent, nullptr);
491     EXPECT_EQ(0, res1);
492     res2 = currentLooper_->AddEventForResult(eventhandler, nullptr);
493     ASSERT_EQ(res2.get(), false);
494     res1 = currentLooper_->AddTimerEvent(eventhandler, pipelineEvent, nullptr, 2, false);
495     sleep(3);
496     EXPECT_EQ(0, res1);
497 
498     const std::string loopName = "restart_loop";
499     currentLooper_ = std::make_shared<EventLoop>(loopName);
500     EXPECT_TRUE(currentLooper_ != nullptr);
501     EXPECT_EQ(currentLooper_->GetName(), loopName);
502     currentLooper_->StartLoop();
503     res1 = currentLooper_->AddEvent(eventhandler, pipelineEvent, nullptr);
504     sleep(2);
505     EXPECT_NE(0, res1);
506     EXPECT_EQ(4, eventhandler->processedEventCount_);
507 
508     EXPECT_NE(currentLooper_->GetName(), loopName); // name: loopName@xxx
509     EXPECT_EQ(currentLooper_->GetRawName(), loopName);
510 }
511 }
512 }
513