• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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