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 <gtest/gtest.h>
17 #include "timer.h"
18 #include "common_timer_errors.h"
19 #include <iostream>
20 #include <thread>
21 #include <chrono>
22 #include <stdatomic.h>
23 #include <sys/time.h>
24 using namespace testing::ext;
25 using namespace std;
26 
27 namespace OHOS {
28 namespace {
CurMs()29 int64_t CurMs()
30 {
31     struct timeval tpend;
32     gettimeofday(&tpend, nullptr);
33     return (tpend.tv_sec * 1000000 + tpend.tv_usec) / 1000;
34 }
35 
36 class UtilsTimerTest : public testing::Test {
37 public :
38     static void SetUpTestCase(void);
39     static void TearDownTestCase(void);
40     void SetUp();
41     void TearDown();
42 };
43 
SetUpTestCase(void)44 void UtilsTimerTest::SetUpTestCase(void)
45 {
46 }
47 
TearDownTestCase(void)48 void UtilsTimerTest::TearDownTestCase(void)
49 {
50 }
51 
SetUp(void)52 void UtilsTimerTest::SetUp(void)
53 {
54 }
55 
TearDown(void)56 void UtilsTimerTest::TearDown(void)
57 {
58 }
59 
60 std::atomic<int> g_data1(0);
TimeOutCallback1()61 void TimeOutCallback1()
62 {
63     g_data1 = g_data1 + 1;
64 }
65 
66 std::atomic<int> g_data2(0);
TimeOutCallback2()67 void TimeOutCallback2()
68 {
69     g_data2 = g_data2 + 1;
70 }
71 
72 /*
73  * @tc.name: testTimer001
74  * @tc.desc: timer unit test
75  *
76  * temporarily offline for kernel difference
77 HWTEST_F(UtilsTimerTest, testTimer001, TestSize.Level0)
78 {
79     g_data1 = 0;
80     Utils::Timer timer("test_timer");
81     uint32_t ret = timer.Setup();
82     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
83     uint32_t timerId = timer.Register(TimeOutCallback1, 1);
84     std::this_thread::sleep_for(std::chrono::milliseconds(8));
85     timer.Unregister(timerId);
86     std::this_thread::sleep_for(std::chrono::milliseconds(10));
87     timer.Shutdown();
88     EXPECT_GE(g_data1, 2);
89     EXPECT_GE(10, g_data1);
90 */
91 
92 /*
93  * @tc.name: testTimer002
94  * @tc.desc: timer unit test
95  */
96 HWTEST_F(UtilsTimerTest, testTimer002, TestSize.Level0)
97 {
98     g_data1 = 0;
99     Utils::Timer timer("test_timer");
100     uint32_t ret = timer.Setup();
101     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
102     timer.Register(TimeOutCallback1, 1, true);
103     std::this_thread::sleep_for(std::chrono::milliseconds(15));
104     timer.Shutdown();
105     EXPECT_EQ(1, g_data1);
106 }
107 
108 /*
109  * @tc.name: testTimer003
110  * @tc.desc: timer unit test
111  */
112 HWTEST_F(UtilsTimerTest, testTimer003, TestSize.Level0)
113 {
114     g_data1 = 0;
115     g_data2 = 0;
116     Utils::Timer timer("test_timer");
117     uint32_t ret = timer.Setup();
118     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
119     timer.Register(TimeOutCallback1, 1);
120     timer.Register(TimeOutCallback2, 50);
121     std::this_thread::sleep_for(std::chrono::milliseconds(500));
122     timer.Shutdown();
123     EXPECT_GE(g_data1, 8);
124     EXPECT_GE(g_data2, 2);
125 }
126 
TestTimerEvent(Utils::Timer & timer)127 static void TestTimerEvent(Utils::Timer& timer)
128 {
129     uint32_t interval = 1;
130     timer.Register(TimeOutCallback1, interval);
131     uint32_t interval2 = 2;
132     timer.Register(TimeOutCallback1, interval2);
133     int sleepTime = 30;
134     std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
135     timer.Shutdown();
136 }
137 
138 /*
139  * @tc.name: testTimer004
140  * @tc.desc: timer unit test
141  */
142 HWTEST_F(UtilsTimerTest, testTimer004, TestSize.Level0)
143 {
144     g_data1 = 0;
145     Utils::Timer timer("test_timer");
146     uint32_t ret = timer.Setup();
147     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
148     TestTimerEvent(timer);
149     EXPECT_GE(g_data1, 5);
150 }
151 
152 class A {
153 public:
A(int data)154     explicit A(int data) : data_(data), timer_("ATimer") {}
155     ~A() = default;
156     bool Init();
157     bool StartTimer(int milliseconds, bool once);
158     void StopTimer();
GetData() const159     int GetData() const
160     {
161         return data_;
162     }
163 private:
TimeOutProc()164     void TimeOutProc()
165     {
166         data_ -= 1;
167     };
168     int data_;
169     Utils::Timer timer_;
170 };
171 
Init()172 bool A::Init()
173 {
174     return timer_.Setup() == Utils::TIMER_ERR_OK;
175 }
176 
StartTimer(int milliseconds,bool once)177 bool A::StartTimer(int milliseconds, bool once)
178 {
179     uint32_t timerId = timer_.Register(std::bind(&A::TimeOutProc, this), milliseconds, once);
180     return timerId != Utils::TIMER_ERR_DEAL_FAILED;
181 }
182 
StopTimer()183 void A::StopTimer()
184 {
185     timer_.Shutdown();
186 }
187 
188 /*
189  * @tc.name: testTimer005
190  * @tc.desc: timer unit test
191  *
192  * temporarily offline for kernel difference
193 HWTEST_F(UtilsTimerTest, testTimer005, TestSize.Level0)
194 {
195     A a(10);
196     EXPECT_TRUE(a.Init());
197     EXPECT_TRUE(a.StartTimer(1, false));
198     std::this_thread::sleep_for(std::chrono::milliseconds(10));
199     a.StopTimer();
200     EXPECT_GE(8, a.GetData());
201 }
202 */
203 
204 /*
205  * @tc.name: testTimer006
206  * @tc.desc: timer unit test
207  */
208 HWTEST_F(UtilsTimerTest, testTimer006, TestSize.Level0)
209 {
210     A a(10);
211     EXPECT_TRUE(a.Init());
212     EXPECT_TRUE(a.StartTimer(1, true));
213     std::this_thread::sleep_for(std::chrono::milliseconds(20));
214     a.StopTimer();
215     EXPECT_EQ(9, a.GetData());
216 }
217 
TimerEventFun(Utils::Timer & timer)218 static void TimerEventFun(Utils::Timer& timer)
219 {
220     uint32_t timerId = 0;
221     uint32_t loops = 10;
222     uint32_t interval = 7;
223     int sleepTime = 10;
224     for (uint32_t i = 0; i < loops; i++) {
225         timerId = timer.Register(TimeOutCallback1, interval, true);
226         std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
227     }
228     timer.Unregister(timerId);
229     timer.Unregister(timerId);
230 }
231 
232 /*
233  * @tc.name: testTimer007
234  * @tc.desc: abnormal case
235  */
236 HWTEST_F(UtilsTimerTest, testTimer007, TestSize.Level0)
237 {
238     g_data1 = 0;
239     Utils::Timer timer("test_timer");
240     uint32_t ret = timer.Setup();
241     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
242     TimerEventFun(timer);
243     timer.Shutdown();
244     timer.Shutdown(false);
245     EXPECT_GE(g_data1, 5);
246 }
247 
SleepLoopFunc()248 static void SleepLoopFunc()
249 {
250     int loops = 11;
251     int sleepTime = 10;
252     int64_t desiredVal = 10;
253     for (int i = 0; i < loops; i++) {
254         int64_t pre = CurMs();
255         std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
256         int64_t cur = CurMs();
257         EXPECT_GE(cur - pre, desiredVal);
258     }
259 }
260 
261 /*
262  * @tc.name: testTimer008
263  * @tc.desc: timer sleep test for ivi
264  */
265 HWTEST_F(UtilsTimerTest, testTimer008, TestSize.Level0)
266 {
267     g_data1 = 0;
268     Utils::Timer timer("test_timer");
269     uint32_t ret = timer.Setup();
270     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
271     timer.Register(TimeOutCallback1, 10);
272 
273     SleepLoopFunc();
274     timer.Shutdown();
275     EXPECT_GE(g_data1, 10);
276 }
277 
278 /*
279  * @tc.name: testTimer009
280  * @tc.desc: recursive test
281  */
DoFunc(Utils::Timer & timer,int & count)282 void DoFunc(Utils::Timer &timer, int &count)
283 {
284     (void)timer.Register(
285         [&timer, &count]() {
286             count += 1;
287             if (count > 9) {
288                 return;
289             }
290             DoFunc(timer, count);
291         },
292         10, true);
293     g_data1++;
294 }
295 
DoFunc2(Utils::Timer & timer,int & count)296 void DoFunc2(Utils::Timer &timer, int &count)
297 {
298     (void)timer.Register(
299         [&timer, &count]() {
300             count += 1;
301             if (count > 9) {
302                 return;
303             }
304             DoFunc2(timer, count);
305         },
306         10, true);
307     g_data1++;
308 }
309 
310 HWTEST_F(UtilsTimerTest, testTimer009, TestSize.Level0)
311 {
312     g_data1 = 0;
313     Utils::Timer timer("test_timer");
314     uint32_t ret = timer.Setup();
315     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
316 
317     int cnt = 0, cnt1 = 0;
318     DoFunc(timer, cnt);
319     DoFunc2(timer, cnt1);
320     std::this_thread::sleep_for(std::chrono::milliseconds(50));
321     EXPECT_GE(g_data1, 5);  /* 8 for max */
322     EXPECT_GE(14, g_data1); /* 10 for min */
323     std::this_thread::sleep_for(std::chrono::milliseconds(50));
324     timer.Shutdown();
325     EXPECT_GE(g_data1, 10); /* 18 for max */
326 }
327 
TimerRegisterMechanism(Utils::Timer & timer,bool once)328 static void TimerRegisterMechanism(Utils::Timer& timer, bool once)
329 {
330     uint32_t interval = 10;
331     timer.Register(TimeOutCallback1, interval, once);
332     timer.Register(TimeOutCallback1, interval, !once);
333     timer.Register(TimeOutCallback1, interval, once);
334     timer.Register(TimeOutCallback1, interval, !once);
335 }
336 
337 /*
338  * @tc.name: testTimer010
339  * @tc.desc: once timer register
340  */
341 HWTEST_F(UtilsTimerTest, testTimer010, TestSize.Level0)
342 {
343     g_data1 = 0;
344     Utils::Timer timer("test_timer");
345     uint32_t ret = timer.Setup();
346     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
347     bool once = true;
348     TimerRegisterMechanism(timer, once);
349     std::this_thread::sleep_for(std::chrono::milliseconds(52));
350     timer.Shutdown();
351     EXPECT_GE(g_data1, 8); /* 12 for max */
352 }
353 
354 /*
355  * @tc.name: testTimer011
356  * @tc.desc: once timer register
357  */
358 HWTEST_F(UtilsTimerTest, testTimer011, TestSize.Level0)
359 {
360     g_data1 = 0;
361     Utils::Timer timer("test_timer");
362     uint32_t ret = timer.Setup();
363     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
364     bool once = false;
365     TimerRegisterMechanism(timer, once);
366     std::this_thread::sleep_for(std::chrono::milliseconds(52));
367     timer.Shutdown();
368     EXPECT_GE(g_data1, 8); /* 12 for max */
369 }
370 
371 /*
372  * @tc.name: testTimer012
373  * @tc.desc: Test double setup.
374  */
375 HWTEST_F(UtilsTimerTest, testTimer012, TestSize.Level0)
376 {
377     g_data1 = 0;
378     Utils::Timer timer("test_timer");
379     uint32_t ret = timer.Setup();
380     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
381     ret = timer.Setup();
382     EXPECT_EQ(Utils::TIMER_ERR_INVALID_VALUE, ret);
383 
384     timer.Shutdown();
385 }
386 
387 /*
388  * @tc.name: testTimer013
389  * @tc.desc: Test uncommon operations.
390  */
391 HWTEST_F(UtilsTimerTest, testTimer013, TestSize.Level0)
392 {
393     g_data1 = 0;
394     Utils::Timer timer("test_timer", -1);
395     uint32_t ret = timer.Setup();
396     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
397     std::this_thread::sleep_for(std::chrono::milliseconds(1));
398     timer.Shutdown();
399 
400     Utils::Timer timer1("test_timer_1");
401     ret = timer1.Setup();
402     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
403     std::this_thread::sleep_for(std::chrono::milliseconds(1));
404     timer1.Shutdown(false);
405 }
406 }  // namespace
407 }  // namespace OHOS