xref: /llvm-project/libc/test/src/time/mktime_test.cpp (revision a72499e47537c02a33d7c1c2e512d0b4a0ecbb89)
1 //===-- Unittests for mktime ----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "src/time/mktime.h"
10 #include "src/time/time_utils.h"
11 #include "test/ErrnoSetterMatcher.h"
12 #include "test/src/time/TmHelper.h"
13 #include "test/src/time/TmMatcher.h"
14 #include "utils/UnitTest/Test.h"
15 
16 #include <errno.h>
17 #include <limits.h>
18 #include <string.h>
19 
20 using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
21 using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
22 using __llvm_libc::time_utils::TimeConstants;
23 
24 static inline time_t call_mktime(struct tm *tm_data, int year, int month,
25                                  int mday, int hour, int min, int sec, int wday,
26                                  int yday) {
27   __llvm_libc::tmhelper::testing::InitializeTmData(tm_data, year, month, mday,
28                                                    hour, min, sec, wday, yday);
29   return __llvm_libc::mktime(tm_data);
30 }
31 
32 TEST(LlvmLibcMkTime, FailureSetsErrno) {
33   struct tm tm_data;
34   __llvm_libc::tmhelper::testing::InitializeTmData(
35       &tm_data, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, -1, 0, 0);
36   EXPECT_THAT(__llvm_libc::mktime(&tm_data), Fails(EOVERFLOW));
37 }
38 
39 TEST(LlvmLibcMkTime, InvalidSeconds) {
40   struct tm tm_data;
41   // -1 second from 1970-01-01 00:00:00 returns 1969-12-31 23:59:59.
42   EXPECT_THAT(call_mktime(&tm_data,
43                           1970, // year
44                           1,    // month
45                           1,    // day
46                           0,    // hr
47                           0,    // min
48                           -1,   // sec
49                           0,    // wday
50                           0),   // yday
51               Succeeds(-1));
52   EXPECT_TM_EQ((tm{59,     // sec
53                    59,     // min
54                    23,     // hr
55                    31,     // day
56                    12 - 1, // tm_mon starts with 0 for Jan
57                    1969 - TimeConstants::TimeYearBase, // year
58                    3,                                  // wday
59                    364,                                // yday
60                    0}),
61                tm_data);
62   // 60 seconds from 1970-01-01 00:00:00 returns 1970-01-01 00:01:00.
63   EXPECT_THAT(call_mktime(&tm_data,
64                           1970, // year
65                           1,    // month
66                           1,    // day
67                           0,    // hr
68                           0,    // min
69                           60,   // sec
70                           0,    // wday
71                           0),   // yday
72               Succeeds(60));
73   EXPECT_TM_EQ((tm{0, // sec
74                    1, // min
75                    0, // hr
76                    1, // day
77                    0, // tm_mon starts with 0 for Jan
78                    1970 - TimeConstants::TimeYearBase, // year
79                    4,                                  // wday
80                    0,                                  // yday
81                    0}),
82                tm_data);
83 }
84 
85 TEST(LlvmLibcMkTime, InvalidMinutes) {
86   struct tm tm_data;
87   // -1 minute from 1970-01-01 00:00:00 returns 1969-12-31 23:59:00.
88   EXPECT_THAT(call_mktime(&tm_data,
89                           1970, // year
90                           1,    // month
91                           1,    // day
92                           0,    // hr
93                           -1,   // min
94                           0,    // sec
95                           0,    // wday
96                           0),   // yday
97               Succeeds(-TimeConstants::SecondsPerMin));
98   EXPECT_TM_EQ((tm{0,  // sec
99                    59, // min
100                    23, // hr
101                    31, // day
102                    11, // tm_mon starts with 0 for Jan
103                    1969 - TimeConstants::TimeYearBase, // year
104                    3,                                  // wday
105                    0,                                  // yday
106                    0}),
107                tm_data);
108   // 60 minutes from 1970-01-01 00:00:00 returns 1970-01-01 01:00:00.
109   EXPECT_THAT(call_mktime(&tm_data,
110                           1970, // year
111                           1,    // month
112                           1,    // day
113                           0,    // hr
114                           60,   // min
115                           0,    // sec
116                           0,    // wday
117                           0),   // yday
118               Succeeds(60 * TimeConstants::SecondsPerMin));
119   EXPECT_TM_EQ((tm{0, // sec
120                    0, // min
121                    1, // hr
122                    1, // day
123                    0, // tm_mon starts with 0 for Jan
124                    1970 - TimeConstants::TimeYearBase, // year
125                    4,                                  // wday
126                    0,                                  // yday
127                    0}),
128                tm_data);
129 }
130 
131 TEST(LlvmLibcMkTime, InvalidHours) {
132   struct tm tm_data;
133   // -1 hour from 1970-01-01 00:00:00 returns 1969-12-31 23:00:00.
134   EXPECT_THAT(call_mktime(&tm_data,
135                           1970, // year
136                           1,    // month
137                           1,    // day
138                           -1,   // hr
139                           0,    // min
140                           0,    // sec
141                           0,    // wday
142                           0),   // yday
143               Succeeds(-TimeConstants::SecondsPerHour));
144   EXPECT_TM_EQ((tm{0,  // sec
145                    0,  // min
146                    23, // hr
147                    31, // day
148                    11, // tm_mon starts with 0 for Jan
149                    1969 - TimeConstants::TimeYearBase, // year
150                    3,                                  // wday
151                    0,                                  // yday
152                    0}),
153                tm_data);
154   // 24 hours from 1970-01-01 00:00:00 returns 1970-01-02 00:00:00.
155   EXPECT_THAT(call_mktime(&tm_data,
156                           1970, // year
157                           1,    // month
158                           1,    // day
159                           24,   // hr
160                           0,    // min
161                           0,    // sec
162                           0,    // wday
163                           0),   // yday
164               Succeeds(24 * TimeConstants::SecondsPerHour));
165   EXPECT_TM_EQ((tm{0, // sec
166                    0, // min
167                    0, // hr
168                    2, // day
169                    0, // tm_mon starts with 0 for Jan
170                    1970 - TimeConstants::TimeYearBase, // year
171                    5,                                  // wday
172                    0,                                  // yday
173                    0}),
174                tm_data);
175 }
176 
177 TEST(LlvmLibcMkTime, InvalidYear) {
178   struct tm tm_data;
179   // -1 year from 1970-01-01 00:00:00 returns 1969-01-01 00:00:00.
180   EXPECT_THAT(call_mktime(&tm_data,
181                           1969, // year
182                           1,    // month
183                           1,    // day
184                           0,    // hr
185                           0,    // min
186                           0,    // sec
187                           0,    // wday
188                           0),   // yday
189               Succeeds(-TimeConstants::DaysPerNonLeapYear *
190                        TimeConstants::SecondsPerDay));
191   EXPECT_TM_EQ((tm{0, // sec
192                    0, // min
193                    0, // hr
194                    1, // day
195                    0, // tm_mon starts with 0 for Jan
196                    1969 - TimeConstants::TimeYearBase, // year
197                    3,                                  // wday
198                    0,                                  // yday
199                    0}),
200                tm_data);
201 }
202 
203 TEST(LlvmLibcMkTime, InvalidEndOf32BitEpochYear) {
204   if (sizeof(size_t) != 4)
205     return;
206   struct tm tm_data;
207   // 2038-01-19 03:14:08 tests overflow of the second in 2038.
208   EXPECT_THAT(call_mktime(&tm_data, 2038, 1, 19, 3, 14, 8, 0, 0),
209               Succeeds(TimeConstants::OutOfRangeReturnValue));
210   // 2038-01-19 03:15:07 tests overflow of the minute in 2038.
211   EXPECT_THAT(call_mktime(&tm_data, 2038, 1, 19, 3, 15, 7, 0, 0),
212               Succeeds(TimeConstants::OutOfRangeReturnValue));
213   // 2038-01-19 04:14:07 tests overflow of the hour in 2038.
214   EXPECT_THAT(call_mktime(&tm_data, 2038, 1, 19, 4, 14, 7, 0, 0),
215               Succeeds(TimeConstants::OutOfRangeReturnValue));
216   // 2038-01-20 03:14:07 tests overflow of the day in 2038.
217   EXPECT_THAT(call_mktime(&tm_data, 2038, 1, 20, 3, 14, 7, 0, 0),
218               Succeeds(TimeConstants::OutOfRangeReturnValue));
219   // 2038-02-19 03:14:07 tests overflow of the month in 2038.
220   EXPECT_THAT(call_mktime(&tm_data, 2038, 2, 19, 3, 14, 7, 0, 0),
221               Succeeds(TimeConstants::OutOfRangeReturnValue));
222   // 2039-01-19 03:14:07 tests overflow of the year.
223   EXPECT_THAT(call_mktime(&tm_data, 2039, 1, 19, 3, 14, 7, 0, 0),
224               Succeeds(TimeConstants::OutOfRangeReturnValue));
225 }
226 
227 TEST(LlvmLibcMkTime, InvalidMonths) {
228   struct tm tm_data;
229   // -1 month from 1970-01-01 00:00:00 returns 1969-12-01 00:00:00.
230   EXPECT_THAT(call_mktime(&tm_data,
231                           1970, // year
232                           0,    // month
233                           1,    // day
234                           0,    // hr
235                           0,    // min
236                           0,    // sec
237                           0,    // wday
238                           0),   // yday
239               Succeeds(-31 * TimeConstants::SecondsPerDay));
240   EXPECT_TM_EQ((tm{0,      // sec
241                    0,      // min
242                    0,      // hr
243                    1,      // day
244                    12 - 1, // tm_mon starts with 0 for Jan
245                    1969 - TimeConstants::TimeYearBase, // year
246                    1,                                  // wday
247                    0,                                  // yday
248                    0}),
249                tm_data);
250   // 1970-13-01 00:00:00 returns 1971-01-01 00:00:00.
251   EXPECT_THAT(call_mktime(&tm_data,
252                           1970, // year
253                           13,   // month
254                           1,    // day
255                           0,    // hr
256                           0,    // min
257                           0,    // sec
258                           0,    // wday
259                           0),   // yday
260               Succeeds(TimeConstants::DaysPerNonLeapYear *
261                        TimeConstants::SecondsPerDay));
262   EXPECT_TM_EQ((tm{0, // sec
263                    0, // min
264                    0, // hr
265                    1, // day
266                    0, // tm_mon starts with 0 for Jan
267                    1971 - TimeConstants::TimeYearBase, // year
268                    5,                                  // wday
269                    0,                                  // yday
270                    0}),
271                tm_data);
272 }
273 
274 TEST(LlvmLibcMkTime, InvalidDays) {
275   struct tm tm_data;
276   // -1 day from 1970-01-01 00:00:00 returns 1969-12-31 00:00:00.
277   EXPECT_THAT(call_mktime(&tm_data,
278                           1970, // year
279                           1,    // month
280                           0,    // day
281                           0,    // hr
282                           0,    // min
283                           0,    // sec
284                           0,    // wday
285                           0),   // yday
286               Succeeds(-1 * TimeConstants::SecondsPerDay));
287   EXPECT_TM_EQ((tm{0,  // sec
288                    0,  // min
289                    0,  // hr
290                    31, // day
291                    11, // tm_mon starts with 0 for Jan
292                    1969 - TimeConstants::TimeYearBase, // year
293                    3,                                  // wday
294                    0,                                  // yday
295                    0}),
296                tm_data);
297 
298   // 1970-01-32 00:00:00 returns 1970-02-01 00:00:00.
299   EXPECT_THAT(call_mktime(&tm_data,
300                           1970, // year
301                           1,    // month
302                           32,   // day
303                           0,    // hr
304                           0,    // min
305                           0,    // sec
306                           0,    // wday
307                           0),   // yday
308               Succeeds(31 * TimeConstants::SecondsPerDay));
309   EXPECT_TM_EQ((tm{0, // sec
310                    0, // min
311                    0, // hr
312                    1, // day
313                    0, // tm_mon starts with 0 for Jan
314                    1970 - TimeConstants::TimeYearBase, // year
315                    0,                                  // wday
316                    0,                                  // yday
317                    0}),
318                tm_data);
319 
320   // 1970-02-29 00:00:00 returns 1970-03-01 00:00:00.
321   EXPECT_THAT(call_mktime(&tm_data,
322                           1970, // year
323                           2,    // month
324                           29,   // day
325                           0,    // hr
326                           0,    // min
327                           0,    // sec
328                           0,    // wday
329                           0),   // yday
330               Succeeds(59 * TimeConstants::SecondsPerDay));
331   EXPECT_TM_EQ((tm{0, // sec
332                    0, // min
333                    0, // hr
334                    1, // day
335                    2, // tm_mon starts with 0 for Jan
336                    1970 - TimeConstants::TimeYearBase, // year
337                    0,                                  // wday
338                    0,                                  // yday
339                    0}),
340                tm_data);
341 
342   // 1972-02-30 00:00:00 returns 1972-03-01 00:00:00.
343   EXPECT_THAT(call_mktime(&tm_data,
344                           1972, // year
345                           2,    // month
346                           30,   // day
347                           0,    // hr
348                           0,    // min
349                           0,    // sec
350                           0,    // wday
351                           0),   // yday
352               Succeeds(((2 * TimeConstants::DaysPerNonLeapYear) + 60) *
353                        TimeConstants::SecondsPerDay));
354   EXPECT_TM_EQ((tm{0, // sec
355                    0, // min
356                    0, // hr
357                    1, // day
358                    2, // tm_mon starts with 0 for Jan
359                    1972 - TimeConstants::TimeYearBase, // year
360                    3,                                  // wday
361                    0,                                  // yday
362                    0}),
363                tm_data);
364 }
365 
366 TEST(LlvmLibcMkTime, EndOf32BitEpochYear) {
367   struct tm tm_data;
368   // Test for maximum value of a signed 32-bit integer.
369   // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
370   EXPECT_THAT(call_mktime(&tm_data,
371                           2038, // year
372                           1,    // month
373                           19,   // day
374                           3,    // hr
375                           14,   // min
376                           7,    // sec
377                           0,    // wday
378                           0),   // yday
379               Succeeds(0x7FFFFFFF));
380   EXPECT_TM_EQ((tm{7,  // sec
381                    14, // min
382                    3,  // hr
383                    19, // day
384                    0,  // tm_mon starts with 0 for Jan
385                    2038 - TimeConstants::TimeYearBase, // year
386                    2,                                  // wday
387                    7,                                  // yday
388                    0}),
389                tm_data);
390 }
391 
392 TEST(LlvmLibcMkTime, Max64BitYear) {
393   if (sizeof(time_t) == 4)
394     return;
395   // Mon Jan 1 12:50:50 2170 (200 years from 1970),
396   struct tm tm_data;
397   EXPECT_THAT(call_mktime(&tm_data,
398                           2170, // year
399                           1,    // month
400                           1,    // day
401                           12,   // hr
402                           50,   // min
403                           50,   // sec
404                           0,    // wday
405                           0),   // yday
406               Succeeds(6311479850));
407   EXPECT_TM_EQ((tm{50, // sec
408                    50, // min
409                    12, // hr
410                    1,  // day
411                    0,  // tm_mon starts with 0 for Jan
412                    2170 - TimeConstants::TimeYearBase, // year
413                    1,                                  // wday
414                    50,                                 // yday
415                    0}),
416                tm_data);
417 
418   // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
419   EXPECT_THAT(call_mktime(&tm_data, 2147483647, 1, 1, 12, 50, 50, 0, 0),
420               Succeeds(67767976202043050));
421   EXPECT_TM_EQ((tm{50, // sec
422                    50, // min
423                    12, // hr
424                    1,  // day
425                    0,  // tm_mon starts with 0 for Jan
426                    2147483647 - TimeConstants::TimeYearBase, // year
427                    2,                                        // wday
428                    50,                                       // yday
429                    0}),
430                tm_data);
431 }
432