summaryrefslogtreecommitdiffstats
path: root/src/lib-http/test-http-url.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-http/test-http-url.c')
-rw-r--r--src/lib-http/test-http-url.c950
1 files changed, 950 insertions, 0 deletions
diff --git a/src/lib-http/test-http-url.c b/src/lib-http/test-http-url.c
new file mode 100644
index 0000000..a9fdf24
--- /dev/null
+++ b/src/lib-http/test-http-url.c
@@ -0,0 +1,950 @@
+/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "net.h"
+#include "http-url.h"
+#include "test-common.h"
+
+struct valid_http_url_test {
+ const char *url;
+ enum http_url_parse_flags flags;
+ struct http_url url_base;
+
+ struct http_url url_parsed;
+};
+
+/* Valid HTTP URL tests */
+static struct valid_http_url_test valid_url_tests[] = {
+ /* Generic tests */
+ {
+ .url = "http://localhost",
+ .url_parsed = {
+ .host = { .name = "localhost" },
+ },
+ },
+ {
+ .url = "http://www.%65%78%61%6d%70%6c%65.com",
+ .url_parsed = {
+ .host = { .name = "www.example.com" },
+ },
+ },
+ {
+ .url = "http://www.dovecot.org:8080",
+ .url_parsed = {
+ .host = { .name = "www.dovecot.org" },
+ .port = 8080,
+ },
+ },
+ {
+ .url = "http://127.0.0.1",
+ .url_parsed = {
+ .host = {
+ .name = "127.0.0.1",
+ .ip = { .family = AF_INET },
+ },
+ },
+ },
+ {
+ .url = "http://[::1]",
+ .url_parsed = {
+ .host = {
+ .name = "[::1]",
+ .ip = { .family = AF_INET6 },
+ },
+ },
+ },
+ {
+ .url = "http://[::1]:8080",
+ .url_parsed = {
+ .host = {
+ .name = "[::1]",
+ .ip = { .family = AF_INET6 },
+ },
+ .port = 8080,
+ },
+ },
+ {
+ .url = "http://user@api.dovecot.org",
+ .flags = HTTP_URL_ALLOW_USERINFO_PART,
+ .url_parsed = {
+ .host = { .name = "api.dovecot.org" },
+ .user = "user",
+ },
+ },
+ {
+ .url = "http://userid:secret@api.dovecot.org",
+ .flags = HTTP_URL_ALLOW_USERINFO_PART,
+ .url_parsed = {
+ .host = { .name = "api.dovecot.org" },
+ .user = "userid",
+ .password = "secret",
+ },
+ },
+ {
+ .url = "http://su%3auserid:secret@api.dovecot.org",
+ .flags = HTTP_URL_ALLOW_USERINFO_PART,
+ .url_parsed = {
+ .host = { .name = "api.dovecot.org" },
+ .user = "su:userid",
+ .password = "secret",
+ },
+ },
+ {
+ .url = "http://www.example.com/"
+ "?question=What%20are%20you%20doing%3f&answer=Nothing.",
+ .url_parsed = {
+ .path = "/",
+ .host = { .name = "www.example.com" },
+ .enc_query = "question=What%20are%20you%20doing%3f&answer=Nothing.",
+ },
+ },
+ /* Empty path segments */
+ {
+ .url = "http://target//index.php",
+ .url_parsed = {
+ .path = "//index.php",
+ .host = { .name = "target" },
+ },
+ },
+ {
+ .url = "http://target//path//index.php",
+ .url_parsed = {
+ .path = "//path//index.php",
+ .host = { .name = "target" },
+ },
+ },
+ {
+ .url = "http://target//path/",
+ .url_parsed = {
+ .path = "//path/",
+ .host = { .name = "target" },
+ },
+ },
+ {
+ .url = "http://target//path//",
+ .url_parsed = {
+ .path = "//path//",
+ .host = { .name = "target" },
+ },
+ },
+ {
+ .url = "http://target//path//to//./index.php",
+ .url_parsed = {
+ .path = "//path//to//index.php",
+ .host = { .name = "target" },
+ },
+ },
+ {
+ .url = "http://target//path//to//../index.php",
+ .url_parsed = {
+ .path = "//path//to/index.php",
+ .host = { .name = "target" },
+ },
+ },
+ {
+ .url = "/index.php",
+ .url_base = {
+ .host = { .name = "target" },
+ },
+ .url_parsed = {
+ .host = { .name = "target" },
+ .path = "/index.php",
+ },
+ },
+ {
+ .url = "//index.php",
+ .url_base = {
+ .host = { .name = "target" },
+ },
+ .url_parsed = {
+ .host = { .name = "index.php" },
+ },
+ },
+ {
+ .url = "/path/to/index.php",
+ .url_base = {
+ .host = { .name = "target" },
+ },
+ .url_parsed = {
+ .host = { .name = "target" },
+ .path = "/path/to/index.php",
+ },
+ },
+ {
+ .url = "//path//to//index.php",
+ .url_base = {
+ .host = { .name = "target" },
+ },
+ .url_parsed = {
+ .host = { .name = "path" },
+ .path = "//to//index.php",
+ },
+ },
+ /* These next 2 URLs don't follow the recommendations in
+ http://tools.ietf.org/html/rfc1034#section-3.5 and
+ http://tools.ietf.org/html/rfc3696
+ However they satisfy the grammar in
+ http://tools.ietf.org/html/rfc1123#section-2 and
+ http://tools.ietf.org/html/rfc952
+ so we should parse them.
+ */
+ {
+ .url = "http://256.0.0.1/that/reverts/to/DNS",
+ .url_parsed = {
+ .path = "/that/reverts/to/DNS",
+ .host = { .name = "256.0.0.1" },
+ },
+ },
+ {
+ .url = "http://127.0.0.284/this/also/reverts/to/DNS",
+ .url_parsed = {
+ .path = "/this/also/reverts/to/DNS",
+ .host = { .name = "127.0.0.284" },
+ },
+ },
+ {
+ .url = "http://www.example.com/#Status%20of%20development",
+ .flags = HTTP_URL_ALLOW_FRAGMENT_PART,
+ .url_parsed = {
+ .path = "/",
+ .host = { .name = "www.example.com" },
+ .enc_fragment = "Status%20of%20development",
+ },
+ },
+ /* RFC 3986, Section 5.4. Reference Resolution Examples
+ *
+ * Within a representation with a well defined base URI of
+ *
+ * http://a/b/c/d;p?q
+ *
+ * a relative reference is transformed to its target URI as follows.
+ *
+ * 5.4.1. Normal Examples
+ */
+ { // "g" = "http://a/b/c/g"
+ .url = "g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ },
+ },
+ { // "./g" = "http://a/b/c/g"
+ .url = "./g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ },
+ },
+ { // "g/" = "http://a/b/c/g/"
+ .url = "g/",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g/",
+ },
+ },
+ { // "/g" = "http://a/g"
+ .url = "/g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/g",
+ },
+ },
+ { // "//g" = "http://g"
+ .url = "//g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "g" },
+ },
+ },
+ { // "?y" = "http://a/b/c/d;p?y"
+ .url = "?y",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "y",
+ },
+ },
+ { // "g?y" = "http://a/b/c/g?y"
+ .url = "g?y",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ .enc_query = "y",
+ },
+ },
+ { // "#s" = "http://a/b/c/d;p?q#s"
+ .url = "#s",
+ .flags = HTTP_URL_ALLOW_FRAGMENT_PART,
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ .enc_fragment = "s",
+ },
+ },
+ { // "g#s" = "http://a/b/c/g#s"
+ .url = "g#s",
+ .flags = HTTP_URL_ALLOW_FRAGMENT_PART,
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ .enc_fragment = "s",
+ },
+ },
+ { // "g?y#s" = "http://a/b/c/g?y#s"
+ .url = "g?y#s",
+ .flags = HTTP_URL_ALLOW_FRAGMENT_PART,
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ .enc_query = "y",
+ .enc_fragment = "s",
+ },
+ },
+ { // ";x" = "http://a/b/c/;x"
+ .url = ";x",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/;x",
+ },
+ },
+ { // "g;x" = "http://a/b/c/g;x"
+ .url = "g;x",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g;x",
+ },
+
+ },
+ { // "g;x?y#s" = "http://a/b/c/g;x?y#s"
+ .url = "g;x?y#s",
+ .flags = HTTP_URL_ALLOW_FRAGMENT_PART,
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g;x",
+ .enc_query = "y",
+ .enc_fragment = "s",
+ },
+ },
+ { // "" = "http://a/b/c/d;p?q"
+ .url = "",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ },
+ { // "." = "http://a/b/c/"
+ .url = ".",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/",
+ },
+ },
+ { // "./" = "http://a/b/c/"
+ .url = "./",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/",
+ },
+ },
+ { // ".." = "http://a/b/"
+ .url = "..",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/",
+ },
+ },
+ { // "../" = "http://a/b/"
+ .url = "../",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/",
+ },
+ },
+ { // "../g" = "http://a/b/g"
+ .url = "../g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/g",
+ },
+ },
+ { // "../.." = "http://a/"
+ .url = "../..",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/",
+ },
+ },
+ { // "../../" = "http://a/"
+ .url = "../../",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/",
+ },
+ },
+ { // "../../g" = "http://a/g"
+ .url = "../../g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/g",
+ },
+ },
+ /* 5.4.2. Abnormal Examples
+ */
+ { // "../../../g" = "http://a/g"
+ .url = "../../../g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/g",
+ },
+ },
+ { // "../../../../g" = "http://a/g"
+ .url = "../../../../g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/g",
+ },
+ },
+ { // "/./g" = "http://a/g"
+ .url = "/./g",
+ .url_base = {
+ .host = {.name = "a"},
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = {.name = "a"},
+ .path = "/g",
+ },
+ },
+ { // "/../g" = "http://a/g"
+ .url = "/../g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/g",
+ },
+ },
+ { // "g." = "http://a/b/c/g."
+ .url = "g.",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g.",
+ },
+ },
+ { // ".g" = "http://a/b/c/.g"
+ .url = ".g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/.g",
+ },
+ },
+ { // "g.." = "http://a/b/c/g.."
+ .url = "g..",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g..",
+ },
+ },
+ { // "..g" = "http://a/b/c/..g"
+ .url = "..g",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/..g",
+ },
+ },
+ { // "./../g" = "http://a/b/g"
+ .url = "./../g",
+ .url_base = {
+ .host = {.name = "a"},
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = {.name = "a"},
+ .path = "/b/g",
+ },
+ },
+ { // "./g/." = "http://a/b/c/g/"
+ .url = "./g/.",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g/",
+ },
+ },
+ { // "g/./h" = "http://a/b/c/g/h"
+ .url = "g/./h",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g/h",
+ },
+ },
+ { // "g/../h" = "http://a/b/c/h"
+ .url = "g/../h",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/h",
+ },
+ },
+ { // "g;x=1/./y" = "http://a/b/c/g;x=1/y"
+ .url = "g;x=1/./y",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g;x=1/y",
+ },
+ },
+ { // "g;x=1/../y" = "http://a/b/c/y"
+ .url = "g;x=1/../y",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/y",
+ },
+ },
+ { // "g?y/./x" = "http://a/b/c/g?y/./x"
+ .url = "g?y/./x",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ .enc_query = "y/./x",
+ },
+ },
+ { // "g?y/../x" = "http://a/b/c/g?y/../x"
+ .url = "g?y/../x",
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed = {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ .enc_query = "y/../x",
+ },
+ },
+ { // "g#s/./x" = "http://a/b/c/g#s/./x"
+ .url = "g#s/./x",
+ .flags = HTTP_URL_ALLOW_FRAGMENT_PART,
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed =
+ {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ .enc_fragment = "s/./x",
+ },
+ },
+ { // "g#s/../x" = "http://a/b/c/g#s/../x"
+ .url = "g#s/../x",
+ .flags = HTTP_URL_ALLOW_FRAGMENT_PART,
+ .url_base = {
+ .host = { .name = "a" },
+ .path = "/b/c/d;p",
+ .enc_query = "q",
+ },
+ .url_parsed =
+ {
+ .host = { .name = "a" },
+ .path = "/b/c/g",
+ .enc_fragment = "s/../x",
+ },
+ }
+};
+
+static unsigned int valid_url_test_count = N_ELEMENTS(valid_url_tests);
+
+static void
+test_http_url_equal(struct http_url *urlt, struct http_url *urlp)
+{
+ if (urlp->host.name == NULL || urlt->host.name == NULL) {
+ test_assert(urlp->host.name == urlt->host.name);
+ } else {
+ test_assert(strcmp(urlp->host.name, urlt->host.name) == 0);
+ }
+ test_assert(urlp->port == urlt->port);
+ test_assert(urlp->host.ip.family == urlt->host.ip.family);
+ if (urlp->user == NULL || urlt->user == NULL) {
+ test_assert(urlp->user == urlt->user);
+ } else {
+ test_assert(strcmp(urlp->user, urlt->user) == 0);
+ }
+ if (urlp->password == NULL || urlt->password == NULL) {
+ test_assert(urlp->password == urlt->password);
+ } else {
+ test_assert(strcmp(urlp->password, urlt->password) == 0);
+ }
+ if (urlp->path == NULL || urlt->path == NULL) {
+ test_assert(urlp->path == urlt->path);
+ } else {
+ test_assert(strcmp(urlp->path, urlt->path) == 0);
+ }
+ if (urlp->enc_query == NULL || urlt->enc_query == NULL) {
+ test_assert(urlp->enc_query == urlt->enc_query);
+ } else {
+ test_assert(strcmp(urlp->enc_query, urlt->enc_query) == 0);
+ }
+ if (urlp->enc_fragment == NULL || urlt->enc_fragment == NULL) {
+ test_assert(urlp->enc_fragment == urlt->enc_fragment);
+ } else {
+ test_assert(strcmp(urlp->enc_fragment,
+ urlt->enc_fragment) == 0);
+ }
+}
+
+static void test_http_url_valid(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < valid_url_test_count; i++) T_BEGIN {
+ const char *url = valid_url_tests[i].url;
+ enum http_url_parse_flags flags = valid_url_tests[i].flags;
+ struct http_url *urlt = &valid_url_tests[i].url_parsed;
+ struct http_url *urlb = &valid_url_tests[i].url_base;
+ struct http_url *urlp;
+ const char *error = NULL;
+
+ test_begin(t_strdup_printf("http url valid [%d]", i));
+
+ if (urlb->host.name == NULL) urlb = NULL;
+ if (http_url_parse(url, urlb, flags, pool_datastack_create(),
+ &urlp, &error) < 0)
+ urlp = NULL;
+
+ test_out_reason(t_strdup_printf("http_url_parse(%s)",
+ valid_url_tests[i].url), urlp != NULL, error);
+ if (urlp != NULL)
+ test_http_url_equal(urlt, urlp);
+
+ test_end();
+ } T_END;
+}
+
+struct invalid_http_url_test {
+ const char *url;
+ enum http_url_parse_flags flags;
+ struct http_url url_base;
+};
+
+static struct invalid_http_url_test invalid_url_tests[] = {
+ {
+ .url = "imap://example.com/INBOX"
+ },
+ {
+ .url = "http:/www.example.com"
+ },
+ {
+ .url = ""
+ },
+ {
+ .url = "/index.html"
+ },
+ {
+ .url = "http://www.example.com/index.html\""
+ },
+ {
+ .url = "http:///dovecot.org"
+ },
+ {
+ .url = "http://[]/index.html"
+ },
+ {
+ .url = "http://[v08.234:232:234:234:2221]/index.html"
+ },
+ {
+ .url = "http://[1::34a:34:234::6]/index.html"
+ },
+ {
+ .url = "http://example%a.com/index.html"
+ },
+ {
+ .url = "http://example.com%/index.html"
+ },
+ {
+ .url = "http://example%00.com/index.html"
+ },
+ {
+ .url = "http://example.com:65536/index.html"
+ },
+ {
+ .url = "http://example.com:72817/index.html"
+ },
+ {
+ .url = "http://example.com/settings/%00/"
+ },
+ {
+ .url = "http://example.com/settings/%0r/"
+ },
+ {
+ .url = "http://example.com/settings/misc/%/"
+ },
+ {
+ .url = "http://example.com/?%00"
+ },
+ {
+ .url = "http://www.example.com/network.html#IMAP_Server"
+ },
+ {
+ .url = "http://example.com/#%00",
+ .flags = HTTP_URL_ALLOW_FRAGMENT_PART
+ }
+};
+
+static unsigned int invalid_url_test_count = N_ELEMENTS(invalid_url_tests);
+
+static void test_http_url_invalid(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < invalid_url_test_count; i++) T_BEGIN {
+ const char *url = invalid_url_tests[i].url;
+ enum http_url_parse_flags flags = invalid_url_tests[i].flags;
+ struct http_url *urlb = &invalid_url_tests[i].url_base;
+ struct http_url *urlp;
+ const char *error = NULL;
+
+ if (urlb->host.name == NULL)
+ urlb = NULL;
+
+ test_begin(t_strdup_printf("http url invalid [%d]", i));
+
+ if (http_url_parse(url, urlb, flags,
+ pool_datastack_create(), &urlp, &error) < 0)
+ urlp = NULL;
+ test_out_reason(t_strdup_printf("parse %s", url),
+ urlp == NULL, error);
+
+ test_end();
+ } T_END;
+
+}
+
+static const char *parse_create_url_tests[] = {
+ "http://www.example.com/",
+ "http://10.0.0.1/",
+ "http://[::1]/",
+ "http://www.example.com:993/",
+ "http://www.example.com/index.html",
+ "http://www.example.com/settings/index.html",
+ "http://www.example.com/%23shared/news",
+ "http://www.example.com/query.php?name=Hendrik%20Visser",
+ "http://www.example.com/network.html#IMAP%20Server",
+};
+
+static unsigned int
+parse_create_url_test_count = N_ELEMENTS(parse_create_url_tests);
+
+static void test_http_url_parse_create(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < parse_create_url_test_count; i++) T_BEGIN {
+ const char *url = parse_create_url_tests[i];
+ struct http_url *urlp;
+ const char *error = NULL;
+
+ test_begin(t_strdup_printf("http url parse/create [%d]", i));
+
+ if (http_url_parse
+ (url, NULL, HTTP_URL_ALLOW_FRAGMENT_PART,
+ pool_datastack_create(), &urlp, &error) < 0)
+ urlp = NULL;
+ test_out_reason(t_strdup_printf("parse %s", url),
+ urlp != NULL, error);
+ if (urlp != NULL) {
+ const char *urlnew = http_url_create(urlp);
+ test_out(t_strdup_printf("create %s", urlnew),
+ strcmp(url, urlnew) == 0);
+ }
+
+ test_end();
+ } T_END;
+
+}
+
+int main(void)
+{
+ static void (*const test_functions[])(void) = {
+ test_http_url_valid,
+ test_http_url_invalid,
+ test_http_url_parse_create,
+ NULL
+ };
+ return test_run(test_functions);
+}
+