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