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 <time.h> 17 #include <sys/timeb.h> 18 #include <sys/times.h> 19 #include <unistd.h> 20 #include <fcntl.h> 21 #include <errno.h> 22 #include <gtest/gtest.h> 23 #include "log.h" 24 #include "utils.h" 25 #include "ClockID.h" 26 27 using namespace testing::ext; 28 29 const char* DATEMSK_FILE = "/storage/getdate_mask"; 30 31 // Resolution of: CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_MONOTONIC_RAW: 1 us 32 const int CLOCK_RESOLUTION_HIGH = 1000; 33 // Resolution of: CLOCK_MONOTONIC_COARSE, CLOCK_REALTIME_COARSE: 1 tick = 10 ms 34 const int CLOCK_RESOLUTION_LOW = 1000 * 1000; 35 36 class ClockTimeTest : public testing::Test { 37 protected: 38 static struct timespec mTestStatTime; 39 // SetUpTestCase: Testsuit setup, run before 1st testcase SetUpTestCase(void)40 static void SetUpTestCase(void) 41 { 42 clock_gettime(CLOCK_REALTIME, &mTestStatTime); 43 LOG("test start at %ld\n", (long)mTestStatTime.tv_sec); 44 } 45 // TearDownTestCase: Testsuit teardown, run after last testcase TearDownTestCase(void)46 static void TearDownTestCase(void) 47 { 48 struct timespec time1 = {0, 0}; 49 clock_gettime(CLOCK_REALTIME, &time1); 50 LOG("test end at %ld", (long)time1.tv_sec); 51 52 mTestStatTime.tv_sec += 10; // approximate total test time 53 if (!clock_settime(CLOCK_REALTIME, &mTestStatTime)) { 54 LOG("restore time ok\n"); 55 } else { 56 LOG("restore time failed\n"); 57 } 58 } 59 }; 60 struct timespec ClockTimeTest::mTestStatTime; 61 62 /** 63 * @tc.number SUB_KERNEL_TIME_API_CLOCK_GETRES_0100 64 * @tc.name test all supported clockid of clock_getres 65 * @tc.desc [C- SOFTWARE -0200] 66 */ 67 HWTEST_P(SupportedClockIDTest, testClockGetresAll, Function | MediumTest | Level1) 68 { 69 clockid_t cid = GetParam(); 70 const char* cname = ALL_CLOCKS_NAME[cid]; 71 72 struct timespec time1 = {0, 0}; 73 int rt = clock_getres(cid, &time1); 74 LOG("%s Resolution: %ld nanosecond\n", cname, time1.tv_nsec); 75 EXPECT_EQ(rt, 0) << "clock_getres of " << cname << "failed, errno =" <<errno; 76 77 EXPECT_EQ(time1.tv_sec, 0); 78 if (cid == CLOCK_MONOTONIC || cid == CLOCK_REALTIME || cid == CLOCK_MONOTONIC_RAW) { 79 EXPECT_EQ(time1.tv_nsec, CLOCK_RESOLUTION_HIGH) << "Resolution check failed"; 80 } else { 81 EXPECT_EQ(time1.tv_nsec, CLOCK_RESOLUTION_LOW) << "Resolution check failed"; 82 } 83 } 84 85 /** 86 * @tc.number SUB_KERNEL_TIME_API_CLOCK_GETTIME_0100 87 * @tc.name test all supported clockid of clock_gettime 88 * @tc.desc [C- SOFTWARE -0200] 89 */ 90 HWTEST_P(SupportedClockIDTest, testClockGettimeAll, Function | MediumTest | Level1) 91 { 92 clockid_t cid = GetParam(); 93 const char* cname = ALL_CLOCKS_NAME[cid]; 94 95 struct timespec time1 = {0, 0}; 96 int rt = clock_gettime(cid, &time1); 97 if (rt == 0) { 98 LOG("clock_gettime(%s) : tv_sec=%ld, tv_nsec=%ld\n", cname, time1.tv_sec, time1.tv_nsec); 99 } else { 100 LOG("%s return error, rt=%d, errno=%d:%s\n", cname, rt, errno, strerror(errno)); 101 } 102 EXPECT_EQ(rt, 0); 103 } 104 105 INSTANTIATE_TEST_CASE_P(ClockTimeTest, SupportedClockIDTest, ALL_SUPPORTED_IDS); 106 107 108 /** 109 * @tc.number SUB_KERNEL_TIME_API_CLOCK_SETTIME_0100 110 * @tc.name test clock_settime basic 111 * @tc.desc [C- SOFTWARE -0200] 112 */ 113 HWTEST_F(ClockTimeTest, testClockSettime, Function | MediumTest | Level1) 114 { 115 struct timespec time1 = {0, 0}; 116 int rt = clock_gettime(CLOCK_REALTIME, &time1); 117 ASSERT_EQ(rt, 0) << "clock_gettime failed, errno=" << errno; 118 LOG("current time: sec=%llu, nsec=%ld", time1.tv_sec, time1.tv_nsec); 119 time_t sec = time1.tv_sec; 120 time1.tv_sec -= 1; 121 time1.tv_nsec = 1; 122 rt = clock_settime(CLOCK_REALTIME, &time1); 123 ASSERT_EQ(rt, 0) << "clock_settime failed, errno=" << errno; 124 sleep(1); 125 rt = clock_gettime(CLOCK_REALTIME, &time1); 126 ASSERT_EQ(rt, 0) << "clock_gettime failed, errno=" << errno; 127 ASSERT_EQ(sec, time1.tv_sec); 128 } 129 130 /** 131 * @tc.number SUB_KERNEL_TIME_API_FTIME_0100 132 * @tc.name test ftime basic 133 * @tc.desc [C- SOFTWARE -0200] 134 */ 135 HWTEST_F(ClockTimeTest, testFtime, Function | MediumTest | Level1) 136 { 137 Msleep(10); // hopefully to let the flowing code not scheduled-out 138 struct timeb tb = {0}; 139 struct timespec ts = {0}; 140 int rt = clock_gettime(CLOCK_REALTIME, &ts); 141 ASSERT_EQ(rt, 0) << "clock_gettime failed, errno=" << errno; 142 ts.tv_sec -= 1; 143 ts.tv_nsec = 1000000; 144 rt = clock_settime(CLOCK_REALTIME, &ts); 145 ASSERT_EQ(rt, 0) << "clock_settime failed, errno=" << errno; 146 rt = clock_gettime(CLOCK_REALTIME, &ts); 147 int rt2 = ftime(&tb); 148 EXPECT_EQ(rt, 0) << "clock_gettime failed, errno=" << errno; 149 EXPECT_EQ(rt2, 0) << "ftime failed, errno=" << errno; 150 LOG("current time: sec=%llu, nsec=%ld", ts.tv_sec, (long)ts.tv_nsec); 151 LOG("current time: sec=%llu, millitm=%d", tb.time, (int)tb.millitm); 152 EXPECT_EQ(ts.tv_sec, tb.time); 153 EXPECT_NEAR((int)ts.tv_nsec/1000000, (int)tb.millitm, 1); 154 } 155 156 /** 157 * @tc.number SUB_KERNEL_TIME_API_STIME_0100 158 * @tc.name test stime basic 159 * @tc.desc [C- SOFTWARE -0200] 160 */ 161 HWTEST_F(ClockTimeTest, testStime, Function | MediumTest | Level1) 162 { 163 Msleep(10); // hopefully to let the flowing code not scheduled-out 164 struct timespec ts = {0}; 165 int rt = clock_gettime(CLOCK_REALTIME, &ts); 166 LOG("current time: sec=%llu, nsec=%ld", ts.tv_sec, (long)ts.tv_nsec); 167 ASSERT_EQ(rt, 0) << "clock_gettime failed, errno=" << errno; 168 time_t t = ts.tv_sec + 1; 169 rt = stime(&t); 170 ASSERT_EQ(rt, 0) << "stime failed, errno=" << errno; 171 Msleep(10); 172 rt = clock_gettime(CLOCK_REALTIME, &ts); 173 EXPECT_EQ(rt, 0) << "clock_gettime failed, errno=" << errno; 174 LOG("current time: sec=%llu, nsec=%ld", ts.tv_sec, (long)ts.tv_nsec); 175 EXPECT_EQ(ts.tv_sec, t); 176 } 177 178 /** 179 * @tc.number SUB_KERNEL_TIME_API_TIME_0100 180 * @tc.name test time basic 181 * @tc.desc [C- SOFTWARE -0200] 182 */ 183 HWTEST_F(ClockTimeTest, testTime, Function | MediumTest | Level1) 184 { 185 Msleep(10); // hopefully to let the flowing code not scheduled-out 186 struct timespec ts = {0}; 187 int rt = clock_gettime(CLOCK_REALTIME, &ts); 188 ASSERT_EQ(rt, 0) << "clock_gettime failed, errno=" << errno; 189 rt = stime(&ts.tv_sec); // set ts.tv_nsec to 0 190 ASSERT_EQ(rt, 0) << "stime failed, errno=" << errno; 191 192 time_t t1, t2; 193 t1 = time(&t2); 194 EXPECT_EQ(t1, ts.tv_sec) << "time failed"; 195 EXPECT_EQ(t1, t2) << "time failed"; 196 197 t2 = 1; 198 rt = stime(&t2); 199 EXPECT_EQ(rt, 0) << "stime failed, errno=" << errno; 200 201 t1 = time(&t2); 202 EXPECT_EQ(t1, 1); 203 EXPECT_EQ(t1, t2); 204 205 t1 = time(nullptr); 206 EXPECT_EQ(t1, 1); 207 208 rt = stime(&ts.tv_sec); // restore time 209 ASSERT_EQ(rt, 0) << "stime failed, errno=" << errno; 210 } 211 212 /** 213 * @tc.number SUB_KERNEL_TIME_API_TIMES_0100 214 * @tc.name test times basic 215 * @tc.desc [C- SOFTWARE -0200] 216 */ 217 HWTEST_F(ClockTimeTest, testTimes, Function | MediumTest | Level1) 218 { 219 // this test should run in a child process 220 pid_t pid = fork(); 221 ASSERT_TRUE(pid >= 0) << "======== Fork Error! ========="; 222 if (pid == 0) { // child 223 int exitCode = 0; 224 const int testClockt = 100; 225 const int msPerClock = 10; 226 struct tms start = {0}; 227 struct tms end = {0}; 228 clock_t stTime = times(&start); 229 LOG("start_clock: stTime: %ld", stTime); 230 LOG("start_clock: tms_utime: %ld, tms_stime: %ld, tms_cutime:%ld, tms_cstime:%ld", 231 start.tms_utime, start.tms_stime, start.tms_cutime, start.tms_cstime); 232 233 KeepRun(testClockt * msPerClock); 234 235 clock_t endTime = times(&end); 236 LOG("end_clock: endTime: %ld", endTime); 237 LOG("end_clock: tms_utime: %ld, tms_stime: %ld, tms_cutime:%ld, tms_cstime:%ld", 238 end.tms_utime, end.tms_stime, end.tms_cutime, end.tms_cstime); 239 240 LOG("Real Time: %ld, User Time %ld, System Time %ld\n", (long)(endTime - stTime), 241 (long)(end.tms_utime - start.tms_utime), 242 (long)(end.tms_stime - start.tms_stime)); 243 244 if (start.tms_utime != 0 || start.tms_stime != 0 || start.tms_cutime != 0 || start.tms_cstime != 0) { 245 LOG("init value check failed"); 246 } 247 if (!CheckValueClose(end.tms_utime, testClockt, 0.02)) { 248 LOG("tms_utime value check failed"); 249 } 250 if (!CheckValueClose((endTime - stTime), testClockt, 0.02)) { 251 LOG("Real Time value check failed"); 252 } 253 exit(exitCode); 254 } else { // parent 255 WaitProcExitedOK(pid); 256 } 257 } 258 259 /** 260 * @tc.number SUB_KERNEL_TIME_API_GETTIMEOFDAY_0100 261 * @tc.name test gettimeofday api 262 * @tc.desc [C- SOFTWARE -0200] 263 */ 264 HWTEST_F(ClockTimeTest, testGettimeofday, Function | MediumTest | Level1) { 265 int sleepSec = 1; 266 struct timeval tvalStart = {0}; 267 struct timeval tvalEnd = {0}; 268 struct timezone tzone; 269 270 int ret1 = gettimeofday(&tvalStart, &tzone); 271 sleep(sleepSec); 272 int ret2 = gettimeofday(&tvalEnd, &tzone); 273 EXPECT_EQ(0, ret1); 274 EXPECT_EQ(0, ret2); 275 EXPECT_TRUE((tvalEnd.tv_sec - tvalStart.tv_sec) >= sleepSec) 276 << "check end-start>=1 fail, start[" << tvalStart.tv_sec << "],end[" << tvalEnd.tv_sec << "]"; 277 EXPECT_TRUE((tvalEnd.tv_sec - tvalStart.tv_sec) < sleepSec+1) 278 << "check end-start<2 fail, start[" << tvalStart.tv_sec << "],end[" << tvalEnd.tv_sec << "]"; 279 } 280 281 /** 282 * @tc.number SUB_KERNEL_TIME_API_SETTIMEOFDAY_0100 283 * @tc.name test settimeofday api 284 * @tc.desc [C- SOFTWARE -0200] 285 */ 286 HWTEST_F(ClockTimeTest, testSettimeofday, Function | MediumTest | Level1) { 287 int setSec = 100; 288 int sleepSec = 2; 289 struct timeval tvalStart = {0}; 290 struct timeval tvalEnd = {0}; 291 struct timeval set = {.tv_sec = setSec, .tv_usec = 0}; 292 293 int ret1 = settimeofday(&set, NULL); 294 int ret2 = gettimeofday(&tvalStart, NULL); 295 sleep(sleepSec); 296 int ret3 = gettimeofday(&tvalEnd, NULL); 297 EXPECT_EQ(0, ret1); 298 EXPECT_EQ(0, ret2); 299 EXPECT_EQ(0, ret3); 300 EXPECT_EQ(setSec, tvalStart.tv_sec) 301 << "settimeofday set[" << setSec << "],get[" << tvalStart.tv_sec << "]"; 302 EXPECT_TRUE((tvalEnd.tv_sec - tvalStart.tv_sec) >= sleepSec) 303 << "check end-start>=2 fail, start[" << tvalStart.tv_sec << "],end[" << tvalEnd.tv_sec << "]"; 304 EXPECT_TRUE((tvalEnd.tv_sec - tvalStart.tv_sec) < sleepSec+1) 305 << "check end-start<3 fail, start[" << tvalStart.tv_sec << "],end[" << tvalEnd.tv_sec << "]"; 306 } 307 308 /** 309 * @tc.number SUB_KERNEL_TIME_API_LOCALTIME_0100 310 * @tc.name test localtime api 311 * @tc.desc [C- SOFTWARE -0200] 312 */ 313 HWTEST_F(ClockTimeTest, testLocaltime, Function | MediumTest | Level1) { 314 char cTime[32]; 315 time_t tStart; 316 time_t tEnd; 317 struct timeval tSet = {.tv_sec = 86399, .tv_usec = 0}; 318 319 int ret = settimeofday(&tSet, NULL); 320 time(&tStart); 321 sleep(2); 322 time(&tEnd); 323 EXPECT_EQ(0, ret); 324 325 struct tm *tmStart = localtime(&tStart); 326 ASSERT_NE(nullptr, tmStart); 327 strftime(cTime, sizeof(cTime), "%H:%M:%S", tmStart); 328 EXPECT_STREQ("23:59:59", cTime); 329 struct tm *tmEnd = localtime(&tEnd); 330 ASSERT_NE(nullptr, tmEnd); 331 strftime(cTime, sizeof(cTime), "%H:%M:%S", tmEnd); 332 EXPECT_STREQ("00:00:01", cTime); 333 } 334 335 /** 336 * @tc.number SUB_KERNEL_TIME_API_LOCALTIMER_0100 337 * @tc.name test localtime_r api 338 * @tc.desc [C- SOFTWARE -0200] 339 */ 340 HWTEST_F(ClockTimeTest, testLocaltimer, Function | MediumTest | Level1) { 341 char cTime[32]; 342 time_t tStart; 343 time_t tEnd; 344 struct tm tmrStart = {0}; 345 struct tm tmrEnd = {0}; 346 347 struct timeval tSet = {.tv_sec = 86399, .tv_usec = 0}; 348 int ret = settimeofday(&tSet, NULL); 349 time(&tStart); 350 sleep(1); 351 time(&tEnd); 352 struct tm *tmrStartPtr = localtime_r(&tStart, &tmrStart); 353 ASSERT_NE(nullptr, tmrStartPtr); 354 struct tm *tmrEndPtr = localtime_r(&tEnd, &tmrEnd); 355 ASSERT_NE(nullptr, tmrEndPtr); 356 357 EXPECT_EQ(0, ret); 358 strftime(cTime, sizeof(cTime), "%H:%M:%S", &tmrStart); 359 EXPECT_STREQ("23:59:59", cTime); 360 strftime(cTime, sizeof(cTime), "%H:%M:%S", tmrStartPtr); 361 EXPECT_STREQ("23:59:59", cTime); 362 strftime(cTime, sizeof(cTime), "%H:%M:%S", &tmrEnd); 363 EXPECT_STREQ("00:00:00", cTime); 364 strftime(cTime, sizeof(cTime), "%H:%M:%S", tmrEndPtr); 365 EXPECT_STREQ("00:00:00", cTime); 366 strftime(cTime, sizeof(cTime), "%F %T", &tmrStart); 367 LOG(" result[%s]", cTime); 368 } 369 370 /** 371 * @tc.number SUB_KERNEL_TIME_API_GETDATE_0100 372 * @tc.name test getdate api 373 * @tc.desc [C- SOFTWARE -0200] 374 */ 375 HWTEST_F(ClockTimeTest, testGetdateBasic, Function | MediumTest | Level1) { 376 // set DATEMSK env 377 FILE *fp = nullptr; 378 char mask[20] = "%Y-%m-%d %H:%M:%S"; 379 fp = fopen(DATEMSK_FILE, "w+"); 380 ASSERT_NE(nullptr, fp); 381 int ret = fwrite(mask, sizeof(mask), 1, fp); 382 EXPECT_TRUE(ret > 0); 383 ret = setenv("DATEMSK", DATEMSK_FILE, 1); 384 EXPECT_EQ(0, ret); 385 ret = fclose(fp); 386 EXPECT_NE(-1, ret); 387 388 // test getdate 389 char cTime[30]; 390 struct tm *retTm = nullptr; 391 const char *cInput = "2020-10-26 00:01:01"; 392 retTm = getdate(cInput); 393 ASSERT_NE(nullptr, retTm) << " getdate fail errno:" << getdate_err; 394 strftime(cTime, sizeof(cTime), mask, retTm); 395 EXPECT_STREQ(cInput, cTime); 396 strftime(cTime, sizeof(cTime), "%D %A %H:%M:%S", retTm); 397 EXPECT_STREQ("10/26/20 Sunday 00:01:01", cTime); 398 399 // restore 400 ret = remove(DATEMSK_FILE); 401 EXPECT_EQ(0, ret); 402 ret = unsetenv("DATEMSK"); 403 EXPECT_EQ(0, ret); 404 } 405 406 /** 407 * @tc.number SUB_KERNEL_TIME_API_GETDATE_0200 408 * @tc.name getdate error test 409 * @tc.desc [C- SOFTWARE -0200] 410 */ 411 HWTEST_F(ClockTimeTest, testGetdateError, Function | MediumTest | Level2) { 412 // no env 413 struct tm *retTm = nullptr; 414 const char *cInput = "2020-10-26 00:01:01"; 415 retTm = getdate(cInput); 416 EXPECT_EQ(nullptr, retTm); 417 EXPECT_EQ(1, getdate_err); 418 419 // set env, but file not exist 420 int ret = setenv("DATEMSK", DATEMSK_FILE, 1); 421 EXPECT_EQ(0, ret); 422 retTm = getdate(cInput); 423 EXPECT_EQ(nullptr, retTm); 424 EXPECT_EQ(2, getdate_err); 425 426 // creat file and set env 427 FILE *fp = nullptr; 428 char mask[10] = "%H:%M:%S"; 429 fp = fopen(DATEMSK_FILE, "w+"); 430 ASSERT_NE(nullptr, fp); 431 ret = fwrite(mask, sizeof(mask), 1, fp); 432 EXPECT_TRUE(ret > 0); 433 ret = fclose(fp); 434 EXPECT_NE(-1, ret); 435 436 // test getdate 437 retTm = getdate("10/26/20 00:01:01"); 438 EXPECT_EQ(nullptr, retTm); 439 EXPECT_EQ(7, getdate_err); 440 441 // restore 442 ret = remove(DATEMSK_FILE); 443 EXPECT_EQ(0, ret); 444 ret = unsetenv("DATEMSK"); 445 EXPECT_EQ(0, ret); 446 } 447