[flang] Accept polymorphic component element in storage_size
[llvm-project.git] / libc / test / src / time / mktime_test.cpp
blob231696d45fcb8538c723e7fe017b935d8ffe8d1e
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 //===----------------------------------------------------------------------===//
9 #include "src/time/mktime.h"
10 #include "src/time/time_utils.h"
11 #include "test/ErrnoSetterMatcher.h"
12 #include "test/UnitTest/Test.h"
13 #include "test/src/time/TmHelper.h"
14 #include "test/src/time/TmMatcher.h"
16 #include <errno.h>
17 #include <limits.h>
19 using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
20 using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
21 using __llvm_libc::time_utils::Month;
23 static inline constexpr int tm_year(int year) {
24 return year - TimeConstants::TIME_YEAR_BASE;
27 TEST(LlvmLibcMkTime, FailureSetsErrno) {
28 struct tm tm_data {
29 .tm_sec = INT_MAX, .tm_min = INT_MAX, .tm_hour = INT_MAX,
30 .tm_mday = INT_MAX, .tm_mon = INT_MAX - 1, .tm_year = tm_year(INT_MAX),
31 .tm_wday = 0, .tm_yday = 0
33 EXPECT_THAT(__llvm_libc::mktime(&tm_data), Fails(EOVERFLOW));
36 TEST(LlvmLibcMkTime, InvalidSeconds) {
38 // -1 second from 1970-01-01 00:00:00 returns 1969-12-31 23:59:59.
39 struct tm tm_data {
40 .tm_sec = -1, .tm_min = 0, .tm_hour = 0, .tm_mday = 1,
41 .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0,
42 .tm_yday = 0
44 EXPECT_THAT(__llvm_libc::mktime(&tm_data), Succeeds(-1));
45 EXPECT_TM_EQ((tm{.tm_sec = 59,
46 .tm_min = 59,
47 .tm_hour = 23,
48 .tm_mday = 31,
49 .tm_mon = Month::DECEMBER,
50 .tm_year = tm_year(1969),
51 .tm_wday = 3,
52 .tm_yday = 364}),
53 tm_data);
57 // 60 seconds from 1970-01-01 00:00:00 returns 1970-01-01 00:01:00.
58 struct tm tm_data {
59 .tm_sec = 60, .tm_min = 0, .tm_hour = 0, .tm_mday = 1,
60 .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0,
61 .tm_yday = 0
63 EXPECT_THAT(__llvm_libc::mktime(&tm_data), Succeeds(60));
64 EXPECT_TM_EQ((tm{.tm_sec = 0,
65 .tm_min = 1,
66 .tm_hour = 0,
67 .tm_mday = 1,
68 .tm_mon = Month::JANUARY,
69 .tm_year = tm_year(1970),
70 .tm_wday = 4,
71 .tm_yday = 0}),
72 tm_data);
76 TEST(LlvmLibcMkTime, InvalidMinutes) {
78 // -1 minute from 1970-01-01 00:00:00 returns 1969-12-31 23:59:00.
79 struct tm tm_data {
80 .tm_sec = 0, .tm_min = -1, .tm_hour = 0, .tm_mday = 1,
81 .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0,
82 .tm_yday = 0
84 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
85 Succeeds(-TimeConstants::SECONDS_PER_MIN));
86 EXPECT_TM_EQ((tm{.tm_sec = 0,
87 .tm_min = 59,
88 .tm_hour = 23,
89 .tm_mday = 31,
90 .tm_mon = Month::DECEMBER,
91 .tm_year = tm_year(1969),
92 .tm_wday = 3,
93 .tm_yday = 0}),
94 tm_data);
98 // 60 minutes from 1970-01-01 00:00:00 returns 1970-01-01 01:00:00.
99 struct tm tm_data {
100 .tm_sec = 0, .tm_min = 60, .tm_hour = 0, .tm_mday = 1,
101 .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0,
102 .tm_yday = 0
104 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
105 Succeeds(60 * TimeConstants::SECONDS_PER_MIN));
106 EXPECT_TM_EQ((tm{.tm_sec = 0,
107 .tm_min = 0,
108 .tm_hour = 1,
109 .tm_mday = 1,
110 .tm_mon = Month::JANUARY,
111 .tm_year = tm_year(1970),
112 .tm_wday = 4,
113 .tm_yday = 0}),
114 tm_data);
118 TEST(LlvmLibcMkTime, InvalidHours) {
120 // -1 hour from 1970-01-01 00:00:00 returns 1969-12-31 23:00:00.
121 struct tm tm_data {
122 .tm_sec = 0, .tm_min = 0, .tm_hour = -1, .tm_mday = 1,
123 .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0,
124 .tm_yday = 0
126 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
127 Succeeds(-TimeConstants::SECONDS_PER_HOUR));
128 EXPECT_TM_EQ((tm{.tm_sec = 0,
129 .tm_min = 0,
130 .tm_hour = 23,
131 .tm_mday = 31,
132 .tm_mon = Month::DECEMBER,
133 .tm_year = tm_year(1969),
134 .tm_wday = 3,
135 .tm_yday = 0}),
136 tm_data);
140 // 24 hours from 1970-01-01 00:00:00 returns 1970-01-02 00:00:00.
141 struct tm tm_data {
142 .tm_sec = 0, .tm_min = 0, .tm_hour = 24, .tm_mday = 1,
143 .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0,
144 .tm_yday = 0
146 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
147 Succeeds(24 * TimeConstants::SECONDS_PER_HOUR));
148 EXPECT_TM_EQ((tm{.tm_sec = 0,
149 .tm_min = 0,
150 .tm_hour = 0,
151 .tm_mday = 2,
152 .tm_mon = Month::JANUARY,
153 .tm_year = tm_year(1970),
154 .tm_wday = 5,
155 .tm_yday = 0}),
156 tm_data);
160 TEST(LlvmLibcMkTime, InvalidYear) {
161 // -1 year from 1970-01-01 00:00:00 returns 1969-01-01 00:00:00.
162 struct tm tm_data {
163 .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1,
164 .tm_mon = Month::JANUARY, .tm_year = tm_year(1969), .tm_wday = 0,
165 .tm_yday = 0
167 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
168 Succeeds(-TimeConstants::DAYS_PER_NON_LEAP_YEAR *
169 TimeConstants::SECONDS_PER_DAY));
170 EXPECT_TM_EQ((tm{.tm_sec = 0,
171 .tm_min = 0,
172 .tm_hour = 0,
173 .tm_mday = 1,
174 .tm_mon = Month::JANUARY,
175 .tm_year = tm_year(1969),
176 .tm_wday = 3,
177 .tm_yday = 0}),
178 tm_data);
181 TEST(LlvmLibcMkTime, InvalidEndOf32BitEpochYear) {
182 if (sizeof(size_t) != 4)
183 return;
185 // 2038-01-19 03:14:08 tests overflow of the second in 2038.
186 struct tm tm_data {
187 .tm_sec = 8, .tm_min = 14, .tm_hour = 3, .tm_mday = 19,
188 .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0,
189 .tm_yday = 0
191 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
192 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
196 // 2038-01-19 03:15:07 tests overflow of the minute in 2038.
197 struct tm tm_data {
198 .tm_sec = 7, .tm_min = 15, .tm_hour = 3, .tm_mday = 19,
199 .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0,
200 .tm_yday = 0
202 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
203 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
207 // 2038-01-19 04:14:07 tests overflow of the hour in 2038.
208 struct tm tm_data {
209 .tm_sec = 7, .tm_min = 14, .tm_hour = 4, .tm_mday = 19,
210 .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0,
211 .tm_yday = 0
213 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
214 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
218 // 2038-01-20 03:14:07 tests overflow of the day in 2038.
219 struct tm tm_data {
220 .tm_sec = 7, .tm_min = 14, .tm_hour = 3, .tm_mday = 20,
221 .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0,
222 .tm_yday = 0
224 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
225 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
229 // 2038-02-19 03:14:07 tests overflow of the month in 2038.
230 struct tm tm_data {
231 .tm_sec = 7, .tm_min = 14, .tm_hour = 3, .tm_mday = 19,
232 .tm_mon = Month::FEBRUARY, .tm_year = tm_year(2038), .tm_wday = 0,
233 .tm_yday = 0
235 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
236 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
240 // 2039-01-19 03:14:07 tests overflow of the year.
241 struct tm tm_data {
242 .tm_sec = 7, .tm_min = 14, .tm_hour = 3, .tm_mday = 19,
243 .tm_mon = Month::JANUARY, .tm_year = tm_year(2039), .tm_wday = 0,
244 .tm_yday = 0
246 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
247 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
251 TEST(LlvmLibcMkTime, InvalidMonths) {
253 // -1 month from 1970-01-01 00:00:00 returns 1969-12-01 00:00:00.
254 struct tm tm_data {
255 .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 0, .tm_mon = -1,
256 .tm_year = tm_year(1970), .tm_wday = 0, .tm_yday = 0
258 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
259 Succeeds(-32 * TimeConstants::SECONDS_PER_DAY));
260 EXPECT_TM_EQ((tm{.tm_sec = 0,
261 .tm_min = 0,
262 .tm_hour = 0,
263 .tm_mday = 1,
264 .tm_mon = Month::DECEMBER,
265 .tm_year = tm_year(1969),
266 .tm_wday = 1,
267 .tm_yday = 0}),
268 tm_data);
272 // 1970-13-01 00:00:00 returns 1971-01-01 00:00:00.
273 struct tm tm_data {
274 .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 12,
275 .tm_year = tm_year(1970), .tm_wday = 0, .tm_yday = 0
277 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
278 Succeeds(TimeConstants::DAYS_PER_NON_LEAP_YEAR *
279 TimeConstants::SECONDS_PER_DAY));
280 EXPECT_TM_EQ((tm{.tm_sec = 0,
281 .tm_min = 0,
282 .tm_hour = 0,
283 .tm_mday = 1,
284 .tm_mon = Month::JANUARY,
285 .tm_year = tm_year(1971),
286 .tm_wday = 5,
287 .tm_yday = 0}),
288 tm_data);
292 TEST(LlvmLibcMkTime, InvalidDays) {
294 // -1 day from 1970-01-01 00:00:00 returns 1969-12-31 00:00:00.
295 struct tm tm_data {
296 .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = (1 - 1),
297 .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0,
298 .tm_yday = 0
300 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
301 Succeeds(-1 * TimeConstants::SECONDS_PER_DAY));
302 EXPECT_TM_EQ((tm{.tm_sec = 0,
303 .tm_min = 0,
304 .tm_hour = 0,
305 .tm_mday = 31,
306 .tm_mon = Month::DECEMBER,
307 .tm_year = tm_year(1969),
308 .tm_wday = 3,
309 .tm_yday = 0}),
310 tm_data);
314 // 1970-01-32 00:00:00 returns 1970-02-01 00:00:00.
315 struct tm tm_data {
316 .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 32,
317 .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0,
318 .tm_yday = 0
320 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
321 Succeeds(31 * TimeConstants::SECONDS_PER_DAY));
322 EXPECT_TM_EQ((tm{.tm_sec = 0,
323 .tm_min = 0,
324 .tm_hour = 0,
325 .tm_mday = 1,
326 .tm_mon = Month::FEBRUARY,
327 .tm_year = tm_year(1970),
328 .tm_wday = 0,
329 .tm_yday = 0}),
330 tm_data);
334 // 1970-02-29 00:00:00 returns 1970-03-01 00:00:00.
335 struct tm tm_data {
336 .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 29,
337 .tm_mon = Month::FEBRUARY, .tm_year = tm_year(1970), .tm_wday = 0,
338 .tm_yday = 0
340 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
341 Succeeds(59 * TimeConstants::SECONDS_PER_DAY));
342 EXPECT_TM_EQ((tm{.tm_sec = 0,
343 .tm_min = 0,
344 .tm_hour = 0,
345 .tm_mday = 1,
346 .tm_mon = Month::MARCH,
347 .tm_year = tm_year(1970),
348 .tm_wday = 0,
349 .tm_yday = 0}),
350 tm_data);
354 // 1972-02-30 00:00:00 returns 1972-03-01 00:00:00.
355 struct tm tm_data {
356 .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 30,
357 .tm_mon = Month::FEBRUARY, .tm_year = tm_year(1972), .tm_wday = 0,
358 .tm_yday = 0
360 EXPECT_THAT(__llvm_libc::mktime(&tm_data),
361 Succeeds(((2 * TimeConstants::DAYS_PER_NON_LEAP_YEAR) + 60) *
362 TimeConstants::SECONDS_PER_DAY));
363 EXPECT_TM_EQ((tm{.tm_sec = 0,
364 .tm_min = 0,
365 .tm_hour = 0,
366 .tm_mday = 1,
367 .tm_mon = Month::MARCH,
368 .tm_year = tm_year(1972),
369 .tm_wday = 3,
370 .tm_yday = 0}),
371 tm_data);
375 TEST(LlvmLibcMkTime, EndOf32BitEpochYear) {
376 // Test for maximum value of a signed 32-bit integer.
377 // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
378 struct tm tm_data {
379 .tm_sec = 7, .tm_min = 14, .tm_hour = 3, .tm_mday = 19,
380 .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0,
381 .tm_yday = 0
383 EXPECT_THAT(__llvm_libc::mktime(&tm_data), Succeeds(0x7FFFFFFF));
384 EXPECT_TM_EQ((tm{.tm_sec = 7,
385 .tm_min = 14,
386 .tm_hour = 3,
387 .tm_mday = 19,
388 .tm_mon = Month::JANUARY,
389 .tm_year = tm_year(2038),
390 .tm_wday = 2,
391 .tm_yday = 7}),
392 tm_data);
395 TEST(LlvmLibcMkTime, Max64BitYear) {
396 if (sizeof(time_t) == 4)
397 return;
399 // Mon Jan 1 12:50:50 2170 (200 years from 1970),
400 struct tm tm_data {
401 .tm_sec = 50, .tm_min = 50, .tm_hour = 12, .tm_mday = 1,
402 .tm_mon = Month::JANUARY, .tm_year = tm_year(2170), .tm_wday = 0,
403 .tm_yday = 0
405 EXPECT_THAT(__llvm_libc::mktime(&tm_data), Succeeds(6311479850));
406 EXPECT_TM_EQ((tm{.tm_sec = 50,
407 .tm_min = 50,
408 .tm_hour = 12,
409 .tm_mday = 1,
410 .tm_mon = Month::JANUARY,
411 .tm_year = tm_year(2170),
412 .tm_wday = 1,
413 .tm_yday = 50}),
414 tm_data);
418 // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
419 struct tm tm_data {
420 .tm_sec = 50, .tm_min = 50, .tm_hour = 12, .tm_mday = 1,
421 .tm_mon = Month::JANUARY, .tm_year = tm_year(2147483647), .tm_wday = 0,
422 .tm_yday = 0
424 EXPECT_THAT(__llvm_libc::mktime(&tm_data), Succeeds(67767976202043050));
425 EXPECT_TM_EQ((tm{.tm_sec = 50,
426 .tm_min = 50,
427 .tm_hour = 12,
428 .tm_mday = 1,
429 .tm_mon = Month::JANUARY,
430 .tm_year = tm_year(2147483647),
431 .tm_wday = 2,
432 .tm_yday = 50}),
433 tm_data);