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