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