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 "test/ErrnoSetterMatcher.h" 11 #include "utils/UnitTest/Test.h" 12 13 #include <errno.h> 14 #include <string.h> 15 16 using __llvm_libc::testing::ErrnoSetterMatcher::Fails; 17 18 static constexpr time_t OutOfRangeReturnValue = -1; 19 20 // A helper function to initialize tm data structure. 21 static inline void initialize_tm_data(struct tm *tm_data, int year, int month, 22 int mday, int hour, int min, int sec) { 23 struct tm temp = {.tm_sec = sec, 24 .tm_min = min, 25 .tm_hour = hour, 26 .tm_mday = mday, 27 .tm_mon = month, 28 .tm_year = year - 1900}; 29 *tm_data = temp; 30 } 31 32 static inline time_t call_mktime(struct tm *tm_data, int year, int month, 33 int mday, int hour, int min, int sec) { 34 initialize_tm_data(tm_data, year, month, mday, hour, min, sec); 35 return __llvm_libc::mktime(tm_data); 36 } 37 38 TEST(MkTime, FailureSetsErrno) { 39 struct tm tm_data; 40 initialize_tm_data(&tm_data, 0, 0, 0, 0, 0, -1); 41 EXPECT_THAT(__llvm_libc::mktime(&tm_data), Fails(EOVERFLOW)); 42 } 43 44 TEST(MkTime, MktimeTestsInvalidSeconds) { 45 struct tm tm_data; 46 EXPECT_EQ(call_mktime(&tm_data, 0, 0, 0, 0, 0, -1), OutOfRangeReturnValue); 47 EXPECT_EQ(call_mktime(&tm_data, 0, 0, 0, 0, 0, 60), OutOfRangeReturnValue); 48 } 49 50 TEST(MkTime, MktimeTestsInvalidMinutes) { 51 struct tm tm_data; 52 EXPECT_EQ(call_mktime(&tm_data, 0, 0, 0, 0, -1, 0), OutOfRangeReturnValue); 53 EXPECT_EQ(call_mktime(&tm_data, 0, 0, 1, 0, 60, 0), OutOfRangeReturnValue); 54 } 55 56 TEST(MkTime, MktimeTestsInvalidHours) { 57 struct tm tm_data; 58 EXPECT_EQ(call_mktime(&tm_data, 0, 0, 0, -1, 0, 0), OutOfRangeReturnValue); 59 EXPECT_EQ(call_mktime(&tm_data, 0, 0, 0, 24, 0, 0), OutOfRangeReturnValue); 60 } 61 62 TEST(MkTime, MktimeTestsInvalidYear) { 63 struct tm tm_data; 64 EXPECT_EQ(call_mktime(&tm_data, 1969, 0, 0, 0, 0, 0), OutOfRangeReturnValue); 65 } 66 67 TEST(MkTime, MktimeTestsInvalidEndOf32BitEpochYear) { 68 if (sizeof(time_t) != 4) 69 return; 70 struct tm tm_data; 71 // 2038-01-19 03:14:08 tests overflow of the second in 2038. 72 EXPECT_EQ(call_mktime(&tm_data, 2038, 0, 19, 3, 14, 8), 73 OutOfRangeReturnValue); 74 // 2038-01-19 03:15:07 tests overflow of the minute in 2038. 75 EXPECT_EQ(call_mktime(&tm_data, 2038, 0, 19, 3, 15, 7), 76 OutOfRangeReturnValue); 77 // 2038-01-19 04:14:07 tests overflow of the hour in 2038. 78 EXPECT_EQ(call_mktime(&tm_data, 2038, 0, 19, 4, 14, 7), 79 OutOfRangeReturnValue); 80 // 2038-01-20 03:14:07 tests overflow of the day in 2038. 81 EXPECT_EQ(call_mktime(&tm_data, 2038, 0, 20, 3, 14, 7), 82 OutOfRangeReturnValue); 83 // 2038-02-19 03:14:07 tests overflow of the month in 2038. 84 EXPECT_EQ(call_mktime(&tm_data, 2038, 1, 19, 3, 14, 7), 85 OutOfRangeReturnValue); 86 // 2039-01-19 03:14:07 tests overflow of the year. 87 EXPECT_EQ(call_mktime(&tm_data, 2039, 0, 19, 3, 14, 7), 88 OutOfRangeReturnValue); 89 } 90 91 TEST(MkTime, MktimeTestsInvalidMonths) { 92 struct tm tm_data; 93 // Before Jan of 1970 94 EXPECT_EQ(call_mktime(&tm_data, 1970, -1, 15, 0, 0, 0), 95 OutOfRangeReturnValue); 96 // After Dec of 1970 97 EXPECT_EQ(call_mktime(&tm_data, 1970, 12, 15, 0, 0, 0), 98 OutOfRangeReturnValue); 99 } 100 101 TEST(MkTime, MktimeTestsInvalidDays) { 102 struct tm tm_data; 103 // -1 day of Jan, 1970 104 EXPECT_EQ(call_mktime(&tm_data, 1970, 0, -1, 0, 0, 0), OutOfRangeReturnValue); 105 // 32 day of Jan, 1970 106 EXPECT_EQ(call_mktime(&tm_data, 1970, 0, 32, 0, 0, 0), OutOfRangeReturnValue); 107 // 29 day of Feb, 1970 108 EXPECT_EQ(call_mktime(&tm_data, 1970, 1, 29, 0, 0, 0), OutOfRangeReturnValue); 109 // 30 day of Feb, 1972 110 EXPECT_EQ(call_mktime(&tm_data, 1972, 1, 30, 0, 0, 0), OutOfRangeReturnValue); 111 // 31 day of Apr, 1970 112 EXPECT_EQ(call_mktime(&tm_data, 1970, 3, 31, 0, 0, 0), OutOfRangeReturnValue); 113 } 114 115 TEST(MkTime, MktimeTestsStartEpochYear) { 116 // Thu Jan 1 00:00:00 1970 117 struct tm tm_data; 118 EXPECT_EQ(call_mktime(&tm_data, 1970, 0, 1, 0, 0, 0), static_cast<time_t>(0)); 119 EXPECT_EQ(4, tm_data.tm_wday); 120 EXPECT_EQ(0, tm_data.tm_yday); 121 } 122 123 TEST(MkTime, MktimeTestsEpochYearRandomTime) { 124 // Thu Jan 1 12:50:50 1970 125 struct tm tm_data; 126 EXPECT_EQ(call_mktime(&tm_data, 1970, 0, 1, 12, 50, 50), 127 static_cast<time_t>(46250)); 128 EXPECT_EQ(4, tm_data.tm_wday); 129 EXPECT_EQ(0, tm_data.tm_yday); 130 } 131 132 TEST(MkTime, MktimeTestsEndOf32BitEpochYear) { 133 struct tm tm_data; 134 // Test for maximum value of a signed 32-bit integer. 135 // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC. 136 EXPECT_EQ(call_mktime(&tm_data, 2038, 0, 19, 3, 14, 7), 137 static_cast<time_t>(0x7FFFFFFF)); 138 EXPECT_EQ(2, tm_data.tm_wday); 139 EXPECT_EQ(18, tm_data.tm_yday); 140 } 141 142 TEST(MkTime, MktimeTests64BitYear) { 143 if (sizeof(time_t) == 4) 144 return; 145 // Mon Jan 1 12:50:50 2170 146 struct tm tm_data; 147 EXPECT_EQ(call_mktime(&tm_data, 2170, 0, 1, 12, 50, 50), 148 static_cast<time_t>(6311479850)); 149 EXPECT_EQ(1, tm_data.tm_wday); 150 EXPECT_EQ(0, tm_data.tm_yday); 151 152 // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year. 153 EXPECT_EQ(call_mktime(&tm_data, 2147483647, 0, 1, 12, 50, 50), 154 static_cast<time_t>(67767976202043050)); 155 EXPECT_EQ(2, tm_data.tm_wday); 156 EXPECT_EQ(0, tm_data.tm_yday); 157 } 158