1 //===-- Unittests for asctime ---------------------------------------------===//
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/asctime.h"
10 #include "test/src/time/TmHelper.h"
11 #include "utils/UnitTest/Test.h"
12 
call_asctime(struct tm * tm_data,int year,int month,int mday,int hour,int min,int sec,int wday,int yday)13 static inline char *call_asctime(struct tm *tm_data, int year, int month,
14                                  int mday, int hour, int min, int sec, int wday,
15                                  int yday) {
16   __llvm_libc::tmhelper::testing::initialize_tm_data(
17       tm_data, year, month, mday, hour, min, sec, wday, yday);
18   return __llvm_libc::asctime(tm_data);
19 }
20 
TEST(LlvmLibcAsctime,Nullptr)21 TEST(LlvmLibcAsctime, Nullptr) {
22   char *result;
23   result = __llvm_libc::asctime(nullptr);
24   ASSERT_EQ(EINVAL, llvmlibc_errno);
25   ASSERT_STREQ(nullptr, result);
26 }
27 
28 // Weekdays are in the range 0 to 6. Test passing invalid value in wday.
TEST(LlvmLibcAsctime,InvalidWday)29 TEST(LlvmLibcAsctime, InvalidWday) {
30   struct tm tm_data;
31   char *result;
32 
33   // Test with wday = -1.
34   result = call_asctime(&tm_data,
35                         1970, // year
36                         1,    // month
37                         1,    // day
38                         0,    // hr
39                         0,    // min
40                         0,    // sec
41                         -1,   // wday
42                         0);   // yday
43   ASSERT_EQ(EINVAL, llvmlibc_errno);
44 
45   // Test with wday = 7.
46   result = call_asctime(&tm_data,
47                         1970, // year
48                         1,    // month
49                         1,    // day
50                         0,    // hr
51                         0,    // min
52                         0,    // sec
53                         7,    // wday
54                         0);   // yday
55   ASSERT_EQ(EINVAL, llvmlibc_errno);
56 }
57 
58 // Months are from January to December. Test passing invalid value in month.
TEST(LlvmLibcAsctime,InvalidMonth)59 TEST(LlvmLibcAsctime, InvalidMonth) {
60   struct tm tm_data;
61   char *result;
62 
63   // Test with month = 0.
64   result = call_asctime(&tm_data,
65                         1970, // year
66                         0,    // month
67                         1,    // day
68                         0,    // hr
69                         0,    // min
70                         0,    // sec
71                         4,    // wday
72                         0);   // yday
73   ASSERT_EQ(EINVAL, llvmlibc_errno);
74 
75   // Test with month = 13.
76   result = call_asctime(&tm_data,
77                         1970, // year
78                         13,   // month
79                         1,    // day
80                         0,    // hr
81                         0,    // min
82                         0,    // sec
83                         4,    // wday
84                         0);   // yday
85   ASSERT_EQ(EINVAL, llvmlibc_errno);
86 }
87 
TEST(LlvmLibcAsctime,ValidWeekdays)88 TEST(LlvmLibcAsctime, ValidWeekdays) {
89   struct tm tm_data;
90   char *result;
91   // 1970-01-01 00:00:00.
92   result = call_asctime(&tm_data,
93                         1970, // year
94                         1,    // month
95                         1,    // day
96                         0,    // hr
97                         0,    // min
98                         0,    // sec
99                         4,    // wday
100                         0);   // yday
101   ASSERT_STREQ("Thu Jan  1 00:00:00 1970\n", result);
102 
103   // 1970-01-03 00:00:00.
104   result = call_asctime(&tm_data,
105                         1970, // year
106                         1,    // month
107                         3,    // day
108                         0,    // hr
109                         0,    // min
110                         0,    // sec
111                         6,    // wday
112                         0);   // yday
113   ASSERT_STREQ("Sat Jan  3 00:00:00 1970\n", result);
114 
115   // 1970-01-04 00:00:00.
116   result = call_asctime(&tm_data,
117                         1970, // year
118                         1,    // month
119                         4,    // day
120                         0,    // hr
121                         0,    // min
122                         0,    // sec
123                         0,    // wday
124                         0);   // yday
125   ASSERT_STREQ("Sun Jan  4 00:00:00 1970\n", result);
126 }
127 
TEST(LlvmLibcAsctime,ValidMonths)128 TEST(LlvmLibcAsctime, ValidMonths) {
129   struct tm tm_data;
130   char *result;
131   // 1970-01-01 00:00:00.
132   result = call_asctime(&tm_data,
133                         1970, // year
134                         1,    // month
135                         1,    // day
136                         0,    // hr
137                         0,    // min
138                         0,    // sec
139                         4,    // wday
140                         0);   // yday
141   ASSERT_STREQ("Thu Jan  1 00:00:00 1970\n", result);
142 
143   // 1970-02-01 00:00:00.
144   result = call_asctime(&tm_data,
145                         1970, // year
146                         2,    // month
147                         1,    // day
148                         0,    // hr
149                         0,    // min
150                         0,    // sec
151                         0,    // wday
152                         0);   // yday
153   ASSERT_STREQ("Sun Feb  1 00:00:00 1970\n", result);
154 
155   // 1970-12-31 23:59:59.
156   result = call_asctime(&tm_data,
157                         1970, // year
158                         12,   // month
159                         31,   // day
160                         23,   // hr
161                         59,   // min
162                         59,   // sec
163                         4,    // wday
164                         0);   // yday
165   ASSERT_STREQ("Thu Dec 31 23:59:59 1970\n", result);
166 }
167 
TEST(LlvmLibcAsctime,EndOf32BitEpochYear)168 TEST(LlvmLibcAsctime, EndOf32BitEpochYear) {
169   struct tm tm_data;
170   char *result;
171   // Test for maximum value of a signed 32-bit integer.
172   // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
173   result = call_asctime(&tm_data,
174                         2038, // year
175                         1,    // month
176                         19,   // day
177                         3,    // hr
178                         14,   // min
179                         7,    // sec
180                         2,    // wday
181                         7);   // yday
182   ASSERT_STREQ("Tue Jan 19 03:14:07 2038\n", result);
183 }
184 
TEST(LlvmLibcAsctime,Max64BitYear)185 TEST(LlvmLibcAsctime, Max64BitYear) {
186   if (sizeof(time_t) == 4)
187     return;
188   // Mon Jan 1 12:50:50 2170 (200 years from 1970),
189   struct tm tm_data;
190   char *result;
191   result = call_asctime(&tm_data,
192                         2170, // year
193                         1,    // month
194                         1,    // day
195                         12,   // hr
196                         50,   // min
197                         50,   // sec
198                         1,    // wday
199                         50);  // yday
200   ASSERT_STREQ("Mon Jan  1 12:50:50 2170\n", result);
201 
202   // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
203   // This test would cause buffer overflow and thus asctime returns nullptr.
204   result = call_asctime(&tm_data,
205                         2147483647, // year
206                         1,          // month
207                         1,          // day
208                         12,         // hr
209                         50,         // min
210                         50,         // sec
211                         2,          // wday
212                         50);        // yday
213   ASSERT_EQ(EOVERFLOW, llvmlibc_errno);
214   ASSERT_STREQ(nullptr, result);
215 }
216