• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	/* ".." past top */
157 	{ "http://example.com/..", "http://example.com/", "785042",
158 	  { "http", NULL, NULL, "example.com", 80, "/", NULL, NULL } },
159 };
160 static int num_abs_tests = G_N_ELEMENTS(abs_tests);
161 
162 /* From RFC 3986. */
163 static const char *base = "http://a/b/c/d;p?q";
164 static struct {
165 	const char *uri_string, *result;
166 	const SoupURI bits;
167 } rel_tests[] = {
168 	{ "g:h", "g:h",
169 	  { "g", NULL, NULL, NULL, 0, "h", NULL, NULL } },
170 	{ "g", "http://a/b/c/g",
171 	  { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, NULL } },
172 	{ "./g", "http://a/b/c/g",
173 	  { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, NULL } },
174 	{ "g/", "http://a/b/c/g/",
175 	  { "http", NULL, NULL, "a", 80, "/b/c/g/", NULL, NULL } },
176 	{ "/g", "http://a/g",
177 	  { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
178 	{ "//g", "http://g/",
179 	  { "http", NULL, NULL, "g", 80, "/", NULL, NULL } },
180 	{ "?y", "http://a/b/c/d;p?y",
181 	  { "http", NULL, NULL, "a", 80, "/b/c/d;p", "y", NULL } },
182 	{ "g?y", "http://a/b/c/g?y",
183 	  { "http", NULL, NULL, "a", 80, "/b/c/g", "y", NULL } },
184 	{ "#s", "http://a/b/c/d;p?q#s",
185 	  { "http", NULL, NULL, "a", 80, "/b/c/d;p", "q", "s" } },
186 	{ "g#s", "http://a/b/c/g#s",
187 	  { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s" } },
188 	{ "g?y#s", "http://a/b/c/g?y#s",
189 	  { "http", NULL, NULL, "a", 80, "/b/c/g", "y", "s" } },
190 	{ ";x", "http://a/b/c/;x",
191 	  { "http", NULL, NULL, "a", 80, "/b/c/;x", NULL, NULL } },
192 	{ "g;x", "http://a/b/c/g;x",
193 	  { "http", NULL, NULL, "a", 80, "/b/c/g;x", NULL, NULL } },
194 	{ "g;x?y#s", "http://a/b/c/g;x?y#s",
195 	  { "http", NULL, NULL, "a", 80, "/b/c/g;x", "y", "s" } },
196 	{ ".", "http://a/b/c/",
197 	  { "http", NULL, NULL, "a", 80, "/b/c/", NULL, NULL } },
198 	{ "./", "http://a/b/c/",
199 	  { "http", NULL, NULL, "a", 80, "/b/c/", NULL, NULL } },
200 	{ "..", "http://a/b/",
201 	  { "http", NULL, NULL, "a", 80, "/b/", NULL, NULL } },
202 	{ "../", "http://a/b/",
203 	  { "http", NULL, NULL, "a", 80, "/b/", NULL, NULL } },
204 	{ "../g", "http://a/b/g",
205 	  { "http", NULL, NULL, "a", 80, "/b/g", NULL, NULL } },
206 	{ "../..", "http://a/",
207 	  { "http", NULL, NULL, "a", 80, "/", NULL, NULL } },
208 	{ "../../", "http://a/",
209 	  { "http", NULL, NULL, "a", 80, "/", NULL, NULL } },
210 	{ "../../g", "http://a/g",
211 	  { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
212 	{ "", "http://a/b/c/d;p?q",
213 	  { "http", NULL, NULL, "a", 80, "/b/c/d;p", "q", 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/g",
219 	  { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } },
220 	{ "/../g", "http://a/g",
221 	  { "http", NULL, NULL, "a", 80, "/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/c/g..",
227 	  { "http", NULL, NULL, "a", 80, "/b/c/g..", NULL, NULL } },
228 	{ "..g", "http://a/b/c/..g",
229 	  { "http", NULL, NULL, "a", 80, "/b/c/..g", NULL, NULL } },
230 	{ "./../g", "http://a/b/g",
231 	  { "http", NULL, NULL, "a", 80, "/b/g", NULL, NULL } },
232 	{ "./g/.", "http://a/b/c/g/",
233 	  { "http", NULL, NULL, "a", 80, "/b/c/g/", NULL, NULL } },
234 	{ "g/./h", "http://a/b/c/g/h",
235 	  { "http", NULL, NULL, "a", 80, "/b/c/g/h", NULL, NULL } },
236 	{ "g/../h", "http://a/b/c/h",
237 	  { "http", NULL, NULL, "a", 80, "/b/c/h", NULL, NULL } },
238 	{ "g;x=1/./y", "http://a/b/c/g;x=1/y",
239 	  { "http", NULL, NULL, "a", 80, "/b/c/g;x=1/y", NULL, NULL } },
240 	{ "g;x=1/../y", "http://a/b/c/y",
241 	  { "http", NULL, NULL, "a", 80, "/b/c/y", NULL, NULL } },
242 	{ "g?y/./x", "http://a/b/c/g?y/./x",
243 	  { "http", NULL, NULL, "a", 80, "/b/c/g", "y/./x", NULL } },
244 	{ "g?y/../x", "http://a/b/c/g?y/../x",
245 	  { "http", NULL, NULL, "a", 80, "/b/c/g", "y/../x", NULL } },
246 	{ "g#s/./x", "http://a/b/c/g#s/./x",
247 	  { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s/./x" } },
248 	{ "g#s/../x", "http://a/b/c/g#s/../x",
249 	  { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s/../x" } },
250 
251 	/* RFC 3986 notes that some old parsers will parse this as
252 	 * a relative URL ("http://a/b/c/g"), but it should be
253 	 * interpreted as absolute. libsoup should parse it
254 	 * correctly as being absolute, but then reject it since it's
255 	 * an http URL with no host.
256 	 */
257 	{ "http:g", NULL, { NULL } }
258 };
259 static int num_rel_tests = G_N_ELEMENTS(rel_tests);
260 
261 static struct {
262 	const char *one, *two, *bugref;
263 } eq_tests[] = {
264 	{ "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D", "628728" },
265 	{ "http://example.com", "http://example.com/", NULL },
266 	/* From RFC 2616 */
267 	{ "http://abc.com:80/~smith/home.html", "http://abc.com:80/~smith/home.html", NULL },
268 	{ "http://abc.com:80/~smith/home.html", "http://ABC.com/%7Esmith/home.html", NULL },
269 	{ "http://abc.com:80/~smith/home.html", "http://ABC.com:/%7esmith/home.html", NULL },
270 };
271 static int num_eq_tests = G_N_ELEMENTS(eq_tests);
272 
273 static void
do_uri(SoupURI * base_uri,const char * base_str,const char * in_uri,const char * out_uri,const SoupURI * bits)274 do_uri (SoupURI *base_uri, const char *base_str,
275 	const char *in_uri, const char *out_uri,
276 	const SoupURI *bits)
277 {
278 	SoupURI *uri;
279 	char *uri_string;
280 
281 	if (base_uri) {
282 		debug_printf (1, "<%s> + <%s> = <%s>\n", base_str, in_uri,
283 			      out_uri ? out_uri : "ERR");
284 		uri = soup_uri_new_with_base (base_uri, in_uri);
285 	} else {
286 		debug_printf (1, "<%s> => <%s>\n", in_uri,
287 			      out_uri ? out_uri : "ERR");
288 		uri = soup_uri_new (in_uri);
289 	}
290 
291 	if (!uri) {
292 		g_assert_null (out_uri);
293 		return;
294 	}
295 
296 	if (bits != NULL) {
297 		g_assert_cmpstr (uri->scheme, ==, bits->scheme);
298 		g_assert_cmpstr (uri->user, ==, bits->user);
299 		g_assert_cmpstr (uri->password, ==, bits->password);
300 		g_assert_cmpstr (uri->host, ==, bits->host);
301 		g_assert_cmpuint (uri->port, ==, bits->port);
302 		g_assert_cmpstr (uri->path, ==, bits->path);
303 		g_assert_cmpstr (uri->query, ==, bits->query);
304 		g_assert_cmpstr (uri->fragment, ==, bits->fragment);
305 	}
306 
307 	uri_string = soup_uri_to_string (uri, FALSE);
308 	soup_uri_free (uri);
309 
310 	g_assert_cmpstr (uri_string, ==, out_uri);
311 	g_free (uri_string);
312 }
313 
314 static void
do_absolute_uri_tests(void)315 do_absolute_uri_tests (void)
316 {
317 	int i;
318 
319 	for (i = 0; i < num_abs_tests; i++) {
320 		if (abs_tests[i].bugref)
321 			g_test_bug (abs_tests[i].bugref);
322 		do_uri (NULL, NULL, abs_tests[i].uri_string,
323 			abs_tests[i].result, &abs_tests[i].bits);
324 	}
325 }
326 
327 static void
do_relative_uri_tests(void)328 do_relative_uri_tests (void)
329 {
330 	SoupURI *base_uri;
331 	char *uri_string;
332 	int i;
333 
334 	base_uri = soup_uri_new (base);
335 	if (!base_uri) {
336 		g_printerr ("Could not parse %s!\n", base);
337 		exit (1);
338 	}
339 
340 	uri_string = soup_uri_to_string (base_uri, FALSE);
341 	g_assert_cmpstr (uri_string, ==, base);
342 	g_free (uri_string);
343 
344 	for (i = 0; i < num_rel_tests; i++) {
345 		do_uri (base_uri, base, rel_tests[i].uri_string,
346 			rel_tests[i].result, &rel_tests[i].bits);
347 	}
348 	soup_uri_free (base_uri);
349 }
350 
351 static void
do_equality_tests(void)352 do_equality_tests (void)
353 {
354 	SoupURI *uri1, *uri2;
355 	int i;
356 
357 	for (i = 0; i < num_eq_tests; i++) {
358 		if (eq_tests[i].bugref)
359 			g_test_bug (eq_tests[i].bugref);
360 
361 		uri1 = soup_uri_new (eq_tests[i].one);
362 		uri2 = soup_uri_new (eq_tests[i].two);
363 
364 		debug_printf (1, "<%s> == <%s>\n", eq_tests[i].one, eq_tests[i].two);
365 		g_assert_true (soup_uri_equal (uri1, uri2));
366 
367 		soup_uri_free (uri1);
368 		soup_uri_free (uri2);
369 	}
370 }
371 
372 static void
do_soup_uri_null_tests(void)373 do_soup_uri_null_tests (void)
374 {
375 	SoupURI *uri, *uri2;
376 	char *uri_string;
377 
378 	g_test_bug ("667637");
379 	g_test_bug ("670431");
380 
381 	uri = soup_uri_new (NULL);
382 	g_assert_false (SOUP_URI_IS_VALID (uri));
383 	g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
384 
385 	/* This implicitly also verifies that none of these methods g_warn */
386 	g_assert_null (soup_uri_get_scheme (uri));
387 	g_assert_null (soup_uri_get_user (uri));
388 	g_assert_null (soup_uri_get_password (uri));
389 	g_assert_null (soup_uri_get_host (uri));
390 	g_assert_cmpint (soup_uri_get_port (uri), ==, 0);
391 	g_assert_null (soup_uri_get_path (uri));
392 	g_assert_null (soup_uri_get_query (uri));
393 	g_assert_null (soup_uri_get_fragment (uri));
394 
395 	g_test_expect_message ("libsoup", G_LOG_LEVEL_CRITICAL,
396 			       "*base == NULL*");
397 	uri2 = soup_uri_new_with_base (uri, "/path");
398 	g_test_assert_expected_messages ();
399 	g_assert_null (uri2);
400 
401 	g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
402 			       "*SOUP_URI_IS_VALID*");
403 	uri_string = soup_uri_to_string (uri, FALSE);
404 	g_test_assert_expected_messages ();
405 	g_assert_cmpstr (uri_string, ==, "");
406 	g_free (uri_string);
407 
408 	soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
409 	g_assert_false (SOUP_URI_IS_VALID (uri));
410 	g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
411 
412 	g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
413 			       "*SOUP_URI_IS_VALID*");
414 	uri_string = soup_uri_to_string (uri, FALSE);
415 	g_test_assert_expected_messages ();
416 	g_assert_cmpstr (uri_string, ==, "http:");
417 	g_free (uri_string);
418 
419 	soup_uri_set_host (uri, "localhost");
420 	g_assert_false (SOUP_URI_IS_VALID (uri));
421 	g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri));
422 
423 	g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
424 			       "*SOUP_URI_IS_VALID*");
425 	uri_string = soup_uri_to_string (uri, FALSE);
426 	g_test_assert_expected_messages ();
427 	g_assert_cmpstr (uri_string, ==, "http://localhost/");
428 	g_free (uri_string);
429 
430 	g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
431 			       "*SOUP_URI_IS_VALID*");
432 	uri2 = soup_uri_new_with_base (uri, "/path");
433 	g_test_assert_expected_messages ();
434 	g_assert_true (uri2 != NULL);
435 
436 	if (uri2) {
437 		uri_string = soup_uri_to_string (uri2, FALSE);
438 		g_assert_cmpstr (uri_string, ==, "http://localhost/path");
439 		g_free (uri_string);
440 		soup_uri_free (uri2);
441 	}
442 
443 	g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING,
444 			       "*path != NULL*");
445 	soup_uri_set_path (uri, NULL);
446 	g_test_assert_expected_messages ();
447 	g_assert_cmpstr (uri->path, ==, "");
448 
449 	uri_string = soup_uri_to_string (uri, FALSE);
450 	g_assert_cmpstr (uri_string, ==, "http://localhost/");
451 	g_free (uri_string);
452 
453 	g_assert_true (SOUP_URI_IS_VALID (uri));
454 	g_assert_true (SOUP_URI_VALID_FOR_HTTP (uri));
455 
456 	soup_uri_free (uri);
457 }
458 
459 static struct {
460 	const char *uri_string, *unescape_extra, *result;
461 } normalization_tests[] = {
462 	{ "fo%6fbar",         NULL, "foobar" },
463 	{ "foo%2fbar",        NULL, "foo%2fbar" },
464 	{ "foo%2Fbar",        NULL, "foo%2Fbar" },
465 	{ "foo%2fbar",        "/",  "foo/bar" },
466 	{ "foo bar",          NULL, "foo%20bar" },
467 	{ "foo bar",          " ",  "foo bar" },
468 	{ "fo\xc3\xb6" "bar", NULL, "fo%C3%B6bar" },
469 	{ "fo\xc3\xb6 bar",   " ",  "fo%C3%B6 bar" },
470 	{ "%",                NULL, "%" },
471 };
472 static int num_normalization_tests = G_N_ELEMENTS (normalization_tests);
473 
474 static void
do_normalization_tests(void)475 do_normalization_tests (void)
476 {
477 	char *normalized;
478 	int i;
479 
480 	g_test_bug ("680018");
481 
482 	for (i = 0; i < num_normalization_tests; i++) {
483 		if (normalization_tests[i].unescape_extra) {
484 			debug_printf (1, "<%s> unescaping <%s> => <%s>\n",
485 				      normalization_tests[i].uri_string,
486 				      normalization_tests[i].unescape_extra,
487 				      normalization_tests[i].result);
488 		} else {
489 			debug_printf (1, "<%s> => <%s>\n",
490 				      normalization_tests[i].uri_string,
491 				      normalization_tests[i].result);
492 		}
493 
494 		normalized = soup_uri_normalize (normalization_tests[i].uri_string,
495 						 normalization_tests[i].unescape_extra);
496 		g_assert_cmpstr (normalized, ==, normalization_tests[i].result);
497 		g_free (normalized);
498 	}
499 }
500 
501 typedef struct {
502 	const char *uri;
503 	const char *mime_type;
504 	const char *body;
505 } DataURITest;
506 
507 static const DataURITest data_tests[] = {
508 	{ "data:text/plain,foo%20bar",
509 	  "text/plain",
510 	  "foo bar" },
511 	{ "data:text/plain;charset=utf-8,foo%20bar",
512 	  "text/plain;charset=utf-8",
513 	  "foo bar" },
514 	{ "data:text/plain;base64,Zm9vIGJhcg==",
515 	  "text/plain",
516 	  "foo bar" },
517 	{ "data:,foo%20bar",
518 	  "text/plain;charset=US-ASCII",
519 	  "foo bar" },
520 	{ "data:;base64,Zm9vIGJhcg==",
521 	  "text/plain;charset=US-ASCII",
522 	  "foo bar" },
523 	{ "data:,",
524 	  "text/plain;charset=US-ASCII",
525 	  "" },
526 	{ "data:text/plain,",
527 	  "text/plain",
528 	  "" }
529 };
530 
531 static void
do_data_tests(void)532 do_data_tests (void)
533 {
534 	SoupSession *session;
535 	SoupRequest *req;
536 	GInputStream *stream;
537 	char buf[128];
538 	gsize nread;
539 	int i;
540 	GError *error = NULL;
541 
542 	session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
543 	for (i = 0; i < G_N_ELEMENTS (data_tests); i++) {
544 		req = soup_session_request (session, data_tests[i].uri, &error);
545 		g_assert_no_error (error);
546 
547 		stream = soup_request_send (req, NULL, &error);
548 		g_assert_no_error (error);
549 
550 		g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error);
551 
552 		g_assert_no_error (error);
553 		g_assert_cmpint (nread, ==, strlen (data_tests[i].body));
554 		buf[nread] = 0;
555 		g_assert_cmpstr (buf, ==, data_tests[i].body);
556 
557 		g_assert_cmpstr (soup_request_get_content_type (req), ==, data_tests[i].mime_type);
558 
559 		g_input_stream_close (stream, NULL, &error);
560 		g_assert_no_error (error);
561 		g_object_unref (stream);
562 		g_object_unref (req);
563 	}
564 	soup_test_session_abort_unref (session);
565 }
566 
567 static void
test_uri_decode(void)568 test_uri_decode (void)
569 {
570 	gchar *decoded = soup_uri_decode ("%");
571 	g_assert_cmpstr (decoded, ==, "%");
572 	g_free (decoded);
573 }
574 
575 int
main(int argc,char ** argv)576 main (int argc, char **argv)
577 {
578 	int ret;
579 
580 	test_init (argc, argv, NULL);
581 
582 	g_test_add_func ("/uri/absolute", do_absolute_uri_tests);
583 	g_test_add_func ("/uri/relative", do_relative_uri_tests);
584 	g_test_add_func ("/uri/equality", do_equality_tests);
585 	g_test_add_func ("/uri/null", do_soup_uri_null_tests);
586 	g_test_add_func ("/uri/normalization", do_normalization_tests);
587 	g_test_add_func ("/uri/data", do_data_tests);
588 	g_test_add_func ("/uri/decode", test_uri_decode);
589 
590 	ret = g_test_run ();
591 
592 	test_cleanup ();
593 	return ret;
594 }
595