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> 24using namespace testing::ext; 25using namespace std; 26 27namespace OHOS { 28namespace { 29int64_t CurMs() 30{ 31 struct timeval tpend; 32 gettimeofday(&tpend, nullptr); 33 return (tpend.tv_sec * 1000000 + tpend.tv_usec) / 1000; 34} 35 36class UtilsTimerTest : public testing::Test { 37public : 38 static void SetUpTestCase(void); 39 static void TearDownTestCase(void); 40 void SetUp(); 41 void TearDown(); 42}; 43 44void UtilsTimerTest::SetUpTestCase(void) 45{ 46} 47 48void UtilsTimerTest::TearDownTestCase(void) 49{ 50} 51 52void UtilsTimerTest::SetUp(void) 53{ 54} 55 56void UtilsTimerTest::TearDown(void) 57{ 58} 59 60std::atomic<int> g_data1(0); 61void TimeOutCallback1() 62{ 63 g_data1 = g_data1 + 1; 64} 65 66std::atomic<int> g_data2(0); 67void 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 77HWTEST_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 */ 96HWTEST_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 */ 112HWTEST_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 127static 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 */ 142HWTEST_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 152class A { 153public: 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(); 159 int GetData() const 160 { 161 return data_; 162 } 163private: 164 void TimeOutProc() 165 { 166 data_ -= 1; 167 }; 168 int data_; 169 Utils::Timer timer_; 170}; 171 172bool A::Init() 173{ 174 return timer_.Setup() == Utils::TIMER_ERR_OK; 175} 176 177bool 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 183void 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 193HWTEST_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 */ 208HWTEST_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 218static 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 */ 236HWTEST_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 248static 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 */ 265HWTEST_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 */ 282void 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 296void 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 310HWTEST_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 328static 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 */ 341HWTEST_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 */ 358HWTEST_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 */ 375HWTEST_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 */ 391HWTEST_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