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