• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <gtest/gtest.h>
18 #include <thread>
19 
20 #include "db_errno.h"
21 #include "distributeddb_tools_unit_test.h"
22 #include "evloop/include/ievent.h"
23 #include "evloop/include/ievent_loop.h"
24 #include "log_print.h"
25 #include "platform_specific.h"
26 
27 using namespace testing::ext;
28 using namespace DistributedDB;
29 
30 namespace {
31     IEventLoop *g_loop = nullptr;
32     constexpr int MAX_RETRY_TIMES = 1000;
33     constexpr int RETRY_TIMES_5 = 5;
34     constexpr EventTime TIME_INACCURACY = 100LL;
35     constexpr EventTime TIME_PIECE_1 = 1LL;
36     constexpr EventTime TIME_PIECE_10 = 10LL;
37     constexpr EventTime TIME_PIECE_50 = 50LL;
38     constexpr EventTime TIME_PIECE_100 = 100LL;
39     constexpr EventTime TIME_PIECE_1000 = 1000LL;
40     constexpr EventTime TIME_PIECE_10000 = 10000LL;
41 }
42 
43 class TimerTester {
44 public:
45     static EventTime GetCurrentTime();
46 };
47 
GetCurrentTime()48 EventTime TimerTester::GetCurrentTime()
49 {
50     uint64_t now;
51     int errCode = OS::GetCurrentSysTimeInMicrosecond(now);
52     if (errCode != E_OK) {
53         LOGE("Get current time failed.");
54         return 0;
55     }
56     return now / 1000; // 1 ms equals to 1000 us
57 }
58 
59 class DistributedDBEventLoopTimerTest : public testing::Test {
60 public:
61     static void SetUpTestCase(void);
62     static void TearDownTestCase(void);
63     void SetUp();
64     void TearDown();
65 };
66 
SetUpTestCase(void)67 void DistributedDBEventLoopTimerTest::SetUpTestCase(void) {}
68 
TearDownTestCase(void)69 void DistributedDBEventLoopTimerTest::TearDownTestCase(void) {}
70 
SetUp(void)71 void DistributedDBEventLoopTimerTest::SetUp(void)
72 {
73     DistributedDBUnitTest::DistributedDBToolsUnitTest::PrintTestCaseInfo();
74     /**
75      * @tc.setup: Create a loop object.
76      */
77     if (g_loop == nullptr) {
78         int errCode = E_OK;
79         g_loop = IEventLoop::CreateEventLoop(errCode);
80         if (g_loop == nullptr) {
81             LOGE("Prepare loop in SetUp() failed.");
82         }
83     }
84 }
85 
TearDown(void)86 void DistributedDBEventLoopTimerTest::TearDown(void)
87 {
88     /**
89      * @tc.teardown: Destroy the loop object.
90      */
91     if (g_loop != nullptr) {
92         g_loop->KillAndDecObjRef(g_loop);
93         g_loop = nullptr;
94     }
95 }
96 
97 /**
98  * @tc.name: EventLoopTimerTest001
99  * @tc.desc: Create and destroy the event loop object.
100  * @tc.type: FUNC
101  * @tc.require: AR000CKRTB AR000CQE0C
102  * @tc.author: fangyi
103  */
104 HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest001, TestSize.Level0)
105 {
106     /**
107      * @tc.steps: step1. create a loop.
108      * @tc.expected: step1. create successfully.
109      */
110     int errCode = E_OK;
111     IEventLoop *loop = IEventLoop::CreateEventLoop(errCode);
112     ASSERT_EQ(loop != nullptr, true);
113 
114     /**
115      * @tc.steps: step2. destroy the loop.
116      * @tc.expected: step2. destroy successfully.
117      */
118     bool finalized = false;
__anon7e8eee710202() 119     loop->OnLastRef([&finalized]() { finalized = true; });
120     loop->DecObjRef(loop);
121     loop = nullptr;
122     EXPECT_EQ(finalized, true);
123 }
124 
125 /**
126  * @tc.name: EventLoopTimerTest002
127  * @tc.desc: Start and stop the loop
128  * @tc.type: FUNC
129  * @tc.require: AR000CKRTB AR000CQE0C
130  * @tc.author: fangyi
131  */
132 HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest002, TestSize.Level1)
133 {
134     // ready data
135     ASSERT_EQ(g_loop != nullptr, true);
136 
137     /**
138      * @tc.steps: step1. create a loop.
139      * @tc.expected: step1. create successfully.
140      */
141     std::atomic<bool> running(false);
142     EventTime delta = 0;
__anon7e8eee710302() 143     std::thread loopThread([&running, &delta]() {
144             running = true;
145             EventTime start = TimerTester::GetCurrentTime();
146             g_loop->Run();
147             EventTime end = TimerTester::GetCurrentTime();
148             delta = end - start;
149         });
150     while (!running) {
151         std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PIECE_1));
152     }
153     std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PIECE_100));
154     g_loop->KillObj();
155     loopThread.join();
156     EXPECT_EQ(delta > TIME_PIECE_50, true);
157 }
158 
159 /**
160  * @tc.name: EventLoopTimerTest003
161  * @tc.desc: Create and destroy a timer object.
162  * @tc.type: FUNC
163  * @tc.require: AR000CKRTB AR000CQE0C
164  * @tc.author: fangyi
165  */
166 HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest003, TestSize.Level0)
167 {
168      /**
169      * @tc.steps: step1. create event(timer) object.
170      * @tc.expected: step1. create successfully.
171      */
172     int errCode = E_OK;
173     IEvent *timer = IEvent::CreateEvent(TIME_PIECE_1, errCode);
174     ASSERT_EQ(timer != nullptr, true);
175 
176     /**
177      * @tc.steps: step2. destroy the event object.
178      * @tc.expected: step2. destroy successfully.
179      */
180     bool finalized = false;
__anon7e8eee710402(EventsMask revents) 181     errCode = timer->SetAction([](EventsMask revents) -> int {
182             return E_OK;
183         }, [&finalized]() {
184             finalized = true;
185         });
186     EXPECT_EQ(errCode, E_OK);
187     timer->KillAndDecObjRef(timer);
188     timer = nullptr;
189     EXPECT_EQ(finalized, true);
190 }
191 
192 /**
193  * @tc.name: EventLoopTimerTest004
194  * @tc.desc: Start a timer
195  * @tc.type: FUNC
196  * @tc.require: AR000CKRTB AR000CQE0C
197  * @tc.author: fangyi
198  */
199 HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest004, TestSize.Level1)
200 {
201     // ready data
202     ASSERT_EQ(g_loop != nullptr, true);
203 
204     /**
205      * @tc.steps: step1. start the loop.
206      * @tc.expected: step1. start successfully.
207      */
208     std::atomic<bool> running(false);
__anon7e8eee710602() 209     std::thread loopThread([&running]() {
210             running = true;
211             g_loop->Run();
212         });
213 
214     int tryCounter = 0;
215     while (!running && ++tryCounter < MAX_RETRY_TIMES) {
216         std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PIECE_1));
217     }
218     EXPECT_EQ(running, true);
219 
220     /**
221      * @tc.steps: step2. create and start a timer.
222      * @tc.expected: step2. start successfully.
223      */
224     int errCode = E_OK;
225     IEvent *timer = IEvent::CreateEvent(TIME_PIECE_10, errCode);
226     ASSERT_EQ(timer != nullptr, true);
227     std::atomic<int> counter(0);
__anon7e8eee710702(EventsMask revents) 228     errCode = timer->SetAction([&counter](EventsMask revents) -> int { ++counter; return E_OK; }, nullptr);
229     EXPECT_EQ(errCode, E_OK);
230     errCode = g_loop->Add(timer);
231     EXPECT_EQ(errCode, E_OK);
232 
233     /**
234      * @tc.steps: step3. wait and check.
235      * @tc.expected: step3. 'counter' increased by the timer.
236      */
237     std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PIECE_100));
238     EXPECT_EQ(counter > 0, true);
239     g_loop->KillObj();
240     loopThread.join();
241     timer->DecObjRef(timer);
242 }
243 
244 /**
245  * @tc.name: EventLoopTimerTest005
246  * @tc.desc: Stop a timer
247  * @tc.type: FUNC
248  * @tc.require: AR000CKRTB AR000CQE0C
249  * @tc.author: fangyi
250  */
251 HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest005, TestSize.Level1)
252 {
253     // ready data
254     ASSERT_EQ(g_loop != nullptr, true);
255 
256     /**
257      * @tc.steps: step1. start the loop.
258      * @tc.expected: step1. start successfully.
259      */
260     std::atomic<bool> running(false);
__anon7e8eee710802() 261     std::thread loopThread([&running]() {
262             running = true;
263             g_loop->Run();
264         });
265 
266     int tryCounter = 0;
267     while (!running && ++tryCounter <= MAX_RETRY_TIMES) {
268         std::this_thread::sleep_for(std::chrono::milliseconds(1));
269     }
270     EXPECT_EQ(running, true);
271 
272     /**
273      * @tc.steps: step2. create and start a timer.
274      * @tc.expected: step2. start successfully.
275      */
276     int errCode = E_OK;
277     IEvent *timer = IEvent::CreateEvent(10, errCode);
278     ASSERT_EQ(timer != nullptr, true);
279     std::atomic<int> counter(0);
280     std::atomic<bool> finalize(false);
281     errCode = timer->SetAction(
__anon7e8eee710902(EventsMask revents) 282         [&counter](EventsMask revents) -> int {
283             ++counter;
284             return E_OK;
285         }, [&finalize]() { finalize = true; });
286     EXPECT_EQ(errCode, E_OK);
287     errCode = g_loop->Add(timer);
288     EXPECT_EQ(errCode, E_OK);
289 
290     /**
291      * @tc.steps: step3. wait and check.
292      * @tc.expected: step3. 'counter' increased by the timer and the timer object finalized.
293      */
294     std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PIECE_100));
295     timer->KillAndDecObjRef(timer);
296     timer = nullptr;
297     g_loop->KillObj();
298     loopThread.join();
299     EXPECT_EQ(counter > 0, true);
300     EXPECT_EQ(finalize, true);
301 }
302 
303 /**
304  * @tc.name: EventLoopTimerTest006
305  * @tc.desc: Stop a timer
306  * @tc.type: FUNC
307  * @tc.require: AR000CKRTB AR000CQE0C
308  * @tc.author: fangyi
309  */
310 HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest006, TestSize.Level1)
311 {
312     // ready data
313     ASSERT_EQ(g_loop != nullptr, true);
314 
315     /**
316      * @tc.steps: step1. start the loop.
317      * @tc.expected: step1. start successfully.
318      */
319     std::atomic<bool> running(false);
__anon7e8eee710b02() 320     std::thread loopThread([&running]() {
321             running = true;
322             g_loop->Run();
323         });
324 
325     int tryCounter = 0;
326     while (!running && ++tryCounter <= MAX_RETRY_TIMES) {
327         std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PIECE_10));
328     }
329     EXPECT_EQ(running, true);
330 
331     /**
332      * @tc.steps: step2. create and start a timer.
333      * @tc.expected: step2. start successfully.
334      */
335     int errCode = E_OK;
336     IEvent *timer = IEvent::CreateEvent(TIME_PIECE_10, errCode);
337     ASSERT_EQ(timer != nullptr, true);
338     std::atomic<int> counter(0);
339     std::atomic<bool> finalize(false);
__anon7e8eee710c02(EventsMask revents) 340     errCode = timer->SetAction([&counter](EventsMask revents) -> int { ++counter; return -E_STALE; },
__anon7e8eee710d02() 341         [&finalize]() { finalize = true; });
342     EXPECT_EQ(errCode, E_OK);
343     errCode = g_loop->Add(timer);
344     EXPECT_EQ(errCode, E_OK);
345 
346     /**
347      * @tc.steps: step3. wait and check.
348      * @tc.expected: step3. 'counter' increased by the timer and the timer object finalized.
349      */
350     std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PIECE_100));
351     g_loop->KillObj();
352     loopThread.join();
353     timer->DecObjRef(timer);
354     timer = nullptr;
355     EXPECT_EQ(finalize, true);
356     EXPECT_EQ(counter > 0, true);
357 }
358 
359 /**
360  * @tc.name: EventLoopTimerTest007
361  * @tc.desc: Modify a timer
362  * @tc.type: FUNC
363  * @tc.require: AR000CKRTB AR000CQE0C
364  * @tc.author: fangyi
365  */
366 HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest007, TestSize.Level2)
367 {
368     // ready data
369     ASSERT_EQ(g_loop != nullptr, true);
370 
371     /**
372      * @tc.steps: step1. start the loop.
373      * @tc.expected: step1. start successfully.
374      */
375     std::atomic<bool> running(false);
__anon7e8eee710e02() 376     std::thread loopThread([&running]() {
377             running = true;
378             g_loop->Run();
379         });
380 
381     int tryCounter = 0;
382     while (!running && ++tryCounter <= MAX_RETRY_TIMES) {
383         std::this_thread::sleep_for(std::chrono::milliseconds(1));
384     }
385     EXPECT_EQ(running, true);
386 
387     /**
388      * @tc.steps: step2. create and start a timer.
389      * @tc.expected: step2. start successfully.
390      */
391     int errCode = E_OK;
392     IEvent *timer = IEvent::CreateEvent(TIME_PIECE_1000, errCode);
393     ASSERT_EQ(timer != nullptr, true);
394     int counter = 1; // Interval: 1 * TIME_PIECE_100
395     EventTime lastTime = TimerTester::GetCurrentTime();
396     errCode = timer->SetAction(
__anon7e8eee710f02(EventsMask revents) 397         [timer, &counter, &lastTime](EventsMask revents) -> int {
398             EventTime now = TimerTester::GetCurrentTime();
399             EventTime delta = now - lastTime;
400             delta -= counter * TIME_PIECE_1000;
401             EXPECT_EQ(delta >= -TIME_INACCURACY && delta <= TIME_INACCURACY, true);
402             if (++counter > RETRY_TIMES_5) {
403                 return -E_STALE;
404             }
405             lastTime = TimerTester::GetCurrentTime();
406             int ret = timer->SetTimeout(counter * TIME_PIECE_1000);
407             EXPECT_EQ(ret, E_OK);
408             return E_OK;
409         }, nullptr);
410     EXPECT_EQ(errCode, E_OK);
411     errCode = g_loop->Add(timer);
412     EXPECT_EQ(errCode, E_OK);
413 
414     std::this_thread::sleep_for(std::chrono::milliseconds(TIME_PIECE_10000));
415     g_loop->KillObj();
416     loopThread.join();
417     timer->DecObjRef(timer);
418 }
419