• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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