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