add missing slash in %configure
[platform/upstream/libsoup.git] / tests / uri-parsing.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 #include "test-utils.h"
4
5 static struct {
6         const char *uri_string, *result, *bugref;
7         const SoupURI bits;
8 } abs_tests[] = {
9         { "foo:", "foo:", NULL,
10           { "foo", NULL, NULL, NULL, 0, "", NULL, NULL } },
11         { "file:/dev/null", "file:/dev/null", NULL,
12           { "file", NULL, NULL, NULL, 0, "/dev/null", NULL, NULL } },
13         { "file:///dev/null", "file:///dev/null", NULL,
14           { "file", NULL, NULL, "", 0, "/dev/null", NULL, NULL } },
15         { "ftp://user@host/path", "ftp://user@host/path", NULL,
16           { "ftp", "user", NULL, "host", 21, "/path", NULL, NULL } },
17         { "ftp://user@host:9999/path", "ftp://user@host:9999/path", NULL,
18           { "ftp", "user", NULL, "host", 9999, "/path", NULL, NULL } },
19         { "ftp://user:password@host/path", "ftp://user@host/path", NULL,
20           { "ftp", "user", "password", "host", 21, "/path", NULL, NULL } },
21         { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path", NULL,
22           { "ftp", "user", "password", "host", 9999, "/path", NULL, NULL } },
23         { "ftp://user:password@host", "ftp://user@host", NULL,
24           { "ftp", "user", "password", "host", 21, "", NULL, NULL } },
25         { "http://us%65r@host", "http://user@host/", NULL,
26           { "http", "user", NULL, "host", 80, "/", NULL, NULL } },
27         { "http://us%40r@host", "http://us%40r@host/", NULL,
28           { "http", "us\x40r", NULL, "host", 80, "/", NULL, NULL } },
29         { "http://us%3ar@host", "http://us%3Ar@host/", NULL,
30           { "http", "us\x3ar", NULL, "host", 80, "/", NULL, NULL } },
31         { "http://us%2fr@host", "http://us%2Fr@host/", NULL,
32           { "http", "us\x2fr", NULL, "host", 80, "/", NULL, NULL } },
33         { "http://us%3fr@host", "http://us%3Fr@host/", NULL,
34           { "http", "us\x3fr", NULL, "host", 80, "/", NULL, NULL } },
35         { "http://host?query", "http://host/?query", NULL,
36           { "http", NULL, NULL, "host", 80, "/", "query", NULL } },
37         { "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value",
38           "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value", NULL,
39           { "http", NULL, NULL, "host", 80, "/path", "query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue&param=value", NULL } },
40         { "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F",
41           "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", NULL,
42           { "http", NULL, NULL, "control-chars", 80, "/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", NULL, NULL } },
43         { "http://space/%20",
44           "http://space/%20", NULL,
45           { "http", NULL, NULL, "space", 80, "/%20", NULL, NULL } },
46         { "http://delims/%3C%3E%23%25%22",
47           "http://delims/%3C%3E%23%25%22", NULL,
48           { "http", NULL, NULL, "delims", 80, "/%3C%3E%23%25%22", NULL, NULL } },
49         { "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60",
50           "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", NULL,
51           { "http", NULL, NULL, "unwise-chars", 80, "/%7B%7D%7C%5C%5E%5B%5D%60", NULL, NULL } },
52
53         /* From RFC 2732 */
54         { "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html",
55           "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html", NULL,
56           { "http", NULL, NULL, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "/index.html", NULL, NULL } },
57         { "http://[1080:0:0:0:8:800:200C:417A]/index.html",
58           "http://[1080:0:0:0:8:800:200C:417A]/index.html", NULL,
59           { "http", NULL, NULL, "1080:0:0:0:8:800:200C:417A", 80, "/index.html", NULL, NULL } },
60         { "http://[3ffe:2a00:100:7031::1]",
61           "http://[3ffe:2a00:100:7031::1]/", NULL,
62           { "http", NULL, NULL, "3ffe:2a00:100:7031::1", 80, "/", NULL, NULL } },
63         { "http://[1080::8:800:200C:417A]/foo",
64           "http://[1080::8:800:200C:417A]/foo", NULL,
65           { "http", NULL, NULL, "1080::8:800:200C:417A", 80, "/foo", NULL, NULL } },
66         { "http://[::192.9.5.5]/ipng",
67           "http://[::192.9.5.5]/ipng", NULL,
68           { "http", NULL, NULL, "::192.9.5.5", 80, "/ipng", NULL, NULL } },
69         { "http://[::FFFF:129.144.52.38]:80/index.html",
70           "http://[::FFFF:129.144.52.38]/index.html", NULL,
71           { "http", NULL, NULL, "::FFFF:129.144.52.38", 80, "/index.html", NULL, NULL } },
72         { "http://[2010:836B:4179::836B:4179]",
73           "http://[2010:836B:4179::836B:4179]/", NULL,
74           { "http", NULL, NULL, "2010:836B:4179::836B:4179", 80, "/", NULL, NULL } },
75
76         /* Try to recover certain kinds of invalid URIs */
77         { "http://host/path with spaces",
78           "http://host/path%20with%20spaces", "566530",
79           { "http", NULL, NULL, "host", 80, "/path%20with%20spaces", NULL, NULL } },
80         { "  http://host/path", "http://host/path", "594405",
81           { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
82         { "http://host/path  ", "http://host/path", "594405",
83           { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
84         { "http://host  ", "http://host/", "594405",
85           { "http", NULL, NULL, "host", 80, "/", NULL, NULL } },
86         { "http://host:999  ", "http://host:999/", "594405",
87           { "http", NULL, NULL, "host", 999, "/", NULL, NULL } },
88         { "http://host/pa\nth", "http://host/path", "594405",
89           { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
90         { "http:\r\n//host/path", "http://host/path", "594405",
91           { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
92         { "http://\thost/path", "http://host/path", "594405",
93           { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } },
94
95         /* 0-length is different from not-present */
96         { "http://host/path?", "http://host/path?", "594405",
97           { "http", NULL, NULL, "host", 80, "/path", "", NULL } },
98         { "http://host/path#", "http://host/path#", "594405",
99           { "http", NULL, NULL, "host", 80, "/path", NULL, "" } },
100
101         /* ignore bad %-encoding */
102         { "http://host/path%", "http://host/path%", "590524",
103           { "http", NULL, NULL, "host", 80, "/path%", NULL, NULL } },
104         { "http://h%ost/path", "http://h%25ost/path", "590524",
105           { "http", NULL, NULL, "h%ost", 80, "/path", NULL, NULL } },
106         { "http://host/path%%", "http://host/path%%", "590524",
107           { "http", NULL, NULL, "host", 80, "/path%%", NULL, NULL } },
108         { "http://host/path%%%", "http://host/path%%%", "590524",
109           { "http", NULL, NULL, "host", 80, "/path%%%", NULL, NULL } },
110         { "http://host/path%/x/", "http://host/path%/x/", "590524",
111           { "http", NULL, NULL, "host", 80, "/path%/x/", NULL, NULL } },
112         { "http://host/path%0x/", "http://host/path%0x/", "590524",
113           { "http", NULL, NULL, "host", 80, "/path%0x/", NULL, NULL } },
114         { "http://host/path%ax", "http://host/path%ax", "590524",
115           { "http", NULL, NULL, "host", 80, "/path%ax", NULL, NULL } },
116
117         /* %-encode non-ASCII characters */
118         { "http://host/p\xc3\xa4th/", "http://host/p%C3%A4th/", "662806",
119           { "http", NULL, NULL, "host", 80, "/p%C3%A4th/", NULL, NULL } },
120
121         { "HTTP:////////////////", "http:////////////////", "667637",
122           { "http", NULL, NULL, "", 80, "//////////////", NULL, NULL } },
123
124         { "http://@host", "http://@host/", NULL,
125           { "http", "", NULL, "host", 80, "/", NULL, NULL } },
126         { "http://:@host", "http://@host/", NULL,
127           { "http", "", "", "host", 80, "/", NULL, NULL } },
128
129         { "http://host/keep%00nuls", "http://host/keep%00nuls", NULL,
130           { "http", NULL, NULL, "host", 80, "/keep%00nuls", NULL, NULL } },
131
132         /* scheme parsing */
133         { "foo0://host/path", "foo0://host/path", "703776",
134           { "foo0", NULL, NULL, "host", 0, "/path", NULL, NULL } },
135         { "f0.o://host/path", "f0.o://host/path", "703776",
136           { "f0.o", NULL, NULL, "host", 0, "/path", NULL, NULL } },
137         { "http++://host/path", "http++://host/path", "703776",
138           { "http++", NULL, NULL, "host", 0, "/path", NULL, NULL } },
139         { "http-ish://host/path", "http-ish://host/path", "703776",
140           { "http-ish", NULL, NULL, "host", 0, "/path", NULL, NULL } },
141         { "99http://host/path", NULL, "703776",
142           { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } },
143         { ".http://host/path", NULL, "703776",
144           { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } },
145         { "+http://host/path", NULL, "703776",
146           { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } },
147
148         /* IPv6 scope ID parsing (both correct and incorrect) */
149         { "http://[fe80::dead:beef%em1]/", "http://[fe80::dead:beef%25em1]/", NULL,
150           { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } },
151         { "http://[fe80::dead:beef%25em1]/", "http://[fe80::dead:beef%25em1]/", NULL,
152           { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } },
153         { "http://[fe80::dead:beef%10]/", "http://[fe80::dead:beef%2510]/", NULL,
154           { "http", NULL, NULL, "fe80::dead:beef%10", 80, "/", NULL, NULL } }
155 };
156 static int num_abs_tests = G_N_ELEMENTS(abs_tests);
157
158 /* From RFC 3986. */
159 static const char *base = "http://a/b/c/d;p?q";
160 static struct {
161         const char *uri_string, *result;
162         const SoupURI bits;
163 } rel_tests[] = {
164         { "g:h", "g:h",
165           { "g", NULL, NULL, NULL, 0, "h", NULL, NULL } },
166         { "g", "http://a/b/c/g",
167           { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, NULL } },
168         { "./g", "http://a/b/c/g",
169           { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, NULL } },
170         { "g/", "http://a/b/c/g/",
171           { "http", NULL, NULL, "a", 80, "/b/c/g/", NULL, NULL } },
172         { "/g", "http://a/g",
173           { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
174         { "//g", "http://g/",
175           { "http", NULL, NULL, "g", 80, "/", NULL, NULL } },
176         { "?y", "http://a/b/c/d;p?y",
177           { "http", NULL, NULL, "a", 80, "/b/c/d;p", "y", NULL } },
178         { "g?y", "http://a/b/c/g?y",
179           { "http", NULL, NULL, "a", 80, "/b/c/g", "y", NULL } },
180         { "#s", "http://a/b/c/d;p?q#s",
181           { "http", NULL, NULL, "a", 80, "/b/c/d;p", "q", "s" } },
182         { "g#s", "http://a/b/c/g#s",
183           { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s" } },
184         { "g?y#s", "http://a/b/c/g?y#s",
185           { "http", NULL, NULL, "a", 80, "/b/c/g", "y", "s" } },
186         { ";x", "http://a/b/c/;x",
187           { "http", NULL, NULL, "a", 80, "/b/c/;x", NULL, NULL } },
188         { "g;x", "http://a/b/c/g;x",
189           { "http", NULL, NULL, "a", 80, "/b/c/g;x", NULL, NULL } },
190         { "g;x?y#s", "http://a/b/c/g;x?y#s",
191           { "http", NULL, NULL, "a", 80, "/b/c/g;x", "y", "s" } },
192         { ".", "http://a/b/c/",
193           { "http", NULL, NULL, "a", 80, "/b/c/", NULL, NULL } },
194         { "./", "http://a/b/c/",
195           { "http", NULL, NULL, "a", 80, "/b/c/", NULL, NULL } },
196         { "..", "http://a/b/",
197           { "http", NULL, NULL, "a", 80, "/b/", NULL, NULL } },
198         { "../", "http://a/b/",
199           { "http", NULL, NULL, "a", 80, "/b/", NULL, NULL } },
200         { "../g", "http://a/b/g",
201           { "http", NULL, NULL, "a", 80, "/b/g", NULL, NULL } },
202         { "../..", "http://a/",
203           { "http", NULL, NULL, "a", 80, "/", NULL, NULL } },
204         { "../../", "http://a/",
205           { "http", NULL, NULL, "a", 80, "/", NULL, NULL } },
206         { "../../g", "http://a/g",
207           { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
208         { "", "http://a/b/c/d;p?q",
209           { "http", NULL, NULL, "a", 80, "/b/c/d;p", "q", NULL } },
210         { "../../../g", "http://a/g",
211           { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
212         { "../../../../g", "http://a/g",
213           { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
214         { "/./g", "http://a/g",
215           { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
216         { "/../g", "http://a/g",
217           { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
218         { "g.", "http://a/b/c/g.",
219           { "http", NULL, NULL, "a", 80, "/b/c/g.", NULL, NULL } },
220         { ".g", "http://a/b/c/.g",
221           { "http", NULL, NULL, "a", 80, "/b/c/.g", NULL, NULL } },
222         { "g..", "http://a/b/c/g..",
223           { "http", NULL, NULL, "a", 80, "/b/c/g..", NULL, NULL } },
224         { "..g", "http://a/b/c/..g",
225           { "http", NULL, NULL, "a", 80, "/b/c/..g", NULL, NULL } },
226         { "./../g", "http://a/b/g",
227           { "http", NULL, NULL, "a", 80, "/b/g", NULL, NULL } },
228         { "./g/.", "http://a/b/c/g/",
229           { "http", NULL, NULL, "a", 80, "/b/c/g/", NULL, NULL } },
230         { "g/./h", "http://a/b/c/g/h",
231           { "http", NULL, NULL, "a", 80, "/b/c/g/h", NULL, NULL } },
232         { "g/../h", "http://a/b/c/h",
233           { "http", NULL, NULL, "a", 80, "/b/c/h", NULL, NULL } },
234         { "g;x=1/./y", "http://a/b/c/g;x=1/y",
235           { "http", NULL, NULL, "a", 80, "/b/c/g;x=1/y", NULL, NULL } },
236         { "g;x=1/../y", "http://a/b/c/y",
237           { "http", NULL, NULL, "a", 80, "/b/c/y", NULL, NULL } },
238         { "g?y/./x", "http://a/b/c/g?y/./x",
239           { "http", NULL, NULL, "a", 80, "/b/c/g", "y/./x", NULL } },
240         { "g?y/../x", "http://a/b/c/g?y/../x",
241           { "http", NULL, NULL, "a", 80, "/b/c/g", "y/../x", NULL } },
242         { "g#s/./x", "http://a/b/c/g#s/./x",
243           { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s/./x" } },
244         { "g#s/../x", "http://a/b/c/g#s/../x",
245           { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s/../x" } },
246
247         /* RFC 3986 notes that some old parsers will parse this as
248          * a relative URL ("http://a/b/c/g"), but it should be
249          * interpreted as absolute. libsoup should parse it
250          * correctly as being absolute, but then reject it since it's
251          * an http URL with no host.
252          */
253         { "http:g", NULL, { NULL } }
254 };
255 static int num_rel_tests = G_N_ELEMENTS(rel_tests);
256
257 static struct {
258         const char *one, *two, *bugref;
259 } eq_tests[] = {
260         { "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D", "628728" },
261         { "http://example.com", "http://example.com/", NULL },
262         /* From RFC 2616 */
263         { "http://abc.com:80/~smith/home.html", "http://abc.com:80/~smith/home.html", NULL },
264         { "http://abc.com:80/~smith/home.html", "http://ABC.com/%7Esmith/home.html", NULL },
265         { "http://abc.com:80/~smith/home.html", "http://ABC.com:/%7esmith/home.html", NULL },
266 };
267 static int num_eq_tests = G_N_ELEMENTS(eq_tests);
268
269 static void
270 do_uri (SoupURI *base_uri, const char *base_str,
271         const char *in_uri, const char *out_uri,
272         const SoupURI *bits)
273 {
274         SoupURI *uri;
275         char *uri_string;
276
277         if (base_uri) {
278                 debug_printf (1, "<%s> + <%s> = <%s>\n", base_str, in_uri,
279                               out_uri ? out_uri : "ERR");
280                 uri = soup_uri_new_with_base (base_uri, in_uri);
281         } else {
282                 debug_printf (1, "<%s> => <%s>\n", in_uri,
283                               out_uri ? out_uri : "ERR");
284                 uri = soup_uri_new (in_uri);
285         }
286
287         if (!uri) {
288                 g_assert_null (out_uri);
289                 return;
290         }
291
292         if (bits != NULL) {
293                 g_assert_cmpstr (uri->scheme, ==, bits->scheme);
294                 g_assert_cmpstr (uri->user, ==, bits->user);
295                 g_assert_cmpstr (uri->password, ==, bits->password);
296                 g_assert_cmpstr (uri->host, ==, bits->host);
297                 g_assert_cmpuint (uri->port, ==, bits->port);
298                 g_assert_cmpstr (uri->path, ==, bits->path);
299                 g_assert_cmpstr (uri->query, ==, bits->query);
300                 g_assert_cmpstr (uri->fragment, ==, bits->fragment);
301         }
302
303         uri_string = soup_uri_to_string (uri, FALSE);
304         soup_uri_free (uri);
305
306         g_assert_cmpstr (uri_string, ==, out_uri);
307         g_free (uri_string);
308 }
309
310 static void
311 do_absolute_uri_tests (void)
312 {
313         int i;
314
315         for (i = 0; i < num_abs_tests; i++) {
316                 if (abs_tests[i].bugref)
317                         g_test_bug (abs_tests[i].bugref);
318                 do_uri (NULL, NULL, abs_tests[i].uri_string,
319                         abs_tests[i].result, &abs_tests[i].bits);
320         }
321 }
322
323 static void
324 do_relative_uri_tests (void)
325 {
326         SoupURI *base_uri;
327         char *uri_string;
328         int i;
329
330         base_uri = soup_uri_new (base);
331         if (!base_uri) {
332                 g_printerr ("Could not parse %s!\n", base);
333                 exit (1);
334         }
335
336         uri_string = soup_uri_to_string (base_uri, FALSE);
337         g_assert_cmpstr (uri_string, ==, base);
338         g_free (uri_string);
339
340         for (i = 0; i < num_rel_tests; i++) {
341                 do_uri (base_uri, base, rel_tests[i].uri_string,
342                         rel_tests[i].result, &rel_tests[i].bits);
343         }
344         soup_uri_free (base_uri);
345 }
346
347 static void
348 do_equality_tests (void)
349 {
350         SoupURI *uri1, *uri2;
351         int i;
352
353         for (i = 0; i < num_eq_tests; i++) {
354                 if (eq_tests[i].bugref)
355                         g_test_bug (eq_tests[i].bugref);
356
357                 uri1 = soup_uri_new (eq_tests[i].one);
358                 uri2 = soup_uri_new (eq_tests[i].two);
359
360                 debug_printf (1, "<%s> == <%s>\n", eq_tests[i].one, eq_tests[i].two);
361                 g_assert_true (soup_uri_equal (uri1, uri2));
362
363                 soup_uri_free (uri1);
364                 soup_uri_free (uri2);
365         }
366 }
367
368 static void
369 do_soup_uri_null_tests (void)
370 {
371         SoupURI *uri, *uri2;
372         char *uri_string;
373
374         g_test_bug ("667637");
375         g_test_bug ("670431");
376
377         uri = soup_uri_new (NULL);
378         g_assert_false (SOUP_URI_IS_VALID (uri));
379         g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
380
381         /* This implicitly also verifies that none of these methods g_warn */
382         g_assert_null (soup_uri_get_scheme (uri));
383         g_assert_null (soup_uri_get_user (uri));
384         g_assert_null (soup_uri_get_password (uri));
385         g_assert_null (soup_uri_get_host (uri));
386         g_assert_cmpint (soup_uri_get_port (uri), ==, 0);
387         g_assert_null (soup_uri_get_path (uri));
388         g_assert_null (soup_uri_get_query (uri));
389         g_assert_null (soup_uri_get_fragment (uri));
390
391         g_test_expect_message ("libsoup", G_LOG_LEVEL_CRITICAL,
392                                "*base == NULL*");
393         uri2 = soup_uri_new_with_base (uri, "/path");
394         g_test_assert_expected_messages ();
395         g_assert_null (uri2);
396
397         g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
398                                "*SOUP_URI_IS_VALID*");
399         uri_string = soup_uri_to_string (uri, FALSE);
400         g_test_assert_expected_messages ();
401         g_assert_cmpstr (uri_string, ==, "");
402         g_free (uri_string);
403
404         soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
405         g_assert_false (SOUP_URI_IS_VALID (uri));
406         g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
407
408         g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
409                                "*SOUP_URI_IS_VALID*");
410         uri_string = soup_uri_to_string (uri, FALSE);
411         g_test_assert_expected_messages ();
412         g_assert_cmpstr (uri_string, ==, "http:");
413         g_free (uri_string);
414
415         soup_uri_set_host (uri, "localhost");
416         g_assert_false (SOUP_URI_IS_VALID (uri));
417         g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
418
419         g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
420                                "*SOUP_URI_IS_VALID*");
421         uri_string = soup_uri_to_string (uri, FALSE);
422         g_test_assert_expected_messages ();
423         g_assert_cmpstr (uri_string, ==, "http://localhost/");
424         g_free (uri_string);
425
426         g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
427                                "*SOUP_URI_IS_VALID*");
428         uri2 = soup_uri_new_with_base (uri, "/path");
429         g_test_assert_expected_messages ();
430         g_assert_true (uri2 != NULL);
431
432         if (uri2) {
433                 uri_string = soup_uri_to_string (uri2, FALSE);
434                 g_assert_cmpstr (uri_string, ==, "http://localhost/path");
435                 g_free (uri_string);
436                 soup_uri_free (uri2);
437         }
438
439         g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
440                                "*path != NULL*");
441         soup_uri_set_path (uri, NULL);
442         g_test_assert_expected_messages ();
443         g_assert_cmpstr (uri->path, ==, "");
444
445         uri_string = soup_uri_to_string (uri, FALSE);
446         g_assert_cmpstr (uri_string, ==, "http://localhost/");
447         g_free (uri_string);
448
449         g_assert_true (SOUP_URI_IS_VALID (uri));
450         g_assert_true (SOUP_URI_VALID_FOR_HTTP (uri));
451
452         soup_uri_free (uri);
453 }
454
455 static struct {
456         const char *uri_string, *unescape_extra, *result;
457 } normalization_tests[] = {
458         { "fo%6fbar",         NULL, "foobar" },
459         { "foo%2fbar",        NULL, "foo%2fbar" },
460         { "foo%2Fbar",        NULL, "foo%2Fbar" },
461         { "foo%2fbar",        "/",  "foo/bar" },
462         { "foo bar",          NULL, "foo%20bar" },
463         { "foo bar",          " ",  "foo bar" },
464         { "fo\xc3\xb6" "bar", NULL, "fo%C3%B6bar" },
465         { "fo\xc3\xb6 bar",   " ",  "fo%C3%B6 bar" }
466 };
467 static int num_normalization_tests = G_N_ELEMENTS (normalization_tests);
468
469 static void
470 do_normalization_tests (void)
471 {
472         char *normalized;
473         int i;
474
475         g_test_bug ("680018");
476
477         for (i = 0; i < num_normalization_tests; i++) {
478                 if (normalization_tests[i].unescape_extra) {
479                         debug_printf (1, "<%s> unescaping <%s> => <%s>\n",
480                                       normalization_tests[i].uri_string,
481                                       normalization_tests[i].unescape_extra,
482                                       normalization_tests[i].result);
483                 } else {
484                         debug_printf (1, "<%s> => <%s>\n",
485                                       normalization_tests[i].uri_string,
486                                       normalization_tests[i].result);
487                 }
488
489                 normalized = soup_uri_normalize (normalization_tests[i].uri_string,
490                                                  normalization_tests[i].unescape_extra);
491                 g_assert_cmpstr (normalized, ==, normalization_tests[i].result);
492                 g_free (normalized);
493         }
494 }
495
496 int
497 main (int argc, char **argv)
498 {
499         int ret;
500
501         test_init (argc, argv, NULL);
502
503         g_test_add_func ("/uri/absolute", do_absolute_uri_tests);
504         g_test_add_func ("/uri/relative", do_relative_uri_tests);
505         g_test_add_func ("/uri/equality", do_equality_tests);
506         g_test_add_func ("/uri/null", do_soup_uri_null_tests);
507         g_test_add_func ("/uri/normalization", do_normalization_tests);
508
509         ret = g_test_run ();
510
511         test_cleanup ();
512         return ret;
513 }