1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Copyright (C) 2005 Novell, Inc.
4 */
5
6 #include "test-utils.h"
7
8 static void check_ok (gconstpointer data);
9
10 static SoupDate *
make_date(const char * strdate)11 make_date (const char *strdate)
12 {
13 char *dup;
14 SoupDate *date;
15
16 /* We do it this way so that if soup_date_new_from_string()
17 * reads off the end of the string, it will trigger an error
18 * when valgrinding, rather than just reading the start of the
19 * next const string.
20 */
21 dup = g_strdup (strdate);
22 date = soup_date_new_from_string (dup);
23 g_free (dup);
24 return date;
25 }
26
27 static SoupDate *
check_correct_date(const char * strdate)28 check_correct_date (const char *strdate)
29 {
30 SoupDate *date;
31
32 date = make_date (strdate);
33 if (!date) {
34 g_assert_nonnull (date);
35 return NULL;
36 }
37
38 g_assert_cmpint (date->year, ==, 2004);
39 g_assert_cmpint (date->month, ==, 11);
40 g_assert_cmpint (date->day, ==, 6);
41 g_assert_cmpint (date->hour, ==, 8);
42 g_assert_cmpint (date->minute, ==, 9);
43 g_assert_cmpint (date->second, ==, 7);
44
45 return date;
46 }
47
48 typedef struct {
49 SoupDateFormat format;
50 const char *date;
51 const char *bugref;
52 } GoodDate;
53
54 static const GoodDate good_dates[] = {
55 { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT", NULL },
56 { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT", NULL },
57 { SOUP_DATE_RFC2822, "Sat, 6 Nov 2004 08:09:07 -0430", "579055" },
58 { SOUP_DATE_ISO8601_COMPACT, "20041106T080907", NULL },
59 { SOUP_DATE_ISO8601_FULL, "2004-11-06T08:09:07", NULL },
60 { SOUP_DATE_ISO8601_XMLRPC, "20041106T08:09:07", NULL }
61 };
62
63 static void
check_good(gconstpointer data)64 check_good (gconstpointer data)
65 {
66 GoodDate *good = (GoodDate *)data;
67 SoupDate *date;
68 char *strdate2;
69
70 if (good->bugref)
71 g_test_bug (good->bugref);
72
73 date = check_correct_date (good->date);
74 if (!date)
75 return;
76
77 strdate2 = soup_date_to_string (date, good->format);
78 soup_date_free (date);
79
80 soup_test_assert (strcmp (good->date, strdate2) == 0,
81 "restringification failed: '%s' -> '%s'\n",
82 good->date, strdate2);
83 g_free (strdate2);
84 }
85
86 typedef struct {
87 const char *date;
88 const char *bugref;
89 } OkDate;
90
91 static const OkDate ok_dates[] = {
92 /* rfc1123-date, and broken variants */
93 { "Sat, 06 Nov 2004 08:09:07 GMT", NULL },
94 { "Sat, 6 Nov 2004 08:09:07 GMT", NULL },
95 { "Sat, 6 Nov 2004 08:09:07 GMT", NULL },
96 { "Sat, 06 Nov 2004 08:09:07", NULL },
97 { "06 Nov 2004 08:09:07 GMT", NULL },
98 { "SAT, 06 NOV 2004 08:09:07 +1000", "644048" },
99
100 /* rfc850-date, and broken variants */
101 { "Saturday, 06-Nov-04 08:09:07 GMT", NULL },
102 { "Saturday, 6-Nov-04 08:09:07 GMT", NULL },
103 { "Saturday, 6-Nov-04 08:09:07 GMT", NULL },
104 { "Saturday, 06-Nov-104 08:09:07 GMT", NULL },
105 { "Saturday, 06-Nov-2004 08:09:07 GMT", NULL },
106 { "Saturday, 6-Nov-2004 08:09:07 GMT", NULL },
107 { "Saturday, 6-Nov-2004 08:09:07 GMT", NULL },
108 { "Saturday, 06-Nov-04 08:09:07", NULL },
109 { "06-Nov-04 08:09:07 GMT", NULL },
110
111 /* asctime-date, and broken variants */
112 { "Sat Nov 6 08:09:07 2004", NULL },
113 { "Sat Nov 06 08:09:07 2004", NULL },
114 { "Sat Nov 6 08:09:07 2004", NULL },
115 { "Sat Nov 6 08:09:07 2004 GMT", NULL },
116
117 /* ISO 8601 */
118 { "2004-11-06T08:09:07Z", NULL },
119 { "20041106T08:09:07Z", NULL },
120 { "20041106T08:09:07+00:00", NULL },
121 { "20041106T080907+00:00", NULL },
122
123 /* Netscape cookie spec date, and broken variants */
124 { "Sat, 06-Nov-2004 08:09:07 GMT", NULL },
125 { "Sat, 6-Nov-2004 08:09:07 GMT", NULL },
126 { "Sat, 6-Nov-2004 08:09:07 GMT", NULL },
127 { "Sat, 06-Nov-2004 08:09:07", NULL },
128
129 /* Original version of Netscape cookie spec, and broken variants */
130 { "Sat, 06-Nov-04 08:09:07 GMT", NULL },
131 { "Sat, 6-Nov-04 08:09:07 GMT", NULL },
132 { "Sat, 6-Nov-04 08:09:07 GMT", NULL },
133 { "Sat, 06-Nov-104 08:09:07 GMT", NULL },
134 { "Sat, 06-Nov-04 08:09:07", NULL },
135
136 /* Miscellaneous broken formats seen on the web */
137 { "Sat 06-Nov-2004 08:9:07", NULL },
138 { "Saturday, 06-Nov-04 8:9:07 GMT", NULL },
139 { "Sat, 06 Nov 2004 08:09:7 GMT", NULL }
140 };
141
142 static void
check_ok(gconstpointer data)143 check_ok (gconstpointer data)
144 {
145 OkDate *ok = (OkDate *)data;
146 SoupDate *date;
147
148 if (ok->bugref)
149 g_test_bug (ok->bugref);
150
151 date = check_correct_date (ok->date);
152 if (!date)
153 return;
154 soup_date_free (date);
155 }
156
157 #define TIME_T 1099728547L
158 #define TIME_T_STRING "1099728547"
159
160 static void
check_ok_time_t(void)161 check_ok_time_t (void)
162 {
163 SoupDate *date;
164
165 date = soup_date_new_from_time_t (TIME_T);
166
167 g_assert_cmpint (date->year, ==, 2004);
168 g_assert_cmpint (date->month, ==, 11);
169 g_assert_cmpint (date->day, ==, 6);
170 g_assert_cmpint (date->hour, ==, 8);
171 g_assert_cmpint (date->minute, ==, 9);
172 g_assert_cmpint (date->second, ==, 7);
173
174 g_assert_cmpuint (TIME_T, ==, soup_date_to_time_t (date));
175
176 soup_date_free (date);
177 }
178
179 typedef struct {
180 const char *date;
181 const char *bugref;
182 } BadDate;
183
184 static const BadDate bad_dates[] = {
185 /* broken rfc1123-date */
186 { ", 06 Nov 2004 08:09:07 GMT", NULL },
187 { "Sat, Nov 2004 08:09:07 GMT", NULL },
188 { "Sat, 06 2004 08:09:07 GMT", NULL },
189 { "Sat, 06 Nov 08:09:07 GMT", NULL },
190 { "Sat, 06 Nov 2004 :09:07 GMT", NULL },
191 { "Sat, 06 Nov 2004 09:07 GMT", NULL },
192 { "Sat, 06 Nov 2004 08::07 GMT", NULL },
193 { "Sat, 06 Nov 2004 08:09: GMT", NULL },
194
195 /* broken rfc850-date */
196 { ", 06-Nov-04 08:09:07 GMT", NULL },
197 { "Saturday, -Nov-04 08:09:07 GMT", NULL },
198 { "Saturday, Nov-04 08:09:07 GMT", NULL },
199 { "Saturday, 06-04 08:09:07 GMT", NULL },
200 { "Saturday, 06--04 08:09:07 GMT", NULL },
201 { "Saturday, 06-Nov- 08:09:07 GMT", NULL },
202 { "Saturday, 06-Nov 08:09:07 GMT", NULL },
203 { "Saturday, 06-Nov-04 :09:07 GMT", NULL },
204 { "Saturday, 06-Nov-04 09:07 GMT", NULL },
205 { "Saturday, 06-Nov-04 08::07 GMT", NULL },
206 { "Saturday, 06-Nov-04 08:09: GMT", NULL },
207
208 /* broken asctime-date */
209 { "Nov 6 08:09:07 2004", NULL },
210 { "Sat 6 08:09:07 2004", NULL },
211 { "Sat Nov 08:09:07 2004", NULL },
212 { "Sat Nov 6 :09:07 2004", NULL },
213 { "Sat Nov 6 09:07 2004", NULL },
214 { "Sat Nov 6 08::07 2004", NULL },
215 { "Sat Nov 6 08:09: 2004", NULL },
216 { "Sat Nov 6 08:09:07", NULL },
217 { "Sat Nov 6 08:09:07 GMT 2004", NULL }
218 };
219
220 static void
check_bad(gconstpointer data)221 check_bad (gconstpointer data)
222 {
223 BadDate *bad = (BadDate *)data;
224 SoupDate *date;
225
226 if (bad->bugref)
227 g_test_bug (bad->bugref);
228
229 date = make_date (bad->date);
230 soup_test_assert (date == NULL,
231 "date parsing succeeded for '%s': %d %d %d - %d %d %d",
232 bad->date,
233 date->year, date->month, date->day,
234 date->hour, date->minute, date->second);
235 g_clear_pointer (&date, soup_date_free);
236 }
237
238 typedef struct {
239 const char *source;
240 const char *http, *cookie, *rfc2822, *compact, *full, *xmlrpc;
241 } DateConversion;
242
243 static const DateConversion conversions[] = {
244 /* SOUP_DATE_HTTP */
245 { "Sat, 06 Nov 2004 08:09:07 GMT",
246
247 "Sat, 06 Nov 2004 08:09:07 GMT",
248 "Sat, 06-Nov-2004 08:09:07 GMT",
249 "Sat, 6 Nov 2004 08:09:07 +0000",
250 "20041106T080907Z",
251 "2004-11-06T08:09:07Z",
252 "20041106T08:09:07" },
253
254 /* RFC2822 GMT */
255 { "Sat, 6 Nov 2004 08:09:07 +0000",
256
257 "Sat, 06 Nov 2004 08:09:07 GMT",
258 "Sat, 06-Nov-2004 08:09:07 GMT",
259 "Sat, 6 Nov 2004 08:09:07 +0000",
260 "20041106T080907Z",
261 "2004-11-06T08:09:07Z",
262 "20041106T08:09:07" },
263
264 /* RFC2822 with positive offset */
265 { "Sat, 6 Nov 2004 08:09:07 +0430",
266
267 "Sat, 06 Nov 2004 04:39:07 GMT",
268 "Sat, 06-Nov-2004 04:39:07 GMT",
269 "Sat, 6 Nov 2004 08:09:07 +0430",
270 "20041106T080907+0430",
271 "2004-11-06T08:09:07+04:30",
272 "20041106T08:09:07" },
273
274 /* RFC2822 with negative offset */
275 { "Sat, 6 Nov 2004 08:09:07 -0430",
276
277 "Sat, 06 Nov 2004 12:39:07 GMT",
278 "Sat, 06-Nov-2004 12:39:07 GMT",
279 "Sat, 6 Nov 2004 08:09:07 -0430",
280 "20041106T080907-0430",
281 "2004-11-06T08:09:07-04:30",
282 "20041106T08:09:07" },
283
284 /* RFC2822 floating */
285 { "Sat, 6 Nov 2004 08:09:07 -0000",
286
287 "Sat, 06 Nov 2004 08:09:07 GMT",
288 "Sat, 06-Nov-2004 08:09:07 GMT",
289 "Sat, 6 Nov 2004 08:09:07 -0000",
290 "20041106T080907",
291 "2004-11-06T08:09:07",
292 "20041106T08:09:07" },
293
294 /* ISO GMT */
295 { "2004-11-06T08:09:07Z",
296
297 "Sat, 06 Nov 2004 08:09:07 GMT",
298 "Sat, 06-Nov-2004 08:09:07 GMT",
299 "Sat, 6 Nov 2004 08:09:07 +0000",
300 "20041106T080907Z",
301 "2004-11-06T08:09:07Z",
302 "20041106T08:09:07" },
303
304 /* ISO with positive offset */
305 { "2004-11-06T08:09:07+04:30",
306
307 "Sat, 06 Nov 2004 04:39:07 GMT",
308 "Sat, 06-Nov-2004 04:39:07 GMT",
309 "Sat, 6 Nov 2004 08:09:07 +0430",
310 "20041106T080907+0430",
311 "2004-11-06T08:09:07+04:30",
312 "20041106T08:09:07" },
313
314 /* ISO with negative offset */
315 { "2004-11-06T08:09:07-04:30",
316
317 "Sat, 06 Nov 2004 12:39:07 GMT",
318 "Sat, 06-Nov-2004 12:39:07 GMT",
319 "Sat, 6 Nov 2004 08:09:07 -0430",
320 "20041106T080907-0430",
321 "2004-11-06T08:09:07-04:30",
322 "20041106T08:09:07" },
323
324 /* ISO floating */
325 { "2004-11-06T08:09:07",
326
327 "Sat, 06 Nov 2004 08:09:07 GMT",
328 "Sat, 06-Nov-2004 08:09:07 GMT",
329 "Sat, 6 Nov 2004 08:09:07 -0000",
330 "20041106T080907",
331 "2004-11-06T08:09:07",
332 "20041106T08:09:07" }
333 };
334
335 static void
check_conversion(gconstpointer data)336 check_conversion (gconstpointer data)
337 {
338 const DateConversion *conv = data;
339 SoupDate *date;
340 char *str;
341
342 date = make_date (conv->source);
343 if (!date) {
344 soup_test_assert (FALSE, "date parsing failed for '%s'.", conv->source);
345 return;
346 }
347
348 str = soup_date_to_string (date, SOUP_DATE_HTTP);
349 g_assert_cmpstr (str, ==, conv->http);
350 g_free (str);
351
352 str = soup_date_to_string (date, SOUP_DATE_COOKIE);
353 g_assert_cmpstr (str, ==, conv->cookie);
354 g_free (str);
355
356 str = soup_date_to_string (date, SOUP_DATE_RFC2822);
357 g_assert_cmpstr (str, ==, conv->rfc2822);
358 g_free (str);
359
360 str = soup_date_to_string (date, SOUP_DATE_ISO8601_COMPACT);
361 g_assert_cmpstr (str, ==, conv->compact);
362 g_free (str);
363
364 str = soup_date_to_string (date, SOUP_DATE_ISO8601_FULL);
365 g_assert_cmpstr (str, ==, conv->full);
366 g_free (str);
367
368 str = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
369 g_assert_cmpstr (str, ==, conv->xmlrpc);
370 g_free (str);
371
372 soup_date_free (date);
373 }
374
375 int
main(int argc,char ** argv)376 main (int argc, char **argv)
377 {
378 int i, ret;
379 char *path;
380
381 test_init (argc, argv, NULL);
382
383 for (i = 0; i < G_N_ELEMENTS (good_dates); i++) {
384 path = g_strdup_printf ("/date/good/%s", good_dates[i].date);
385 g_test_add_data_func (path, &good_dates[i], check_good);
386 g_free (path);
387 }
388
389 for (i = 0; i < G_N_ELEMENTS (ok_dates); i++) {
390 path = g_strdup_printf ("/date/ok/%s", ok_dates[i].date);
391 g_test_add_data_func (path, &ok_dates[i], check_ok);
392 g_free (path);
393 }
394 g_test_add_func ("/date/ok/" TIME_T_STRING, check_ok_time_t);
395
396 for (i = 0; i < G_N_ELEMENTS (bad_dates); i++) {
397 path = g_strdup_printf ("/date/bad/%s", bad_dates[i].date);
398 g_test_add_data_func (path, &bad_dates[i], check_bad);
399 g_free (path);
400 }
401
402 for (i = 0; i < G_N_ELEMENTS (conversions); i++) {
403 path = g_strdup_printf ("/date/conversions/%s", conversions[i].source);
404 g_test_add_data_func (path, &conversions[i], check_conversion);
405 g_free (path);
406 }
407
408 ret = g_test_run ();
409
410 test_cleanup ();
411 return ret;
412 }
413