From 9a7e26f44feeccba050886f832dd5d23a9fa64fd Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 3 Feb 2012 14:19:28 +0000 Subject: [PATCH] uri-parsing test: verify that URIs are split correctly Testing the round-trip (split + reassemble) is necessary, but not sufficient: a large proportion of SoupURI's API is in terms of the separate parts, and this was never explicitly tested before. Bug: https://bugzilla.gnome.org/show_bug.cgi?id=667637 Signed-off-by: Simon McVittie --- tests/uri-parsing.c | 332 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 243 insertions(+), 89 deletions(-) diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index 285b41e..dd61c79 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -12,74 +12,119 @@ static struct { const char *uri_string, *result; + const SoupURI bits; } abs_tests[] = { - { "foo:", "foo:" }, - { "file:/dev/null", "file:/dev/null" }, - { "file:///dev/null", "file:///dev/null" }, - { "ftp://user@host/path", "ftp://user@host/path" }, - { "ftp://user@host:9999/path", "ftp://user@host:9999/path" }, - { "ftp://user:password@host/path", "ftp://user@host/path" }, - { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path" }, - { "ftp://user:password@host", "ftp://user@host" }, - { "http://us%65r@host", "http://user@host/" }, - { "http://us%40r@host", "http://us%40r@host/" }, - { "http://us%3ar@host", "http://us%3Ar@host/" }, - { "http://us%2fr@host", "http://us%2Fr@host/" }, - { "http://us%3fr@host", "http://us%3Fr@host/" }, - { "http://host?query", "http://host/?query" }, + { "foo:", "foo:", + { "foo", NULL, NULL, NULL, 0, "", NULL, NULL } }, + { "file:/dev/null", "file:/dev/null", + { "file", NULL, NULL, NULL, 0, "/dev/null", NULL, NULL } }, + { "file:///dev/null", "file:///dev/null", + { "file", NULL, NULL, "", 0, "/dev/null", NULL, NULL } }, + { "ftp://user@host/path", "ftp://user@host/path", + { "ftp", "user", NULL, "host", 21, "/path", NULL, NULL } }, + { "ftp://user@host:9999/path", "ftp://user@host:9999/path", + { "ftp", "user", NULL, "host", 9999, "/path", NULL, NULL } }, + { "ftp://user:password@host/path", "ftp://user@host/path", + { "ftp", "user", "password", "host", 21, "/path", NULL, NULL } }, + { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path", + { "ftp", "user", "password", "host", 9999, "/path", NULL, NULL } }, + { "ftp://user:password@host", "ftp://user@host", + { "ftp", "user", "password", "host", 21, "", NULL, NULL } }, + { "http://us%65r@host", "http://user@host/", + { "http", "user", NULL, "host", 80, "/", NULL, NULL } }, + { "http://us%40r@host", "http://us%40r@host/", + { "http", "us\x40r", NULL, "host", 80, "/", NULL, NULL } }, + { "http://us%3ar@host", "http://us%3Ar@host/", + { "http", "us\x3ar", NULL, "host", 80, "/", NULL, NULL } }, + { "http://us%2fr@host", "http://us%2Fr@host/", + { "http", "us\x2fr", NULL, "host", 80, "/", NULL, NULL } }, + { "http://us%3fr@host", "http://us%3Fr@host/", + { "http", "us\x3fr", NULL, "host", 80, "/", NULL, NULL } }, + { "http://host?query", "http://host/?query", + { "http", NULL, NULL, "host", 80, "/", "query", NULL } }, { "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", - "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value" }, + "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", + { "http", NULL, NULL, "host", 80, "/path", "query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", NULL } }, { "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", - "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"}, + "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", + { "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 } }, { "http://space/%20", - "http://space/%20" }, + "http://space/%20", + { "http", NULL, NULL, "space", 80, "/%20", NULL, NULL } }, { "http://delims/%3C%3E%23%25%22", - "http://delims/%3C%3E%23%25%22" }, + "http://delims/%3C%3E%23%25%22", + { "http", NULL, NULL, "delims", 80, "/%3C%3E%23%25%22", NULL, NULL } }, { "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", - "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60" }, + "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", + { "http", NULL, NULL, "unwise-chars", 80, "/%7B%7D%7C%5C%5E%5B%5D%60", NULL, NULL } }, /* From RFC 2732 */ { "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html", - "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html" }, + "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html", + { "http", NULL, NULL, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "/index.html", NULL, NULL } }, { "http://[1080:0:0:0:8:800:200C:417A]/index.html", - "http://[1080:0:0:0:8:800:200C:417A]/index.html" }, + "http://[1080:0:0:0:8:800:200C:417A]/index.html", + { "http", NULL, NULL, "1080:0:0:0:8:800:200C:417A", 80, "/index.html", NULL, NULL } }, { "http://[3ffe:2a00:100:7031::1]", - "http://[3ffe:2a00:100:7031::1]/" }, + "http://[3ffe:2a00:100:7031::1]/", + { "http", NULL, NULL, "3ffe:2a00:100:7031::1", 80, "/", NULL, NULL } }, { "http://[1080::8:800:200C:417A]/foo", - "http://[1080::8:800:200C:417A]/foo" }, + "http://[1080::8:800:200C:417A]/foo", + { "http", NULL, NULL, "1080::8:800:200C:417A", 80, "/foo", NULL, NULL } }, { "http://[::192.9.5.5]/ipng", - "http://[::192.9.5.5]/ipng" }, + "http://[::192.9.5.5]/ipng", + { "http", NULL, NULL, "::192.9.5.5", 80, "/ipng", NULL, NULL } }, { "http://[::FFFF:129.144.52.38]:80/index.html", - "http://[::FFFF:129.144.52.38]/index.html" }, + "http://[::FFFF:129.144.52.38]/index.html", + { "http", NULL, NULL, "::FFFF:129.144.52.38", 80, "/index.html", NULL, NULL } }, { "http://[2010:836B:4179::836B:4179]", - "http://[2010:836B:4179::836B:4179]/" }, + "http://[2010:836B:4179::836B:4179]/", + { "http", NULL, NULL, "2010:836B:4179::836B:4179", 80, "/", NULL, NULL } }, /* Try to recover certain kinds of invalid URIs */ { "http://host/path with spaces", - "http://host/path%20with%20spaces" }, - { " http://host/path", "http://host/path" }, - { "http://host/path ", "http://host/path" }, - { "http://host ", "http://host/" }, - { "http://host:999 ", "http://host:999/" }, - { "http://host/pa\nth", "http://host/path" }, - { "http:\r\n//host/path", "http://host/path" }, - { "http://\thost/path", "http://host/path" }, + "http://host/path%20with%20spaces", + { "http", NULL, NULL, "host", 80, "/path%20with%20spaces", NULL, NULL } }, + { " http://host/path", "http://host/path", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + { "http://host/path ", "http://host/path", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + { "http://host ", "http://host/", + { "http", NULL, NULL, "host", 80, "/", NULL, NULL } }, + { "http://host:999 ", "http://host:999/", + { "http", NULL, NULL, "host", 999, "/", NULL, NULL } }, + { "http://host/pa\nth", "http://host/path", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + { "http:\r\n//host/path", "http://host/path", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, + { "http://\thost/path", "http://host/path", + { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, /* Bug 594405; 0-length is different from not-present */ - { "http://host/path?", "http://host/path?" }, - { "http://host/path#", "http://host/path#" }, + { "http://host/path?", "http://host/path?", + { "http", NULL, NULL, "host", 80, "/path", "", NULL } }, + { "http://host/path#", "http://host/path#", + { "http", NULL, NULL, "host", 80, "/path", NULL, "" } }, /* Bug 590524; ignore badly-%-encoding */ - { "http://host/path%", "http://host/path%" }, - { "http://h%ost/path", "http://h%25ost/path" }, - { "http://host/path%%", "http://host/path%%" }, - { "http://host/path%%%", "http://host/path%%%" }, - { "http://host/path%/x/", "http://host/path%/x/" }, - { "http://host/path%0x/", "http://host/path%0x/" }, - { "http://host/path%ax", "http://host/path%ax" }, + { "http://host/path%", "http://host/path%", + { "http", NULL, NULL, "host", 80, "/path%", NULL, NULL } }, + { "http://h%ost/path", "http://h%25ost/path", + { "http", NULL, NULL, "h%ost", 80, "/path", NULL, NULL } }, + { "http://host/path%%", "http://host/path%%", + { "http", NULL, NULL, "host", 80, "/path%%", NULL, NULL } }, + { "http://host/path%%%", "http://host/path%%%", + { "http", NULL, NULL, "host", 80, "/path%%%", NULL, NULL } }, + { "http://host/path%/x/", "http://host/path%/x/", + { "http", NULL, NULL, "host", 80, "/path%/x/", NULL, NULL } }, + { "http://host/path%0x/", "http://host/path%0x/", + { "http", NULL, NULL, "host", 80, "/path%0x/", NULL, NULL } }, + { "http://host/path%ax", "http://host/path%ax", + { "http", NULL, NULL, "host", 80, "/path%ax", NULL, NULL } }, /* Bug 662806; %-encode non-ASCII characters */ - { "http://host/p\xc3\xa4th/", "http://host/p%C3%A4th/" } + { "http://host/p\xc3\xa4th/", "http://host/p%C3%A4th/", + { "http", NULL, NULL, "host", 80, "/p%C3%A4th/", NULL, NULL } }, }; static int num_abs_tests = G_N_ELEMENTS(abs_tests); @@ -87,48 +132,90 @@ static int num_abs_tests = G_N_ELEMENTS(abs_tests); static const char *base = "http://a/b/c/d;p?q"; static struct { const char *uri_string, *result; + const SoupURI bits; } rel_tests[] = { - { "g:h", "g:h" }, - { "g", "http://a/b/c/g" }, - { "./g", "http://a/b/c/g" }, - { "g/", "http://a/b/c/g/" }, - { "/g", "http://a/g" }, - { "//g", "http://g/" }, - { "?y", "http://a/b/c/d;p?y" }, - { "g?y", "http://a/b/c/g?y" }, - { "#s", "http://a/b/c/d;p?q#s" }, - { "g#s", "http://a/b/c/g#s" }, - { "g?y#s", "http://a/b/c/g?y#s" }, - { ";x", "http://a/b/c/;x" }, - { "g;x", "http://a/b/c/g;x" }, - { "g;x?y#s", "http://a/b/c/g;x?y#s" }, - { ".", "http://a/b/c/" }, - { "./", "http://a/b/c/" }, - { "..", "http://a/b/" }, - { "../", "http://a/b/" }, - { "../g", "http://a/b/g" }, - { "../..", "http://a/" }, - { "../../", "http://a/" }, - { "../../g", "http://a/g" }, - { "", "http://a/b/c/d;p?q" }, - { "../../../g", "http://a/g" }, - { "../../../../g", "http://a/g" }, - { "/./g", "http://a/g" }, - { "/../g", "http://a/g" }, - { "g.", "http://a/b/c/g." }, - { ".g", "http://a/b/c/.g" }, - { "g..", "http://a/b/c/g.." }, - { "..g", "http://a/b/c/..g" }, - { "./../g", "http://a/b/g" }, - { "./g/.", "http://a/b/c/g/" }, - { "g/./h", "http://a/b/c/g/h" }, - { "g/../h", "http://a/b/c/h" }, - { "g;x=1/./y", "http://a/b/c/g;x=1/y" }, - { "g;x=1/../y", "http://a/b/c/y" }, - { "g?y/./x", "http://a/b/c/g?y/./x" }, - { "g?y/../x", "http://a/b/c/g?y/../x" }, - { "g#s/./x", "http://a/b/c/g#s/./x" }, - { "g#s/../x", "http://a/b/c/g#s/../x" }, + { "g:h", "g:h", + { "g", NULL, NULL, NULL, 0, "h", NULL, NULL } }, + { "g", "http://a/b/c/g", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, NULL } }, + { "./g", "http://a/b/c/g", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, NULL } }, + { "g/", "http://a/b/c/g/", + { "http", NULL, NULL, "a", 80, "/b/c/g/", NULL, NULL } }, + { "/g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "//g", "http://g/", + { "http", NULL, NULL, "g", 80, "/", NULL, NULL } }, + { "?y", "http://a/b/c/d;p?y", + { "http", NULL, NULL, "a", 80, "/b/c/d;p", "y", NULL } }, + { "g?y", "http://a/b/c/g?y", + { "http", NULL, NULL, "a", 80, "/b/c/g", "y", NULL } }, + { "#s", "http://a/b/c/d;p?q#s", + { "http", NULL, NULL, "a", 80, "/b/c/d;p", "q", "s" } }, + { "g#s", "http://a/b/c/g#s", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s" } }, + { "g?y#s", "http://a/b/c/g?y#s", + { "http", NULL, NULL, "a", 80, "/b/c/g", "y", "s" } }, + { ";x", "http://a/b/c/;x", + { "http", NULL, NULL, "a", 80, "/b/c/;x", NULL, NULL } }, + { "g;x", "http://a/b/c/g;x", + { "http", NULL, NULL, "a", 80, "/b/c/g;x", NULL, NULL } }, + { "g;x?y#s", "http://a/b/c/g;x?y#s", + { "http", NULL, NULL, "a", 80, "/b/c/g;x", "y", "s" } }, + { ".", "http://a/b/c/", + { "http", NULL, NULL, "a", 80, "/b/c/", NULL, NULL } }, + { "./", "http://a/b/c/", + { "http", NULL, NULL, "a", 80, "/b/c/", NULL, NULL } }, + { "..", "http://a/b/", + { "http", NULL, NULL, "a", 80, "/b/", NULL, NULL } }, + { "../", "http://a/b/", + { "http", NULL, NULL, "a", 80, "/b/", NULL, NULL } }, + { "../g", "http://a/b/g", + { "http", NULL, NULL, "a", 80, "/b/g", NULL, NULL } }, + { "../..", "http://a/", + { "http", NULL, NULL, "a", 80, "/", NULL, NULL } }, + { "../../", "http://a/", + { "http", NULL, NULL, "a", 80, "/", NULL, NULL } }, + { "../../g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "", "http://a/b/c/d;p?q", + { "http", NULL, NULL, "a", 80, "/b/c/d;p", "q", NULL } }, + { "../../../g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "../../../../g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "/./g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "/../g", "http://a/g", + { "http", NULL, NULL, "a", 80, "/g", NULL, NULL } }, + { "g.", "http://a/b/c/g.", + { "http", NULL, NULL, "a", 80, "/b/c/g.", NULL, NULL } }, + { ".g", "http://a/b/c/.g", + { "http", NULL, NULL, "a", 80, "/b/c/.g", NULL, NULL } }, + { "g..", "http://a/b/c/g..", + { "http", NULL, NULL, "a", 80, "/b/c/g..", NULL, NULL } }, + { "..g", "http://a/b/c/..g", + { "http", NULL, NULL, "a", 80, "/b/c/..g", NULL, NULL } }, + { "./../g", "http://a/b/g", + { "http", NULL, NULL, "a", 80, "/b/g", NULL, NULL } }, + { "./g/.", "http://a/b/c/g/", + { "http", NULL, NULL, "a", 80, "/b/c/g/", NULL, NULL } }, + { "g/./h", "http://a/b/c/g/h", + { "http", NULL, NULL, "a", 80, "/b/c/g/h", NULL, NULL } }, + { "g/../h", "http://a/b/c/h", + { "http", NULL, NULL, "a", 80, "/b/c/h", NULL, NULL } }, + { "g;x=1/./y", "http://a/b/c/g;x=1/y", + { "http", NULL, NULL, "a", 80, "/b/c/g;x=1/y", NULL, NULL } }, + { "g;x=1/../y", "http://a/b/c/y", + { "http", NULL, NULL, "a", 80, "/b/c/y", NULL, NULL } }, + { "g?y/./x", "http://a/b/c/g?y/./x", + { "http", NULL, NULL, "a", 80, "/b/c/g", "y/./x", NULL } }, + { "g?y/../x", "http://a/b/c/g?y/../x", + { "http", NULL, NULL, "a", 80, "/b/c/g", "y/../x", NULL } }, + { "g#s/./x", "http://a/b/c/g#s/./x", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s/./x" } }, + { "g#s/../x", "http://a/b/c/g#s/../x", + { "http", NULL, NULL, "a", 80, "/b/c/g", NULL, "s/../x" } }, /* RFC 3986 notes that some old parsers will parse this as * a relative URL ("http://a/b/c/g"), but it should be @@ -136,7 +223,7 @@ static struct { * correctly as being absolute, but then reject it since it's * an http URL with no host. */ - { "http:g", NULL } + { "http:g", NULL, { NULL } } }; static int num_rel_tests = G_N_ELEMENTS(rel_tests); @@ -152,9 +239,42 @@ static struct { }; static int num_eq_tests = G_N_ELEMENTS(eq_tests); +#define test_cmpstr(a, b) _test_cmpstr (#a, #b, a, b) + +static gboolean +_test_cmpstr (const char *got_desc, + const char *exp_desc, + const char *got, + const char *expected) +{ + if (got == expected) + return TRUE; + + if (got == NULL) { + debug_printf (1, "ERR\n %s = NULL, expected %s = \"%s\"\n", + got_desc, exp_desc, expected); + return FALSE; + } + + if (expected == NULL) { + debug_printf (1, "ERR\n %s = \"%s\", expected %s = NULL\n", + got_desc, got, exp_desc); + return FALSE; + } + + if (strcmp (got, expected) != 0) { + debug_printf (1, "ERR\n %s = \"%s\", expected %s = \"%s\"\n", + got_desc, got, exp_desc, expected); + return FALSE; + } + + return TRUE; +} + static gboolean do_uri (SoupURI *base_uri, const char *base_str, - const char *in_uri, const char *out_uri) + const char *in_uri, const char *out_uri, + const SoupURI *bits) { SoupURI *uri; char *uri_string; @@ -179,6 +299,40 @@ do_uri (SoupURI *base_uri, const char *base_str, } } + if (bits != NULL) { + gboolean failed = FALSE; + + if (!test_cmpstr (uri->scheme, bits->scheme)) + failed = TRUE; + + if (!test_cmpstr (uri->user, bits->user)) + failed = TRUE; + + if (!test_cmpstr (uri->password, bits->password)) + failed = TRUE; + + if (!test_cmpstr (uri->host, bits->host)) + failed = TRUE; + + if (uri->port != bits->port) { + debug_printf (1, "ERR\n port was %u, expected %u\n", + uri->port, bits->port); + failed = TRUE; + } + + if (!test_cmpstr (uri->path, bits->path)) + failed = TRUE; + + if (!test_cmpstr (uri->query, bits->query)) + failed = TRUE; + + if (!test_cmpstr (uri->fragment, bits->fragment)) + failed = TRUE; + + if (failed) + return FALSE; + } + uri_string = soup_uri_to_string (uri, FALSE); soup_uri_free (uri); @@ -210,7 +364,7 @@ main (int argc, char **argv) debug_printf (1, "Absolute URI parsing\n"); for (i = 0; i < num_abs_tests; i++) { if (!do_uri (NULL, NULL, abs_tests[i].uri_string, - abs_tests[i].result)) + abs_tests[i].result, &abs_tests[i].bits)) errors++; } @@ -231,7 +385,7 @@ main (int argc, char **argv) for (i = 0; i < num_rel_tests; i++) { if (!do_uri (base_uri, base, rel_tests[i].uri_string, - rel_tests[i].result)) + rel_tests[i].result, &rel_tests[i].bits)) errors++; } soup_uri_free (base_uri); -- 2.7.4