1 //===-- Unittests for gmtime ----------------------------------------------===//
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/gmtime.h"
10 #include "src/time/time_utils.h"
11 #include "test/ErrnoSetterMatcher.h"
12 #include "test/src/time/TmMatcher.h"
13 #include "utils/UnitTest/Test.h"
14 
15 #include <errno.h>
16 #include <limits.h>
17 #include <string.h>
18 
19 using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
20 using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
21 using __llvm_libc::time_utils::TimeConstants;
22 
TEST(LlvmLibcGmTime,OutOfRange)23 TEST(LlvmLibcGmTime, OutOfRange) {
24   time_t seconds = 1 + INT_MAX * static_cast<int64_t>(
25                                      TimeConstants::NumberOfSecondsInLeapYear);
26   struct tm *tm_data = __llvm_libc::gmtime(&seconds);
27   EXPECT_TRUE(tm_data == nullptr);
28   EXPECT_EQ(llvmlibc_errno, EOVERFLOW);
29 
30   llvmlibc_errno = 0;
31   seconds =
32       INT_MIN * static_cast<int64_t>(TimeConstants::NumberOfSecondsInLeapYear) -
33       1;
34   tm_data = __llvm_libc::gmtime(&seconds);
35   EXPECT_TRUE(tm_data == nullptr);
36   EXPECT_EQ(llvmlibc_errno, EOVERFLOW);
37 }
38 
TEST(LlvmLibcGmTime,InvalidSeconds)39 TEST(LlvmLibcGmTime, InvalidSeconds) {
40   time_t seconds = 0;
41   struct tm *tm_data = nullptr;
42   // -1 second from 1970-01-01 00:00:00 returns 1969-12-31 23:59:59.
43   seconds = -1;
44   tm_data = __llvm_libc::gmtime(&seconds);
45   EXPECT_TM_EQ((tm{59,     // sec
46                    59,     // min
47                    23,     // hr
48                    31,     // day
49                    12 - 1, // tm_mon starts with 0 for Jan
50                    1969 - TimeConstants::TimeYearBase, // year
51                    3,                                  // wday
52                    364,                                // yday
53                    0}),
54                *tm_data);
55   // 60 seconds from 1970-01-01 00:00:00 returns 1970-01-01 00:01:00.
56   seconds = 60;
57   tm_data = __llvm_libc::gmtime(&seconds);
58   EXPECT_TM_EQ((tm{0, // sec
59                    1, // min
60                    0, // hr
61                    1, // day
62                    0, // tm_mon starts with 0 for Jan
63                    1970 - TimeConstants::TimeYearBase, // year
64                    4,                                  // wday
65                    0,                                  // yday
66                    0}),
67                *tm_data);
68 }
69 
TEST(LlvmLibcGmTime,InvalidMinutes)70 TEST(LlvmLibcGmTime, InvalidMinutes) {
71   time_t seconds = 0;
72   struct tm *tm_data = nullptr;
73   // -1 minute from 1970-01-01 00:00:00 returns 1969-12-31 23:59:00.
74   seconds = -TimeConstants::SecondsPerMin;
75   tm_data = __llvm_libc::gmtime(&seconds);
76   EXPECT_TM_EQ((tm{0,  // sec
77                    59, // min
78                    23, // hr
79                    31, // day
80                    11, // tm_mon starts with 0 for Jan
81                    1969 - TimeConstants::TimeYearBase, // year
82                    3,                                  // wday
83                    0,                                  // yday
84                    0}),
85                *tm_data);
86   // 60 minutes from 1970-01-01 00:00:00 returns 1970-01-01 01:00:00.
87   seconds = 60 * TimeConstants::SecondsPerMin;
88   tm_data = __llvm_libc::gmtime(&seconds);
89   EXPECT_TM_EQ((tm{0, // sec
90                    0, // min
91                    1, // hr
92                    1, // day
93                    0, // tm_mon starts with 0 for Jan
94                    1970 - TimeConstants::TimeYearBase, // year
95                    4,                                  // wday
96                    0,                                  // yday
97                    0}),
98                *tm_data);
99 }
100 
TEST(LlvmLibcGmTime,InvalidHours)101 TEST(LlvmLibcGmTime, InvalidHours) {
102   time_t seconds = 0;
103   struct tm *tm_data = nullptr;
104   // -1 hour from 1970-01-01 00:00:00 returns 1969-12-31 23:00:00.
105   seconds = -TimeConstants::SecondsPerHour;
106   tm_data = __llvm_libc::gmtime(&seconds);
107   EXPECT_TM_EQ((tm{0,  // sec
108                    0,  // min
109                    23, // hr
110                    31, // day
111                    11, // tm_mon starts with 0 for Jan
112                    1969 - TimeConstants::TimeYearBase, // year
113                    3,                                  // wday
114                    0,                                  // yday
115                    0}),
116                *tm_data);
117   // 24 hours from 1970-01-01 00:00:00 returns 1970-01-02 00:00:00.
118   seconds = 24 * TimeConstants::SecondsPerHour;
119   tm_data = __llvm_libc::gmtime(&seconds);
120   EXPECT_TM_EQ((tm{0, // sec
121                    0, // min
122                    0, // hr
123                    2, // day
124                    0, // tm_mon starts with 0 for Jan
125                    1970 - TimeConstants::TimeYearBase, // year
126                    5,                                  // wday
127                    0,                                  // yday
128                    0}),
129                *tm_data);
130 }
131 
TEST(LlvmLibcGmTime,InvalidYear)132 TEST(LlvmLibcGmTime, InvalidYear) {
133   // -1 year from 1970-01-01 00:00:00 returns 1969-01-01 00:00:00.
134   time_t seconds =
135       -TimeConstants::DaysPerNonLeapYear * TimeConstants::SecondsPerDay;
136   struct tm *tm_data = __llvm_libc::gmtime(&seconds);
137   EXPECT_TM_EQ((tm{0, // sec
138                    0, // min
139                    0, // hr
140                    1, // day
141                    0, // tm_mon starts with 0 for Jan
142                    1969 - TimeConstants::TimeYearBase, // year
143                    3,                                  // wday
144                    0,                                  // yday
145                    0}),
146                *tm_data);
147 }
148 
TEST(LlvmLibcGmTime,InvalidMonths)149 TEST(LlvmLibcGmTime, InvalidMonths) {
150   time_t seconds = 0;
151   struct tm *tm_data = nullptr;
152   // -1 month from 1970-01-01 00:00:00 returns 1969-12-01 00:00:00.
153   seconds = -31 * TimeConstants::SecondsPerDay;
154   tm_data = __llvm_libc::gmtime(&seconds);
155   EXPECT_TM_EQ((tm{0,      // sec
156                    0,      // min
157                    0,      // hr
158                    1,      // day
159                    12 - 1, // tm_mon starts with 0 for Jan
160                    1969 - TimeConstants::TimeYearBase, // year
161                    1,                                  // wday
162                    0,                                  // yday
163                    0}),
164                *tm_data);
165   // 1970-13-01 00:00:00 returns 1971-01-01 00:00:00.
166   seconds = TimeConstants::DaysPerNonLeapYear * TimeConstants::SecondsPerDay;
167   tm_data = __llvm_libc::gmtime(&seconds);
168   EXPECT_TM_EQ((tm{0, // sec
169                    0, // min
170                    0, // hr
171                    1, // day
172                    0, // tm_mon starts with 0 for Jan
173                    1971 - TimeConstants::TimeYearBase, // year
174                    5,                                  // wday
175                    0,                                  // yday
176                    0}),
177                *tm_data);
178 }
179 
TEST(LlvmLibcGmTime,InvalidDays)180 TEST(LlvmLibcGmTime, InvalidDays) {
181   time_t seconds = 0;
182   struct tm *tm_data = nullptr;
183   // -1 day from 1970-01-01 00:00:00 returns 1969-12-31 00:00:00.
184   seconds = -1 * TimeConstants::SecondsPerDay;
185   tm_data = __llvm_libc::gmtime(&seconds);
186   EXPECT_TM_EQ((tm{0,  // sec
187                    0,  // min
188                    0,  // hr
189                    31, // day
190                    11, // tm_mon starts with 0 for Jan
191                    1969 - TimeConstants::TimeYearBase, // year
192                    3,                                  // wday
193                    0,                                  // yday
194                    0}),
195                *tm_data);
196 
197   // 1970-01-32 00:00:00 returns 1970-02-01 00:00:00.
198   seconds = 31 * TimeConstants::SecondsPerDay;
199   tm_data = __llvm_libc::gmtime(&seconds);
200   EXPECT_TM_EQ((tm{0, // sec
201                    0, // min
202                    0, // hr
203                    1, // day
204                    0, // tm_mon starts with 0 for Jan
205                    1970 - TimeConstants::TimeYearBase, // year
206                    0,                                  // wday
207                    0,                                  // yday
208                    0}),
209                *tm_data);
210 
211   // 1970-02-29 00:00:00 returns 1970-03-01 00:00:00.
212   seconds = 59 * TimeConstants::SecondsPerDay;
213   tm_data = __llvm_libc::gmtime(&seconds);
214   EXPECT_TM_EQ((tm{0, // sec
215                    0, // min
216                    0, // hr
217                    1, // day
218                    2, // tm_mon starts with 0 for Jan
219                    1970 - TimeConstants::TimeYearBase, // year
220                    0,                                  // wday
221                    0,                                  // yday
222                    0}),
223                *tm_data);
224 
225   // 1972-02-30 00:00:00 returns 1972-03-01 00:00:00.
226   seconds = ((2 * TimeConstants::DaysPerNonLeapYear) + 60) *
227             TimeConstants::SecondsPerDay;
228   tm_data = __llvm_libc::gmtime(&seconds);
229   EXPECT_TM_EQ((tm{0, // sec
230                    0, // min
231                    0, // hr
232                    1, // day
233                    2, // tm_mon starts with 0 for Jan
234                    1972 - TimeConstants::TimeYearBase, // year
235                    3,                                  // wday
236                    0,                                  // yday
237                    0}),
238                *tm_data);
239 }
240 
TEST(LlvmLibcGmTime,EndOf32BitEpochYear)241 TEST(LlvmLibcGmTime, EndOf32BitEpochYear) {
242   // Test for maximum value of a signed 32-bit integer.
243   // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
244   time_t seconds = 0x7FFFFFFF;
245   struct tm *tm_data = __llvm_libc::gmtime(&seconds);
246   EXPECT_TM_EQ((tm{7,  // sec
247                    14, // min
248                    3,  // hr
249                    19, // day
250                    0,  // tm_mon starts with 0 for Jan
251                    2038 - TimeConstants::TimeYearBase, // year
252                    2,                                  // wday
253                    7,                                  // yday
254                    0}),
255                *tm_data);
256 }
257 
TEST(LlvmLibcGmTime,Max64BitYear)258 TEST(LlvmLibcGmTime, Max64BitYear) {
259   if (sizeof(time_t) == 4)
260     return;
261   // Mon Jan 1 12:50:50 2170 (200 years from 1970),
262   time_t seconds = 6311479850;
263   struct tm *tm_data = __llvm_libc::gmtime(&seconds);
264   EXPECT_TM_EQ((tm{50, // sec
265                    50, // min
266                    12, // hr
267                    1,  // day
268                    0,  // tm_mon starts with 0 for Jan
269                    2170 - TimeConstants::TimeYearBase, // year
270                    1,                                  // wday
271                    50,                                 // yday
272                    0}),
273                *tm_data);
274 
275   // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
276   seconds = 67767976202043050;
277   tm_data = __llvm_libc::gmtime(&seconds);
278   EXPECT_TM_EQ((tm{50, // sec
279                    50, // min
280                    12, // hr
281                    1,  // day
282                    0,  // tm_mon starts with 0 for Jan
283                    2147483647 - TimeConstants::TimeYearBase, // year
284                    2,                                        // wday
285                    50,                                       // yday
286                    0}),
287                *tm_data);
288 }
289