1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "apr_time.h"
18 #include "apr_errno.h"
19 #include "apr_general.h"
20 #include "apr_lib.h"
21 #include "testutil.h"
22 #include "apr_strings.h"
23 #include <time.h>
24
25 #define STR_SIZE 45
26
27 /* The time value is used throughout the tests, so just make this a global.
28 * Also, we need a single value that we can test for the positive tests, so
29 * I chose the number below, it corresponds to:
30 * 2002-09-14 12:05:36.186711 -25200 [257 Sat].
31 * Which happens to be when I wrote the new tests.
32 */
33 static apr_time_t now = APR_INT64_C(1032030336186711);
34 /* 2012-08-11 16:00:55.151600 -14400 [224 Sat] DST */
35 static apr_time_t leap_year_now = APR_INT64_C(1344715255151600);
36
print_time(apr_pool_t * pool,const apr_time_exp_t * xt)37 static char* print_time (apr_pool_t *pool, const apr_time_exp_t *xt)
38 {
39 return apr_psprintf (pool,
40 "%04d-%02d-%02d %02d:%02d:%02d.%06d %+05d [%d %s]%s",
41 xt->tm_year + 1900,
42 xt->tm_mon + 1,
43 xt->tm_mday,
44 xt->tm_hour,
45 xt->tm_min,
46 xt->tm_sec,
47 xt->tm_usec,
48 xt->tm_gmtoff,
49 xt->tm_yday + 1,
50 apr_day_snames[xt->tm_wday],
51 (xt->tm_isdst ? " DST" : ""));
52 }
53
54
test_now(abts_case * tc,void * data)55 static void test_now(abts_case *tc, void *data)
56 {
57 apr_time_t timediff;
58 apr_time_t current;
59 time_t os_now;
60
61 current = apr_time_now();
62 time(&os_now);
63
64 timediff = os_now - (current / APR_USEC_PER_SEC);
65 /* Even though these are called so close together, there is the chance
66 * that the time will be slightly off, so accept anything between -1 and
67 * 1 second.
68 */
69 ABTS_ASSERT(tc, "apr_time and OS time do not agree",
70 (timediff > -2) && (timediff < 2));
71 }
72
test_gmtstr(abts_case * tc,void * data)73 static void test_gmtstr(abts_case *tc, void *data)
74 {
75 apr_status_t rv;
76 apr_time_exp_t xt;
77
78 rv = apr_time_exp_gmt(&xt, now);
79 if (rv == APR_ENOTIMPL) {
80 ABTS_NOT_IMPL(tc, "apr_time_exp_gmt");
81 }
82 ABTS_TRUE(tc, rv == APR_SUCCESS);
83 ABTS_STR_EQUAL(tc, "2002-09-14 19:05:36.186711 +0000 [257 Sat]",
84 print_time(p, &xt));
85 }
86
test_exp_lt(abts_case * tc,void * data)87 static void test_exp_lt(abts_case *tc, void *data)
88 {
89 apr_time_t test_times[] = {0, 0, 0};
90 int i;
91
92 test_times[0] = now;
93 test_times[1] = leap_year_now;
94
95 for (i = 0; test_times[i] != 0; i++) {
96 apr_status_t rv;
97 apr_time_exp_t xt;
98 time_t posix_secs = (time_t)apr_time_sec(test_times[i]);
99 struct tm *posix_exp = localtime(&posix_secs);
100
101 rv = apr_time_exp_lt(&xt, test_times[i]);
102 if (rv == APR_ENOTIMPL) {
103 ABTS_NOT_IMPL(tc, "apr_time_exp_lt");
104 }
105 ABTS_TRUE(tc, rv == APR_SUCCESS);
106
107 #define CHK_FIELD(f) \
108 ABTS_ASSERT(tc, "Mismatch in " #f, posix_exp->f == xt.f)
109
110 CHK_FIELD(tm_sec);
111 CHK_FIELD(tm_min);
112 CHK_FIELD(tm_hour);
113 CHK_FIELD(tm_mday);
114 CHK_FIELD(tm_mon);
115 CHK_FIELD(tm_year);
116 CHK_FIELD(tm_wday);
117 CHK_FIELD(tm_yday);
118 CHK_FIELD(tm_isdst);
119 #undef CHK_FIELD
120 }
121 }
122
test_exp_get_gmt(abts_case * tc,void * data)123 static void test_exp_get_gmt(abts_case *tc, void *data)
124 {
125 apr_status_t rv;
126 apr_time_exp_t xt;
127 apr_time_t imp;
128 apr_int64_t hr_off_64;
129
130 rv = apr_time_exp_gmt(&xt, now);
131 ABTS_TRUE(tc, rv == APR_SUCCESS);
132 rv = apr_time_exp_get(&imp, &xt);
133 if (rv == APR_ENOTIMPL) {
134 ABTS_NOT_IMPL(tc, "apr_time_exp_get");
135 }
136 ABTS_TRUE(tc, rv == APR_SUCCESS);
137 hr_off_64 = (apr_int64_t) xt.tm_gmtoff * APR_USEC_PER_SEC;
138 ABTS_TRUE(tc, now + hr_off_64 == imp);
139 }
140
test_exp_get_lt(abts_case * tc,void * data)141 static void test_exp_get_lt(abts_case *tc, void *data)
142 {
143 apr_status_t rv;
144 apr_time_exp_t xt;
145 apr_time_t imp;
146 apr_int64_t hr_off_64;
147
148 rv = apr_time_exp_lt(&xt, now);
149 ABTS_TRUE(tc, rv == APR_SUCCESS);
150 rv = apr_time_exp_get(&imp, &xt);
151 if (rv == APR_ENOTIMPL) {
152 ABTS_NOT_IMPL(tc, "apr_time_exp_get");
153 }
154 ABTS_TRUE(tc, rv == APR_SUCCESS);
155 hr_off_64 = (apr_int64_t) xt.tm_gmtoff * APR_USEC_PER_SEC;
156 ABTS_TRUE(tc, now + hr_off_64 == imp);
157 }
158
test_imp_gmt(abts_case * tc,void * data)159 static void test_imp_gmt(abts_case *tc, void *data)
160 {
161 apr_status_t rv;
162 apr_time_exp_t xt;
163 apr_time_t imp;
164
165 rv = apr_time_exp_gmt(&xt, now);
166 ABTS_TRUE(tc, rv == APR_SUCCESS);
167 rv = apr_time_exp_gmt_get(&imp, &xt);
168 if (rv == APR_ENOTIMPL) {
169 ABTS_NOT_IMPL(tc, "apr_time_exp_gmt_get");
170 }
171 ABTS_TRUE(tc, rv == APR_SUCCESS);
172 ABTS_TRUE(tc, now == imp);
173 }
174
test_rfcstr(abts_case * tc,void * data)175 static void test_rfcstr(abts_case *tc, void *data)
176 {
177 apr_status_t rv;
178 char str[STR_SIZE];
179
180 rv = apr_rfc822_date(str, now);
181 if (rv == APR_ENOTIMPL) {
182 ABTS_NOT_IMPL(tc, "apr_rfc822_date");
183 }
184 ABTS_TRUE(tc, rv == APR_SUCCESS);
185 ABTS_STR_EQUAL(tc, "Sat, 14 Sep 2002 19:05:36 GMT", str);
186 }
187
test_ctime(abts_case * tc,void * data)188 static void test_ctime(abts_case *tc, void *data)
189 {
190 apr_status_t rv;
191 char apr_str[STR_SIZE];
192 char libc_str[STR_SIZE];
193 apr_time_t now_sec = apr_time_sec(now);
194 time_t posix_sec = (time_t) now_sec;
195
196 rv = apr_ctime(apr_str, now);
197 if (rv == APR_ENOTIMPL) {
198 ABTS_NOT_IMPL(tc, "apr_ctime");
199 }
200 ABTS_TRUE(tc, rv == APR_SUCCESS);
201 strcpy(libc_str, ctime(&posix_sec));
202 *strchr(libc_str, '\n') = '\0';
203
204 ABTS_STR_EQUAL(tc, libc_str, apr_str);
205 }
206
test_strftime(abts_case * tc,void * data)207 static void test_strftime(abts_case *tc, void *data)
208 {
209 apr_status_t rv;
210 apr_time_exp_t xt;
211 char *str = NULL;
212 apr_size_t sz;
213
214 rv = apr_time_exp_gmt(&xt, now);
215 str = apr_palloc(p, STR_SIZE + 1);
216 rv = apr_strftime(str, &sz, STR_SIZE, "%R %A %d %B %Y", &xt);
217 if (rv == APR_ENOTIMPL) {
218 ABTS_NOT_IMPL(tc, "apr_strftime");
219 }
220 ABTS_TRUE(tc, rv == APR_SUCCESS);
221 ABTS_STR_EQUAL(tc, "19:05 Saturday 14 September 2002", str);
222 }
223
test_strftimesmall(abts_case * tc,void * data)224 static void test_strftimesmall(abts_case *tc, void *data)
225 {
226 apr_status_t rv;
227 apr_time_exp_t xt;
228 char str[STR_SIZE];
229 apr_size_t sz;
230
231 rv = apr_time_exp_gmt(&xt, now);
232 rv = apr_strftime(str, &sz, STR_SIZE, "%T", &xt);
233 if (rv == APR_ENOTIMPL) {
234 ABTS_NOT_IMPL(tc, "apr_strftime");
235 }
236 ABTS_TRUE(tc, rv == APR_SUCCESS);
237 ABTS_STR_EQUAL(tc, "19:05:36", str);
238 }
239
test_exp_tz(abts_case * tc,void * data)240 static void test_exp_tz(abts_case *tc, void *data)
241 {
242 apr_status_t rv;
243 apr_time_exp_t xt;
244 apr_int32_t hr_off = -5 * 3600; /* 5 hours in seconds */
245
246 rv = apr_time_exp_tz(&xt, now, hr_off);
247 if (rv == APR_ENOTIMPL) {
248 ABTS_NOT_IMPL(tc, "apr_time_exp_tz");
249 }
250 ABTS_TRUE(tc, rv == APR_SUCCESS);
251 ABTS_TRUE(tc, (xt.tm_usec == 186711) &&
252 (xt.tm_sec == 36) &&
253 (xt.tm_min == 5) &&
254 (xt.tm_hour == 14) &&
255 (xt.tm_mday == 14) &&
256 (xt.tm_mon == 8) &&
257 (xt.tm_year == 102) &&
258 (xt.tm_wday == 6) &&
259 (xt.tm_yday == 256));
260 }
261
test_strftimeoffset(abts_case * tc,void * data)262 static void test_strftimeoffset(abts_case *tc, void *data)
263 {
264 apr_status_t rv;
265 apr_time_exp_t xt;
266 char str[STR_SIZE];
267 apr_size_t sz;
268 apr_int32_t hr_off = -5 * 3600; /* 5 hours in seconds */
269
270 apr_time_exp_tz(&xt, now, hr_off);
271 rv = apr_strftime(str, &sz, STR_SIZE, "%T", &xt);
272 if (rv == APR_ENOTIMPL) {
273 ABTS_NOT_IMPL(tc, "apr_strftime");
274 }
275 ABTS_TRUE(tc, rv == APR_SUCCESS);
276 }
277
278 /* 0.9.4 and earlier rejected valid dates in 2038 */
test_2038(abts_case * tc,void * data)279 static void test_2038(abts_case *tc, void *data)
280 {
281 apr_time_exp_t xt;
282 apr_time_t t;
283
284 /* 2038-01-19T03:14:07.000000Z */
285 xt.tm_year = 138;
286 xt.tm_mon = 0;
287 xt.tm_mday = 19;
288 xt.tm_hour = 3;
289 xt.tm_min = 14;
290 xt.tm_sec = 7;
291
292 APR_ASSERT_SUCCESS(tc, "explode January 19th, 2038",
293 apr_time_exp_get(&t, &xt));
294 }
295
testtime(abts_suite * suite)296 abts_suite *testtime(abts_suite *suite)
297 {
298 suite = ADD_SUITE(suite)
299
300 abts_run_test(suite, test_now, NULL);
301 abts_run_test(suite, test_gmtstr, NULL);
302 abts_run_test(suite, test_exp_lt, NULL);
303 abts_run_test(suite, test_exp_get_gmt, NULL);
304 abts_run_test(suite, test_exp_get_lt, NULL);
305 abts_run_test(suite, test_imp_gmt, NULL);
306 abts_run_test(suite, test_rfcstr, NULL);
307 abts_run_test(suite, test_ctime, NULL);
308 abts_run_test(suite, test_strftime, NULL);
309 abts_run_test(suite, test_strftimesmall, NULL);
310 abts_run_test(suite, test_exp_tz, NULL);
311 abts_run_test(suite, test_strftimeoffset, NULL);
312 abts_run_test(suite, test_2038, NULL);
313
314 return suite;
315 }
316
317