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();