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 */
HWTEST_P(SupportedClockIDTest, testClockGetresAll, Function | MediumTest | Level1)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 */
HWTEST_P(SupportedClockIDTest, testClockGettimeAll, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testClockSettime, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testFtime, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testStime, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testTime, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testTimes, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testGettimeofday, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testSettimeofday, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testLocaltime, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testLocaltimer, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testGetdateBasic, Function | MediumTest | Level1)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 */
HWTEST_F(ClockTimeTest, testGetdateError, Function | MediumTest | Level2)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