1 /* check-sources:disable-copyright-check */
2 #include <droplet.h>
3 #include <droplet/utils.h>
4 #include <check.h>
5 #include "utest_main.h"
6
7 /*
8 * Test case data copied from the Cyrus IMAPD unit tests
9 * http://git.cyrusimap.org/cyrus-imapd/tree/cunit/times.testc
10 */
11
START_TEST(rfc3501_test)12 START_TEST(rfc3501_test)
13 {
14 time_t t;
15
16 /* RFC3501 format */
17
18 /* Well-formed full RFC3501 format with 2-digit day
19 * "dd-mmm-yyyy HH:MM:SS zzzzz" */
20 t = dpl_get_date("15-Oct-2010 03:19:52 +1100", (time_t*)NULL);
21 dpl_assert_int_eq(t, 1287073192);
22
23 /* Well-formed full RFC3501 format with 1-digit day
24 * " d-mmm-yyyy HH:MM:SS zzzzz" */
25 t = dpl_get_date(" 5-Oct-2010 03:19:52 +1100", (time_t*)NULL);
26 dpl_assert_int_eq(t, 1286209192);
27 }
28 END_TEST
29
30 /* The getdate.y parser allows for RFC-822 style (comments)
31 * which are stripped out. */
START_TEST(bracket_test)32 START_TEST(bracket_test)
33 {
34 time_t t;
35
36 /* This is a quick and dirty way to break up the tokens
37 * in a date without introducing spaces. */
38 t = dpl_get_date("15-Oct-2010()03:19:52()+1100", (time_t*)NULL);
39 dpl_assert_int_eq(t, 1287073192);
40
41 t = dpl_get_date("15-Oct-2010( )03:19:52(\t )+1100", (time_t*)NULL);
42 dpl_assert_int_eq(t, 1287073192);
43
44 t = dpl_get_date("15-Oct-2010 ( hello ) 03:19:52(world)+1100", (time_t*)NULL);
45 dpl_assert_int_eq(t, 1287073192);
46 }
47 END_TEST
48
START_TEST(standard_timezone_test)49 START_TEST(standard_timezone_test)
50 {
51 static const time_t zulu = 813727192;
52 time_t t;
53 #define DATE "15-Oct-95 03:19:52"
54
55 /* Note, this test relies on the code not being able to tell
56 * that when daylight savings apply the given date/timezone
57 * combination may not be not valid. We're basically just
58 * testing that certain timezone names are recognised and
59 * that their time offsets are correct. */
60
61 /* GMT/UTC */
62 t = dpl_get_date(DATE " gmt", (time_t*)NULL);
63 dpl_assert_int_eq(t, zulu);
64 t = dpl_get_date(DATE " GMT", (time_t*)NULL);
65 dpl_assert_int_eq(t, zulu);
66 t = dpl_get_date(DATE " UT", (time_t*)NULL);
67 dpl_assert_int_eq(t, zulu);
68 t = dpl_get_date(DATE " ut", (time_t*)NULL);
69 dpl_assert_int_eq(t, zulu);
70 t = dpl_get_date(DATE " UTC", (time_t*)NULL);
71 dpl_assert_int_eq(t, zulu);
72 t = dpl_get_date(DATE " utc", (time_t*)NULL);
73 dpl_assert_int_eq(t, zulu);
74
75 /* US standard timezones */
76 t = dpl_get_date(DATE " est", (time_t*)NULL);
77 dpl_assert_int_eq(t, zulu + 5 * 3600);
78 t = dpl_get_date(DATE " EST", (time_t*)NULL);
79 dpl_assert_int_eq(t, zulu + 5 * 3600);
80 t = dpl_get_date(DATE " cst", (time_t*)NULL);
81 dpl_assert_int_eq(t, zulu + 6 * 3600);
82 t = dpl_get_date(DATE " CST", (time_t*)NULL);
83 dpl_assert_int_eq(t, zulu + 6 * 3600);
84 t = dpl_get_date(DATE " mst", (time_t*)NULL);
85 dpl_assert_int_eq(t, zulu + 7 * 3600);
86 t = dpl_get_date(DATE " MST", (time_t*)NULL);
87 dpl_assert_int_eq(t, zulu + 7 * 3600);
88 t = dpl_get_date(DATE " pst", (time_t*)NULL);
89 dpl_assert_int_eq(t, zulu + 8 * 3600);
90 t = dpl_get_date(DATE " PST", (time_t*)NULL);
91 dpl_assert_int_eq(t, zulu + 8 * 3600);
92
93 /* US daylight saving timezones */
94 t = dpl_get_date(DATE " edt", (time_t*)NULL);
95 dpl_assert_int_eq(t, zulu + 4 * 3600);
96 t = dpl_get_date(DATE " EDT", (time_t*)NULL);
97 dpl_assert_int_eq(t, zulu + 4 * 3600);
98 t = dpl_get_date(DATE " cdt", (time_t*)NULL);
99 dpl_assert_int_eq(t, zulu + 5 * 3600);
100 t = dpl_get_date(DATE " CDT", (time_t*)NULL);
101 dpl_assert_int_eq(t, zulu + 5 * 3600);
102 t = dpl_get_date(DATE " mdt", (time_t*)NULL);
103 dpl_assert_int_eq(t, zulu + 6 * 3600);
104 t = dpl_get_date(DATE " MDT", (time_t*)NULL);
105 dpl_assert_int_eq(t, zulu + 6 * 3600);
106 t = dpl_get_date(DATE " pdt", (time_t*)NULL);
107 dpl_assert_int_eq(t, zulu + 7 * 3600);
108 t = dpl_get_date(DATE " PDT", (time_t*)NULL);
109 dpl_assert_int_eq(t, zulu + 7 * 3600);
110
111 /* Australian standard timezones */
112
113 /* Eastern */
114 t = dpl_get_date(DATE " aest", (time_t*)NULL);
115 dpl_assert_int_eq(t, zulu - 10 * 3600);
116 t = dpl_get_date(DATE " AEST", (time_t*)NULL);
117 dpl_assert_int_eq(t, zulu - 10 * 3600);
118 /* Central is tricky - half an hour offset */
119 t = dpl_get_date(DATE " acst", (time_t*)NULL);
120 dpl_assert_int_eq(t, zulu - (9 * 3600 + 1800));
121 t = dpl_get_date(DATE " ACST", (time_t*)NULL);
122 dpl_assert_int_eq(t, zulu - (9 * 3600 + 1800));
123 /* Western */
124 t = dpl_get_date(DATE " wst", (time_t*)NULL);
125 dpl_assert_int_eq(t, zulu - 8 * 3600);
126 t = dpl_get_date(DATE " WST", (time_t*)NULL);
127 dpl_assert_int_eq(t, zulu - 8 * 3600);
128
129 /* Australian daylight timezones */
130
131 /* Eastern */
132 t = dpl_get_date(DATE " aedt", (time_t*)NULL);
133 dpl_assert_int_eq(t, zulu - 11 * 3600);
134 t = dpl_get_date(DATE " AEDT", (time_t*)NULL);
135 dpl_assert_int_eq(t, zulu - 11 * 3600);
136 /* Central */
137 t = dpl_get_date(DATE " acdt", (time_t*)NULL);
138 dpl_assert_int_eq(t, zulu - (10 * 3600 + 1800));
139 t = dpl_get_date(DATE " ACDT", (time_t*)NULL);
140 dpl_assert_int_eq(t, zulu - (10 * 3600 + 1800));
141 /* no daylight savings in Western Aus */
142
143 #undef DATE
144 }
145 END_TEST
146
147 /*
148 * Test US military single-letter timezone names.
149 *
150 * Sadly the code appears to calculate the correct timezone
151 * offset but then apply it *BACKWARDS*. As a result only
152 * the J (invalid) and Z (offset 0) cases pass. If I cared
153 * more about this niche feature I would fix it.
154 */
START_TEST(military_timezone_test)155 START_TEST(military_timezone_test)
156 {
157 time_t t;
158 int r;
159 static const time_t zulu = 813727192;
160 #define DATE "15-Oct-95 03:19:52"
161
162 /* Well-formed legacy format with 2-digit day, 2-digit year,
163 * uppercase 1-char timezone = UTC, "dd-mmm-yy HH:MM:SS-z" */
164 t = dpl_get_date(DATE "-Z", (time_t*)NULL);
165 dpl_assert_int_eq(t, zulu);
166
167 /* Well-formed legacy format with 2-digit day, 2-digit year,
168 * lowercase 1-char timezone = UTC, "dd-mmm-yy HH:MM:SS-z" */
169 t = dpl_get_date(DATE "-z", (time_t*)NULL);
170 dpl_assert_int_eq(t, zulu);
171
172 #if 0
173 /* Well-formed legacy format with 2-digit day, 2-digit year,
174 * uppercase 1-char timezone = +0100, "dd-mmm-yy HH:MM:SS-z" */
175 t = dpl_get_date(DATE"-A", (time_t *)NULL);
176 dpl_assert_int_eq(t, zulu-1*3600);
177
178 /* Well-formed legacy format with 2-digit day, 2-digit year,
179 * uppercase 1-char timezone = +0200, "dd-mmm-yy HH:MM:SS-z" */
180 t = dpl_get_date(DATE"-B", (time_t *)NULL);
181 dpl_assert_int_eq(t, zulu-2*3600);
182
183 /* Well-formed legacy format with 2-digit day, 2-digit year,
184 * uppercase 1-char timezone = +0900, "dd-mmm-yy HH:MM:SS-z" */
185 t = dpl_get_date(DATE"-I", (time_t *)NULL);
186 dpl_assert_int_eq(t, zulu-9*3600);
187 #endif
188
189 /* Well-formed legacy format with 2-digit day, 2-digit year,
190 * erroneous uppercase 1-char timezone, "dd-mmm-yy HH:MM:SS-z" */
191 t = dpl_get_date(DATE "-J", (time_t*)NULL);
192 dpl_assert_int_eq(t, -1);
193
194 #if 0
195 /* Well-formed legacy format with 2-digit day, 2-digit year,
196 * uppercase 1-char timezone = +1000, "dd-mmm-yy HH:MM:SS-z" */
197 t = dpl_get_date(DATE"-K", (time_t *)NULL);
198 dpl_assert_int_eq(t, zulu-10*3600);
199
200 /* Well-formed legacy format with 2-digit day, 2-digit year,
201 * 1-char timezone = +1200, "dd-mmm-yy HH:MM:SS-z" */
202 t = dpl_get_date(DATE"-M", (time_t *)NULL);
203 dpl_assert_int_eq(t, zulu-12*3600);
204
205 /* Well-formed legacy format with 2-digit day, 2-digit year,
206 * uppercase 1-char timezone = -0100, "dd-mmm-yy HH:MM:SS-z" */
207 t = dpl_get_date(DATE"-N", (time_t *)NULL);
208 dpl_assert_int_eq(t, zulu+1*3600);
209
210 /* Well-formed legacy format with 2-digit day, 2-digit year,
211 * 1-char timezone = -1200, "dd-mmm-yy HH:MM:SS-z" */
212 t = dpl_get_date(DATE"-Y", (time_t *)NULL);
213 dpl_assert_int_eq(t, zulu+12*3600);
214 #endif
215
216 #undef DATE
217 }
218 END_TEST
219
START_TEST(numeric_timezone_test)220 START_TEST(numeric_timezone_test)
221 {
222 static const time_t zulu = 813727192;
223 time_t t;
224 #define DATE "15-Oct-95 03:19:52"
225
226 t = dpl_get_date(DATE "+0000", (time_t*)NULL);
227 dpl_assert_int_eq(t, zulu);
228
229 t = dpl_get_date(DATE "+0100", (time_t*)NULL);
230 dpl_assert_int_eq(t, zulu - 1 * 3600);
231
232 t = dpl_get_date(DATE "+0900", (time_t*)NULL);
233 dpl_assert_int_eq(t, zulu - 9 * 3600);
234
235 t = dpl_get_date(DATE "+1000", (time_t*)NULL);
236 dpl_assert_int_eq(t, zulu - 10 * 3600);
237
238 t = dpl_get_date(DATE "+1100", (time_t*)NULL);
239 dpl_assert_int_eq(t, zulu - 11 * 3600);
240
241 t = dpl_get_date(DATE "-0100", (time_t*)NULL);
242 dpl_assert_int_eq(t, zulu + 1 * 3600);
243
244 t = dpl_get_date(DATE "-0900", (time_t*)NULL);
245 dpl_assert_int_eq(t, zulu + 9 * 3600);
246
247 t = dpl_get_date(DATE "-1000", (time_t*)NULL);
248 dpl_assert_int_eq(t, zulu + 10 * 3600);
249
250 t = dpl_get_date(DATE "-1100", (time_t*)NULL);
251 dpl_assert_int_eq(t, zulu + 11 * 3600);
252
253 #undef DATE
254 }
255 END_TEST
256
START_TEST(rfc822_test)257 START_TEST(rfc822_test)
258 {
259 time_t t;
260
261 t = dpl_get_date("Tue, 16 Nov 2010 12:46:49 +1100", (time_t*)NULL);
262 dpl_assert_int_eq(t, 1289872009);
263 }
264 END_TEST
265
START_TEST(ctime_test)266 START_TEST(ctime_test)
267 {
268 time_t t;
269
270 t = dpl_get_date("16-Nov-2010 13:15:25 +1100", (time_t*)NULL);
271 dpl_assert_int_eq(t, 1289873725);
272 }
273 END_TEST
274
275 #if 0
276 /* ISO 8601 format, like 2010-11-26T14:22:02+11:00 doesn't work,
277 * the "T" confuses the parser */
278 START_TEST(iso8601_test)
279 {
280 static const time_t TIMET = 1290741722;
281 time_t t;
282
283 t = dpl_get_date("2010-11-26T14:22:02+11:00", (time_t *)NULL);
284 dpl_assert_int_eq(t, TIMET);
285
286 t = dpl_get_date("2010-11-26T03:22:02Z", (time_t *)NULL);
287 dpl_assert_int_eq(t, TIMET);
288
289 t = dpl_get_date("2010-11-25T22:22:02-05:00", (time_t *)NULL);
290 dpl_assert_int_eq(t, TIMET);
291 }
292 END_TEST
293 #endif
294
295
296 #if 0
297 /* the getdate.y code doesn't seem to check for leapyear correctness */
298 START_TEST(rfc3501_leapyear_test)
299 {
300 time_t t;
301
302 /* 2000 is a leapyear */
303 t = dpl_get_date("29-Feb-2000 11:22:33 +1100", (time_t *)NULL);
304 dpl_assert_int_eq(t, 951783753);
305
306 /* 2001 is not a leapyear */
307 t = dpl_get_date("29-Feb-2001 11:22:33 +1100", (time_t *)NULL);
308 dpl_assert_int_eq(t, -1);
309
310 /* 2004 is a leapyear */
311 t = dpl_get_date("29-Feb-2004 11:22:33 +1100", (time_t *)NULL);
312 dpl_assert_int_eq(t, 1078014153);
313 }
314 END_TEST
315 #endif
316
317
getdate_suite(void)318 Suite* getdate_suite(void)
319 {
320 Suite* s = suite_create("getdate");
321 TCase* t = tcase_create("base");
322 tcase_add_test(t, rfc3501_test);
323 tcase_add_test(t, bracket_test);
324 tcase_add_test(t, standard_timezone_test);
325 tcase_add_test(t, military_timezone_test);
326 tcase_add_test(t, numeric_timezone_test);
327 tcase_add_test(t, rfc822_test);
328 tcase_add_test(t, ctime_test);
329 suite_add_tcase(s, t);
330 return s;
331 }
332