summaryrefslogtreecommitdiffstats
path: root/tests/util/url
diff options
context:
space:
mode:
Diffstat (limited to 'tests/util/url')
-rw-r--r--tests/util/url/http.c752
-rw-r--r--tests/util/url/joinpath.c193
-rw-r--r--tests/util/url/parse.c805
-rw-r--r--tests/util/url/pattern.c103
-rw-r--r--tests/util/url/redirect.c146
-rw-r--r--tests/util/url/scp.c317
-rw-r--r--tests/util/url/valid.c17
7 files changed, 2333 insertions, 0 deletions
diff --git a/tests/util/url/http.c b/tests/util/url/http.c
new file mode 100644
index 0000000..8823889
--- /dev/null
+++ b/tests/util/url/http.c
@@ -0,0 +1,752 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+static git_net_url conndata;
+
+void test_url_http__initialize(void)
+{
+ memset(&conndata, 0, sizeof(conndata));
+}
+
+void test_url_http__cleanup(void)
+{
+ git_net_url_dispose(&conndata);
+}
+
+/* Hostname */
+
+void test_url_http__has_scheme(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "http://example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__no_scheme(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__hostname_root(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "example.com/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__hostname_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "example.com"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__hostname_numeric(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "8888888/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "8888888");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__hostname_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "example.com:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__hostname_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "example.com:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__hostname_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass%2fis%40bad@hostname.com:1234/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "hostname.com");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__hostname_user(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user@example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__hostname_user_pass(void)
+{
+ /* user:pass@hostname.tld/resource */
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__hostname_port(void)
+{
+ /* hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__hostname_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "example.com:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__hostname_user_port(void)
+{
+ /* user@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user@example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__hostname_user_pass_port(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__hostname_user_pass_port_query(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@example.com:9191/resource?query=q&foo=bar&z=asdf"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_s(conndata.query, "query=q&foo=bar&z=asdf");
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__hostname_user_pass_port_fragment(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@example.com:9191/resource#fragment"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_s(conndata.fragment, "fragment");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__hostname_user_pass_port_query_fragment(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@example.com:9191/resource?query=q&foo=bar&z=asdf#fragment"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_s(conndata.query, "query=q&foo=bar&z=asdf");
+ cl_assert_equal_s(conndata.fragment, "fragment");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__fragment_with_question_mark(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@example.com:9191/resource#fragment_with?question_mark"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_s(conndata.fragment, "fragment_with?question_mark");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+/* IPv4 addresses */
+
+void test_url_http__ipv4_trivial(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv4_root(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "192.168.1.1/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv4_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "192.168.1.1"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv4_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "192.168.1.1:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv4_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "192.168.1.1:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv4_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass%2fis%40bad@192.168.1.1:1234/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv4_user(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user@192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv4_user_pass(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv4_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv4_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "192.168.1.1:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv4_user_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user@192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv4_user_pass_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+/* IPv6 addresses */
+
+void test_url_http__ipv6_trivial(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv6_root(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "[fe80::dcad:beff:fe00:0001]/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv6_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "[fe80::dcad:beff:fe00:0001]"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv6_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "[fe80::dcad:beff:fe00:0001]:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv6_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "[fe80::dcad:beff:fe00:0001]:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv6_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001]:1234/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv6_user(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user@[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv6_user_pass(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv6_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv6_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "[fe80::dcad:beff:fe00:0001]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__ipv6_user_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user@[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv6_user_pass_port(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata,
+ "user:pass@[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_http__ipv6_invalid_addresses(void)
+{
+ /* Opening bracket missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001]/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001]"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001]:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001]:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass%2fis%40bad@fe80::dcad:beff:fe00:0001]:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user@fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass@fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001]:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user@fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass@fe80::dcad:beff:fe00:0001]:9191/resource"));
+
+ /* Closing bracket missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user@[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass@[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user@[fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass@[fe80::dcad:beff:fe00:0001:9191/resource"));
+
+ /* Both brackets missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass%2fis%40bad@fe80::dcad:beff:fe00:0001:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user@fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass@fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::dcad:beff:fe00:0001:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user@fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "user:pass@fe80::dcad:beff:fe00:0001:9191/resource"));
+
+ /* Invalid character inside address */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata, "[fe8o::dcad:beff:fe00:0001]/resource"));
+
+ /* Characters before/after braces */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "fe80::[dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "cafe[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_http(&conndata,
+ "[fe80::dcad:beff:fe00:0001]cafe/resource"));
+}
+
+/* Oddities */
+
+void test_url_http__invalid_scheme_is_relative(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "foo!bar://host:42/path/to/project?query_string=yes"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "foo!bar");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "//host:42/path/to/project");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_s(conndata.query, "query_string=yes");
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__scheme_case_is_normalized(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "GIT+SSH://host:42/path/to/project"));
+ cl_assert_equal_s(conndata.scheme, "git+ssh");
+}
+
+void test_url_http__no_scheme_relative_path(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "path"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "path");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__no_scheme_absolute_path(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "/path"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_p(conndata.host, NULL);
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/path");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__empty_path_with_empty_authority(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, ""));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_p(conndata.host, NULL);
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_http__spaces_in_the_name(void)
+{
+ cl_git_pass(git_net_url_parse_http(&conndata, "libgit2@dev.azure.com/libgit2/test/_git/spaces%20in%20the%20name"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "dev.azure.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/libgit2/test/_git/spaces%20in%20the%20name");
+ cl_assert_equal_s(conndata.username, "libgit2");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
diff --git a/tests/util/url/joinpath.c b/tests/util/url/joinpath.c
new file mode 100644
index 0000000..6027093
--- /dev/null
+++ b/tests/util/url/joinpath.c
@@ -0,0 +1,193 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+static git_net_url source, target;
+
+void test_url_joinpath__initialize(void)
+{
+ memset(&source, 0, sizeof(source));
+ memset(&target, 0, sizeof(target));
+}
+
+void test_url_joinpath__cleanup(void)
+{
+ git_net_url_dispose(&source);
+ git_net_url_dispose(&target);
+}
+
+void test_url_joinpath__target_paths_and_queries(void)
+{
+ cl_git_pass(git_net_url_parse(&source, "http://example.com/a/b"));
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/c/d"));
+ cl_assert_equal_s(target.path, "/a/b/c/d");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/c/d?foo"));
+ cl_assert_equal_s(target.path, "/a/b/c/d");
+ cl_assert_equal_s(target.query, "foo");
+ git_net_url_dispose(&target);
+}
+
+void test_url_joinpath__source_query_removed(void)
+{
+ cl_git_pass(git_net_url_parse(&source, "http://example.com/a/b?query&one&two"));
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/c/d"));
+ cl_assert_equal_s(target.path, "/a/b/c/d");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/c/d?foo"));
+ cl_assert_equal_s(target.path, "/a/b/c/d");
+ cl_assert_equal_s(target.query, "foo");
+ git_net_url_dispose(&target);
+}
+
+void test_url_joinpath__source_lacks_path(void)
+{
+ cl_git_pass(git_net_url_parse(&source, "http://example.com"));
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/"));
+ cl_assert_equal_s(target.path, "/");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, ""));
+ cl_assert_equal_s(target.path, "/");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "asdf"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar"));
+ cl_assert_equal_s(target.path, "/foo/bar");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "asdf?hello"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf?hello"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar?hello"));
+ cl_assert_equal_s(target.path, "/foo/bar");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+}
+
+void test_url_joinpath__source_is_slash(void)
+{
+ cl_git_pass(git_net_url_parse(&source, "http://example.com/"));
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/"));
+ cl_assert_equal_s(target.path, "/");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, ""));
+ cl_assert_equal_s(target.path, "/");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "asdf"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar"));
+ cl_assert_equal_s(target.path, "/foo/bar");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "asdf?hello"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf?hello"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar?hello"));
+ cl_assert_equal_s(target.path, "/foo/bar");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+}
+
+
+void test_url_joinpath__source_has_query(void)
+{
+ cl_git_pass(git_net_url_parse(&source, "http://example.com?query"));
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/"));
+ cl_assert_equal_s(target.path, "/");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, ""));
+ cl_assert_equal_s(target.path, "/");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "asdf"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar"));
+ cl_assert_equal_s(target.path, "/foo/bar");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "asdf?hello"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/asdf?hello"));
+ cl_assert_equal_s(target.path, "/asdf");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/foo/bar?hello"));
+ cl_assert_equal_s(target.path, "/foo/bar");
+ cl_assert_equal_s(target.query, "hello");
+ git_net_url_dispose(&target);
+}
+
+
+void test_url_joinpath__empty_query_ignored(void)
+{
+ cl_git_pass(git_net_url_parse(&source, "http://example.com/foo"));
+
+ cl_git_pass(git_net_url_joinpath(&target, &source, "/bar/baz?"));
+ cl_assert_equal_s(target.path, "/foo/bar/baz");
+ cl_assert_equal_p(target.query, NULL);
+ git_net_url_dispose(&target);
+}
diff --git a/tests/util/url/parse.c b/tests/util/url/parse.c
new file mode 100644
index 0000000..35486f7
--- /dev/null
+++ b/tests/util/url/parse.c
@@ -0,0 +1,805 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+static git_net_url conndata;
+
+void test_url_parse__initialize(void)
+{
+ memset(&conndata, 0, sizeof(conndata));
+}
+
+void test_url_parse__cleanup(void)
+{
+ git_net_url_dispose(&conndata);
+}
+
+/* Hostname */
+
+void test_url_parse__hostname_trivial(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__hostname_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__hostname_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__hostname_numeric(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://8888888/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "8888888");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__hostname_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__hostname_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__hostname_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@hostname.com:1234/"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "hostname.com");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__hostname_user(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__hostname_user_pass(void)
+{
+ /* user:pass@hostname.tld/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__hostname_port(void)
+{
+ /* hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__hostname_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://example.com:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__hostname_user_port(void)
+{
+ /* user@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__hostname_user_pass_port(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@example.com:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__hostname_user_pass_port_query(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@example.com:9191/resource?query=q&foo=bar&z=asdf"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_s(conndata.query, "query=q&foo=bar&z=asdf");
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__hostname_user_pass_port_fragment(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@example.com:9191/resource#fragment"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_s(conndata.fragment, "fragment");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__hostname_user_pass_port_query_fragment(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@example.com:9191/resource?query=q&foo=bar&z=asdf#fragment"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_s(conndata.query, "query=q&foo=bar&z=asdf");
+ cl_assert_equal_s(conndata.fragment, "fragment");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__fragment_with_question_mark(void)
+{
+ /* user:pass@hostname.tld:port/resource */
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@example.com:9191/resource#fragment_with?question_mark"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_s(conndata.fragment, "fragment_with?question_mark");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+/* IPv4 addresses */
+
+void test_url_parse__ipv4_trivial(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv4_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv4_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv4_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv4_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv4_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@192.168.1.1:1234/"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv4_user(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv4_user_pass(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@192.168.1.1/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv4_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv4_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv4_user_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv4_user_pass_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@192.168.1.1:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "192.168.1.1");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+/* IPv6 addresses */
+
+void test_url_parse__ipv6_trivial(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv6_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]/"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv6_implied_root(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv6_implied_root_custom_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:42"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv6_implied_root_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv6_encoded_password(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001]:1234/"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "1234");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass/is@bad");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv6_user(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv6_user_pass(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv6_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv6_empty_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__ipv6_user_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user@[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv6_user_pass_port(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user:pass@[fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "fe80::dcad:beff:fe00:0001");
+ cl_assert_equal_s(conndata.port, "9191");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "user");
+ cl_assert_equal_s(conndata.password, "pass");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ipv6_invalid_addresses(void)
+{
+ /* Opening bracket missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@fe80::dcad:beff:fe00:0001]:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001]:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@fe80::dcad:beff:fe00:0001]:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@fe80::dcad:beff:fe00:0001]:9191/resource"));
+
+ /* Closing bracket missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@[fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://[fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@[fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@[fe80::dcad:beff:fe00:0001:9191/resource"));
+
+ /* Both brackets missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001:42"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass%2fis%40bad@fe80::dcad:beff:fe00:0001:1234/"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@fe80::dcad:beff:fe00:0001/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::dcad:beff:fe00:0001:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user@fe80::dcad:beff:fe00:0001:9191/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "https://user:pass@fe80::dcad:beff:fe00:0001:9191/resource"));
+
+ /* Invalid character inside address */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata, "http://[fe8o::dcad:beff:fe00:0001]/resource"));
+
+ /* Characters before/after braces */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://fe80::[dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://cafe[fe80::dcad:beff:fe00:0001]/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
+ "http://[fe80::dcad:beff:fe00:0001]cafe/resource"));
+}
+
+/* Oddities */
+
+void test_url_parse__empty_scheme(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "://example.com/resource"));
+ cl_assert_equal_s(conndata.scheme, NULL);
+ cl_assert_equal_s(conndata.host, NULL);
+ cl_assert_equal_s(conndata.port, NULL);
+ cl_assert_equal_s(conndata.path, "//example.com/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_p(conndata.query, NULL);
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__invalid_scheme_is_relative(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "foo!bar://host:42/path/to/project?query_string=yes"));
+ cl_assert_equal_p(conndata.scheme, NULL);
+ cl_assert_equal_p(conndata.host, NULL);
+ cl_assert_equal_p(conndata.port, NULL);
+ cl_assert_equal_s(conndata.path, "foo!bar://host:42/path/to/project");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_s(conndata.query, "query_string=yes");
+ cl_assert_equal_p(conndata.fragment, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__scheme_case_is_normalized(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "GIT+SSH://host:42/path/to/project"));
+ cl_assert_equal_s(conndata.scheme, "git+ssh");
+}
+
+void test_url_parse__nonhierarchical_scheme(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "mailto:foobar@example.com"));
+ cl_assert_equal_s(conndata.scheme, "mailto");
+ cl_assert_equal_p(conndata.host, NULL);
+ cl_assert_equal_p(conndata.port, NULL);
+ cl_assert_equal_s(conndata.path, "foobar@example.com");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__no_scheme_relative_path(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "path"));
+ cl_assert_equal_p(conndata.scheme, NULL);
+ cl_assert_equal_p(conndata.host, NULL);
+ cl_assert_equal_p(conndata.port, NULL);
+ cl_assert_equal_s(conndata.path, "path");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__no_scheme_absolute_path(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "/path"));
+ cl_assert_equal_p(conndata.scheme, NULL);
+ cl_assert_equal_p(conndata.host, NULL);
+ cl_assert_equal_p(conndata.port, NULL);
+ cl_assert_equal_s(conndata.path, "/path");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__empty_path(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "mailto:"));
+ cl_assert_equal_s(conndata.scheme, "mailto");
+ cl_assert_equal_p(conndata.host, NULL);
+ cl_assert_equal_p(conndata.port, NULL);
+ cl_assert_equal_s(conndata.path, NULL);
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__empty_path_with_empty_authority(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "http://"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_p(conndata.host, NULL);
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_parse__http_follows_the_rfc(void)
+{
+ cl_git_fail(git_net_url_parse(&conndata, "https://my.email.address@gmail.com@source.developers.google.com:4433/p/my-project/r/my-repository"));
+}
+
+void test_url_parse__ssh_from_terrible_google_rfc_violating_products(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "ssh://my.email.address@gmail.com@source.developers.google.com:2022/p/my-project/r/my-repository"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "source.developers.google.com");
+ cl_assert_equal_s(conndata.port, "2022");
+ cl_assert_equal_s(conndata.path, "/p/my-project/r/my-repository");
+ cl_assert_equal_s(conndata.username, "my.email.address@gmail.com");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__ssh_with_password_from_terrible_google_rfc_violating_products(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "ssh://my.email.address@gmail.com:seekret@source.developers.google.com:2022/p/my-project/r/my-repository"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "source.developers.google.com");
+ cl_assert_equal_s(conndata.port, "2022");
+ cl_assert_equal_s(conndata.path, "/p/my-project/r/my-repository");
+ cl_assert_equal_s(conndata.username, "my.email.address@gmail.com");
+ cl_assert_equal_s(conndata.password, "seekret");
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_parse__spaces_in_the_name(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata, "https://libgit2@dev.azure.com/libgit2/test/_git/spaces%20in%20the%20name"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "dev.azure.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/libgit2/test/_git/spaces%20in%20the%20name");
+ cl_assert_equal_s(conndata.username, "libgit2");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
diff --git a/tests/util/url/pattern.c b/tests/util/url/pattern.c
new file mode 100644
index 0000000..f183d7f
--- /dev/null
+++ b/tests/util/url/pattern.c
@@ -0,0 +1,103 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+struct url_pattern {
+ const char *url;
+ const char *pattern;
+ bool matches;
+};
+
+void test_url_pattern__single(void)
+{
+ git_net_url url;
+ size_t i;
+
+ struct url_pattern url_patterns[] = {
+ /* Wildcard matches */
+ { "https://example.com/", "", false },
+ { "https://example.com/", "*", true },
+
+ /* Literal and wildcard matches */
+ { "https://example.com/", "example.com", true },
+ { "https://example.com/", ".example.com", true },
+ { "https://example.com/", "*.example.com", true },
+ { "https://www.example.com/", "www.example.com", true },
+ { "https://www.example.com/", ".example.com", true },
+ { "https://www.example.com/", "*.example.com", true },
+
+ /* Literal and wildcard failures */
+ { "https://example.com/", "example.org", false },
+ { "https://example.com/", ".example.org", false },
+ { "https://example.com/", "*.example.org", false },
+ { "https://foo.example.com/", "www.example.com", false },
+
+ /*
+ * A port in the pattern is optional; if no port is
+ * present, it matches *all* ports.
+ */
+ { "https://example.com/", "example.com:443", true },
+ { "https://example.com/", "example.com:80", false },
+ { "https://example.com:1443/", "example.com", true },
+
+ /* Failures with similar prefix/suffix */
+ { "https://texample.com/", "example.com", false },
+ { "https://example.com/", "mexample.com", false },
+ { "https://example.com:44/", "example.com:443", false },
+ { "https://example.com:443/", "example.com:44", false },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(url_patterns); i++) {
+ cl_git_pass(git_net_url_parse(&url, url_patterns[i].url));
+ cl_assert_(git_net_url_matches_pattern(&url, url_patterns[i].pattern) == url_patterns[i].matches, url_patterns[i].pattern);
+ git_net_url_dispose(&url);
+ }
+}
+
+void test_url_pattern__list(void)
+{
+ git_net_url url;
+ size_t i;
+
+ struct url_pattern url_patterns[] = {
+ /* Wildcard matches */
+ { "https://example.com/", "", false },
+ { "https://example.com/", "*", true },
+ { "https://example.com/", ",example.com,", true },
+ { "https://example.com/", "foo,,example.com,,bar", true },
+ { "https://example.com/", "foo,,zzz,,*,,bar", true },
+
+ /* Literals */
+ { "https://example.com/", "example.com", true },
+ { "https://example.com/", "foo.bar,example.com", true },
+ { "https://example.com/", "foo.bar", false },
+ { "https://example.com/", "foo.bar,example.org", false },
+ { "https://www.example.com/", "foo.example.com,www.example.com,bar.example.com", true },
+ { "https://www.example.com/", "foo.example.com,baz.example.com,bar.example.com", false },
+ { "https://foo.example.com/", "www.example.com", false },
+ { "https://foo.example.com/", "bar.example.com,www.example.com,", false },
+
+ /* Wildcards */
+ { "https://example.com/", ".example.com", true },
+ { "https://example.com/", "*.example.com", true },
+ { "https://example.com/", "foo.com,bar.com,.example.com", true },
+ { "https://example.com/", ".foo.com,.bar.com,.example.com", true },
+ { "https://example.com/", ".foo.com,.bar.com,asdf.com", false },
+ { "https://example.com/", "*.foo,*.bar,*.example.com,*.asdf", true },
+ { "https://example.com/", "*.foo,*.bar,*.asdf", false },
+
+
+ /* Ports! */
+ { "https://example.com/", "example.com:443", true },
+ { "https://example.com/", "example.com:42,example.com:443,example.com:99", true },
+ { "https://example.com/", "example.com:42,example.com:80,example.org:443", false },
+ { "https://example.com:1443/", "example.com", true },
+ { "https://example.com:44/", "example.com:443", false },
+ { "https://example.com:443/", "example.com:44", false },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(url_patterns); i++) {
+ cl_git_pass(git_net_url_parse(&url, url_patterns[i].url));
+ cl_assert_(git_net_url_matches_pattern_list(&url, url_patterns[i].pattern) == url_patterns[i].matches, url_patterns[i].pattern);
+ git_net_url_dispose(&url);
+ }
+}
diff --git a/tests/util/url/redirect.c b/tests/util/url/redirect.c
new file mode 100644
index 0000000..a6f99dc
--- /dev/null
+++ b/tests/util/url/redirect.c
@@ -0,0 +1,146 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+static git_net_url conndata;
+
+void test_url_redirect__initialize(void)
+{
+ memset(&conndata, 0, sizeof(conndata));
+}
+
+void test_url_redirect__cleanup(void)
+{
+ git_net_url_dispose(&conndata);
+}
+
+void test_url_redirect__redirect_http(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "http://example.com/foo/bar/baz"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "http://example.com/foo/bar/baz", false, "bar/baz"));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/foo/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+}
+
+void test_url_redirect__redirect_ssl(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://example.com/foo/bar/baz"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "https://example.com/foo/bar/baz", false, "bar/baz"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/foo/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+}
+
+void test_url_redirect__redirect_leaves_root_path(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://example.com/foo/bar/baz"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "https://example.com/foo/bar/baz", false, "/foo/bar/baz"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+}
+
+void test_url_redirect__redirect_encoded_username_password(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz", false, "bar/baz"));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/foo/");
+ cl_assert_equal_s(conndata.username, "user/name");
+ cl_assert_equal_s(conndata.password, "pass@word%zyx%v");
+}
+
+void test_url_redirect__redirect_cross_host_allowed(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://bar.com/bar/baz"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "https://foo.com/bar/baz", true, NULL));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "foo.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/bar/baz");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+}
+
+void test_url_redirect__redirect_cross_host_denied(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://bar.com/bar/baz"));
+ cl_git_fail_with(git_net_url_apply_redirect(&conndata,
+ "https://foo.com/bar/baz", false, NULL), -1);
+}
+
+void test_url_redirect__redirect_http_downgrade_denied(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://foo.com/bar/baz"));
+ cl_git_fail_with(git_net_url_apply_redirect(&conndata,
+ "http://foo.com/bar/baz", true, NULL), -1);
+}
+
+void test_url_redirect__redirect_relative(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "http://foo.com/bar/baz/biff"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "/zap/baz/biff?bam", true, NULL));
+ cl_assert_equal_s(conndata.scheme, "http");
+ cl_assert_equal_s(conndata.host, "foo.com");
+ cl_assert_equal_s(conndata.port, "80");
+ cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+}
+
+void test_url_redirect__redirect_relative_ssl(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://foo.com/bar/baz/biff"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "/zap/baz/biff?bam", true, NULL));
+ cl_assert_equal_s(conndata.scheme, "https");
+ cl_assert_equal_s(conndata.host, "foo.com");
+ cl_assert_equal_s(conndata.port, "443");
+ cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+}
+
+void test_url_redirect__service_query_no_query_params_in_location(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://foo.com/bar/info/refs?service=git-upload-pack"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "/baz/info/refs", true, "/info/refs?service=git-upload-pack"));
+ cl_assert_equal_s(conndata.path, "/baz");
+}
+
+void test_url_redirect__service_query_with_query_params_in_location(void)
+{
+ cl_git_pass(git_net_url_parse(&conndata,
+ "https://foo.com/bar/info/refs?service=git-upload-pack"));
+ cl_git_pass(git_net_url_apply_redirect(&conndata,
+ "/baz/info/refs?service=git-upload-pack", true, "/info/refs?service=git-upload-pack"));
+ cl_assert_equal_s(conndata.path, "/baz");
+}
diff --git a/tests/util/url/scp.c b/tests/util/url/scp.c
new file mode 100644
index 0000000..0e0dce1
--- /dev/null
+++ b/tests/util/url/scp.c
@@ -0,0 +1,317 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+static git_net_url conndata;
+
+void test_url_scp__initialize(void)
+{
+ memset(&conndata, 0, sizeof(conndata));
+}
+
+void test_url_scp__cleanup(void)
+{
+ git_net_url_dispose(&conndata);
+}
+
+/* Hostname */
+
+void test_url_scp__hostname_trivial(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "example.com:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__hostname_bracketed(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[example.com]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__hostname_root(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "example.com:/"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__hostname_user(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "git@example.com:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "git");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__hostname_user_bracketed(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[git@example.com]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "git");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__hostname_port(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[example.com:42]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_scp__hostname_user_port(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[git@example.com:42]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "example.com");
+ cl_assert_equal_s(conndata.port, "42");
+ cl_assert_equal_s(conndata.path, "/resource");
+ cl_assert_equal_s(conndata.username, "git");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_scp__ipv4_trivial(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "192.168.99.88:/resource/a/b/c"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "192.168.99.88");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__ipv4_bracketed(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[192.168.99.88]:/resource/a/b/c"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "192.168.99.88");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__ipv4_user(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "git@192.168.99.88:/resource/a/b/c"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "192.168.99.88");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+ cl_assert_equal_s(conndata.username, "git");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__ipv4_port(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[192.168.99.88:1111]:/resource/a/b/c"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "192.168.99.88");
+ cl_assert_equal_s(conndata.port, "1111");
+ cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_scp__ipv4_user_port(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[git@192.168.99.88:1111]:/resource/a/b/c"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "192.168.99.88");
+ cl_assert_equal_s(conndata.port, "1111");
+ cl_assert_equal_s(conndata.path, "/resource/a/b/c");
+ cl_assert_equal_s(conndata.username, "git");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_scp__ipv6_trivial(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[fe80::dcad:beff:fe00:0001]:/resource/foo"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource/foo");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__ipv6_user(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "git@[fe80::dcad:beff:fe00:0001]:/resource/foo"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource/foo");
+ cl_assert_equal_s(conndata.username, "git");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__ipv6_port(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[[fe80::dcad:beff:fe00:0001]:99]:/resource/foo"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+ cl_assert_equal_s(conndata.port, "99");
+ cl_assert_equal_s(conndata.path, "/resource/foo");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_scp__ipv6_user_port(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[git@[fe80::dcad:beff:fe00:0001]:99]:/resource/foo"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+ cl_assert_equal_s(conndata.port, "99");
+ cl_assert_equal_s(conndata.path, "/resource/foo");
+ cl_assert_equal_s(conndata.username, "git");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
+}
+
+void test_url_scp__hexhost_and_port(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[fe:22]:/resource/foo"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "fe");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "/resource/foo");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__malformed_ipv6_one(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "fe80::dcad:beff:fe00:0001]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "fe80");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, ":dcad:beff:fe00:0001]:/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__malformed_ipv6_two(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "[fe80::dcad:beff:fe00:0001]:42]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "42]:/resource");
+ cl_assert_equal_p(conndata.username, NULL);
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__malformed_ipv6_with_user(void)
+{
+ cl_git_pass(git_net_url_parse_scp(&conndata, "git@[fe80::dcad:beff:fe00:0001]:42]:/resource"));
+ cl_assert_equal_s(conndata.scheme, "ssh");
+ cl_assert_equal_s(conndata.host, "[fe80::dcad:beff:fe00:0001]");
+ cl_assert_equal_s(conndata.port, "22");
+ cl_assert_equal_s(conndata.path, "42]:/resource");
+ cl_assert_equal_s(conndata.username, "git");
+ cl_assert_equal_p(conndata.password, NULL);
+ cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
+}
+
+void test_url_scp__invalid_addresses(void)
+{
+ /* Path is required */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "example.com"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "example.com:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[example.com:42]:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[git@example.com:42]:"));
+
+ /* Host is required */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ ":"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ ":foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "git@:foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[]:"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "git@[]:"));
+
+ /* User is required if specified */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "@example.com:foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "@:foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[@localhost:22]:foo"));
+
+ /* Port is required in brackets */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[example.com:]:foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[git@example.com:]:foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[fe:]:foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[@localhost]:foo"));
+
+ /* Extra brackets are disallowed */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[git@[[fe80::dcad:beff:fe00:0001]]:42]:foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[[git@[fe80::dcad:beff:fe00:0001]]:42]:foo"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[[git@[fe80::dcad:beff:fe00:0001]:42]]:foo"));
+
+ /* Closing bracket missing */
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[fe80::dcad:beff:fe00:0001:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[[fe80::dcad:beff:fe00:0001]:42:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[git@[fe80::dcad:beff:fe00:0001]:42:/resource"));
+ cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse_scp(&conndata,
+ "[git@[fe80::dcad:beff:fe00:0001:42]:/resource"));
+}
diff --git a/tests/util/url/valid.c b/tests/util/url/valid.c
new file mode 100644
index 0000000..797b697
--- /dev/null
+++ b/tests/util/url/valid.c
@@ -0,0 +1,17 @@
+#include "clar_libgit2.h"
+#include "net.h"
+
+void test_url_valid__test(void)
+{
+ cl_assert(git_net_str_is_url("http://example.com/"));
+ cl_assert(git_net_str_is_url("file://localhost/tmp/foo/"));
+ cl_assert(git_net_str_is_url("ssh://user@host:42/tmp"));
+ cl_assert(git_net_str_is_url("git+ssh://user@host:42/tmp"));
+ cl_assert(git_net_str_is_url("ssh+git://user@host:42/tmp"));
+ cl_assert(git_net_str_is_url("https://user:pass@example.com/foo/bar"));
+
+ cl_assert(!git_net_str_is_url("host:foo.git"));
+ cl_assert(!git_net_str_is_url("host:/foo.git"));
+ cl_assert(!git_net_str_is_url("[host:42]:/foo.git"));
+ cl_assert(!git_net_str_is_url("[user@host:42]:/foo.git"));
+}