/* * Copyright 2015 Vincent Sanders * Copyright 2011 John Mark Bell * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file * Test nsurl operations. */ #include #include #include #include #include #include #include "utils/corestrings.h" #include "utils/nsurl.h" #define NELEMS(x) (sizeof(x) / sizeof((x)[0])) struct test_pairs { const char* test; const char* res; }; struct test_triplets { const char* test1; const char* test2; const char* res; }; struct test_compare { const char* test1; const char* test2; nsurl_component parts; bool res; }; /* Fixtures */ static void corestring_create(void) { ck_assert(corestrings_init() == NSERROR_OK); } /** * iterator for any remaining strings in teardown fixture */ static void netsurf_lwc_iterator(lwc_string *str, void *pw) { fprintf(stderr, "[%3u] %.*s", str->refcnt, (int)lwc_string_length(str), lwc_string_data(str)); } static void corestring_teardown(void) { corestrings_fini(); lwc_iterate_strings(netsurf_lwc_iterator, NULL); } /* tests */ static const char *base_str = "http://a/b/c/d;p?q"; static const struct test_pairs create_tests[] = { { "", NULL }, { "http:", NULL }, { "http:/", NULL }, { "http://", NULL }, { "http:a", "http://a/" }, { "http:a/", "http://a/" }, { "http:a/b", "http://a/b" }, { "http:/a", "http://a/" }, { "http:/a/b", "http://a/b" }, { "http://a", "http://a/" }, { "http://a/b", "http://a/b" }, { "www.example.org", "http://www.example.org/" }, { "www.example.org/x", "http://www.example.org/x" }, { "about:", "about:" }, { "about:blank", "about:blank" }, { "http://www.ns-b.org:8080/", "http://www.ns-b.org:8080/" }, { "http://user@www.ns-b.org:8080/hello", "http://user@www.ns-b.org:8080/hello" }, { "http://user:pass@www.ns-b.org:8080/hello", "http://user:pass@www.ns-b.org:8080/hello" }, { "http://www.ns-b.org:80/", "http://www.ns-b.org/" }, { "http://user@www.ns-b.org:80/hello", "http://user@www.ns-b.org/hello" }, { "http://user:pass@www.ns-b.org:80/hello", "http://user:pass@www.ns-b.org/hello" }, { "http://www.ns-b.org:/", "http://www.ns-b.org/" }, { "http://///////////www.ns-b.org:/", "http://www.ns-b.org/" }, { "http://u@www.ns-b.org:/hello", "http://u@www.ns-b.org/hello" }, { "http://u:p@www.ns-b.org:/hello", "http://u:p@www.ns-b.org/hello" }, { "http:a/", "http://a/" }, { "http:/a/", "http://a/" }, { "http://u@a", "http://u@a/" }, { "http://@a", "http://a/" }, { "mailto:u@a", "mailto:u@a" }, { "mailto:@a", "mailto:a" }, { "file:///", "file:///" }, { "file://", "file:///" }, { "file:/", "file:///" }, { "file:", "file:///" }, { "file:////", "file:////" }, { "file://///", "file://///" }, { "file://localhost/", "file:///" }, { "file://foobar/", "file:///" }, { "file://foobar", "file:///" }, { "file:///foobar", "file:///foobar" }, { "file://tlsa@foo/", "file:///" }, /* test case insensitivity */ { "HTTP://a/b", "http://a/b" }, { "HTTPS://a/b", "https://a/b" }, { "ftp://a/b", "ftp://a/b" }, { "FTP://a/b", "ftp://a/b" }, { "MAILTO:foo@bar", "mailto:foo@bar" }, { "FILE:///", "file:///" }, { "http://HOST/", "http://host/" }, /* punycode */ { "http://a.कॉम/a", "http://a.xn--11b4c3d/a" }, { "https://smog.大众汽车/test", "https://smog.xn--3oq18vl8pn36a/test"}, /* unnecessary escape */ { "http://%7a%7A/", "http://zz/" }, /* bad escape */ { "http://%1g%G0/", "http://%1g%g0/" }, { " http://www.ns-b.org/", "http://www.ns-b.org/" }, { "http://www.ns-b.org/ ", "http://www.ns-b.org/" }, { "http://www.ns-b.org ", "http://www.ns-b.org/" }, { "http://www.ns-b.org/?q ", "http://www.ns-b.org/?q" }, { "http://www.ns-b.org/#f ", "http://www.ns-b.org/#f" }, }; /** * url creation test */ START_TEST(nsurl_create_test) { nserror err; nsurl *res; const struct test_pairs *tst = &create_tests[_i]; err = nsurl_create(tst->test, &res); if (tst->res == NULL) { /* result must be invalid */ ck_assert(err != NSERROR_OK); } else { /* result must be valid */ ck_assert(err == NSERROR_OK); ck_assert_str_eq(nsurl_access(res), tst->res); nsurl_unref(res); } } END_TEST static const struct test_triplets access_tests[] = { { "http://www.netsurf-browser.org/a/big/tree", "http://www.netsurf-browser.org/a/big/tree", "tree" }, { "HTTP://ci.netsurf-browser.org/jenkins/view/Unit Tests/job/coverage-netsurf/11/cobertura/utils/nsurl_c/", "http://ci.netsurf-browser.org/jenkins/view/Unit%20Tests/job/coverage-netsurf/11/cobertura/utils/nsurl_c/", "" }, { "FILE:///", "file:///", "/" }, }; /** * url access test */ START_TEST(nsurl_access_test) { nserror err; nsurl *res_url; const struct test_triplets *tst = &access_tests[_i]; /* not testing create, this should always succeed */ err = nsurl_create(tst->test1, &res_url); ck_assert(err == NSERROR_OK); /* The url accessed string must match the input */ ck_assert_str_eq(nsurl_access(res_url), tst->test2); nsurl_unref(res_url); } END_TEST /** * url access leaf test */ START_TEST(nsurl_access_leaf_test) { nserror err; nsurl *res_url; const struct test_triplets *tst = &access_tests[_i]; /* not testing create, this should always succeed */ err = nsurl_create(tst->test1, &res_url); ck_assert(err == NSERROR_OK); ck_assert_str_eq(nsurl_access_leaf(res_url), tst->res); nsurl_unref(res_url); } END_TEST /** * url length test * * uses access dataset and test unit */ START_TEST(nsurl_length_test) { nserror err; nsurl *res_url; const struct test_triplets *tst = &access_tests[_i]; /* not testing create, this should always succeed */ err = nsurl_create(tst->test1, &res_url); ck_assert(err == NSERROR_OK); ck_assert_int_eq(nsurl_length(res_url), strlen(tst->test2)); nsurl_unref(res_url); } END_TEST static const struct test_pairs nice_tests[] = { { "about:", NULL }, { "www.foo.org", "www_foo_org" }, { "www.foo.org/index.html", "www_foo_org" }, { "www.foo.org/default.en", "www_foo_org" }, { "www.foo.org/about", "about" }, { "www.foo.org/about.jpg", "about.jpg" }, { "www.foo.org/moose/index.en", "moose" }, { "www.foo.org/a//index.en", "www_foo_org" }, { "www.foo.org/a//index.en", "www_foo_org" }, { "http://www.f.org//index.en", "www_f_org" }, }; /** * url nice filename without stripping */ START_TEST(nsurl_nice_nostrip_test) { nserror err; nsurl *res_url; char *res_str; const struct test_pairs *tst = &nice_tests[_i]; /* not testing create, this should always succeed */ err = nsurl_create(tst->test, &res_url); ck_assert(err == NSERROR_OK); err = nsurl_nice(res_url, &res_str, false); if (tst->res == NULL) { /* result must be invalid (bad input) */ ck_assert(err != NSERROR_OK); } else { /* result must be valid */ ck_assert(err == NSERROR_OK); ck_assert_str_eq(res_str, tst->res); free(res_str); } nsurl_unref(res_url); } END_TEST static const struct test_pairs nice_strip_tests[] = { { "about:", NULL }, { "www.foo.org", "www_foo_org" }, { "www.foo.org/index.html", "www_foo_org" }, { "www.foo.org/default.en", "www_foo_org" }, { "www.foo.org/about", "about" }, { "www.foo.org/about.jpg", "about" }, { "www.foo.org/moose/index.en", "moose" }, { "www.foo.org/a//index.en", "www_foo_org" }, { "www.foo.org/a//index.en", "www_foo_org" }, { "http://www.f.org//index.en", "www_f_org" }, }; /** * url nice filename with stripping */ START_TEST(nsurl_nice_strip_test) { nserror err; nsurl *res_url; char *res_str; const struct test_pairs *tst = &nice_strip_tests[_i]; /* not testing create, this should always succeed */ err = nsurl_create(tst->test, &res_url); ck_assert(err == NSERROR_OK); err = nsurl_nice(res_url, &res_str, true); if (tst->res == NULL) { /* result must be invalid (bad input) */ ck_assert(err != NSERROR_OK); } else { /* result must be valid */ ck_assert(err == NSERROR_OK); ck_assert_str_eq(res_str, tst->res); free(res_str); } nsurl_unref(res_url); } END_TEST /** * simple joins that all use http://a/b/c/d;p?q as a base */ static const struct test_pairs join_tests[] = { /* Normal Examples rfc3986 5.4.1 */ { "g:h", "g:h" }, { "g", "http://a/b/c/g" }, { "./g", "http://a/b/c/g" }, { "g/", "http://a/b/c/g/" }, { "/g", "http://a/g" }, { "//g", "http://g" /* [1] */ "/" }, { "?y", "http://a/b/c/d;p?y" }, { "g?y", "http://a/b/c/g?y" }, { "#s", "http://a/b/c/d;p?q#s" }, { "g#s", "http://a/b/c/g#s" }, { "g?y#s", "http://a/b/c/g?y#s" }, { ";x", "http://a/b/c/;x" }, { "g;x", "http://a/b/c/g;x" }, { "g;x?y#s", "http://a/b/c/g;x?y#s" }, { "", "http://a/b/c/d;p?q" }, { ".", "http://a/b/c/" }, { "./", "http://a/b/c/" }, { "..", "http://a/b/" }, { "../", "http://a/b/" }, { "../g", "http://a/b/g" }, { "../..", "http://a/" }, { "../../", "http://a/" }, { "../../g", "http://a/g" }, /* Abnormal Examples rfc3986 5.4.2 */ { "../../../g", "http://a/g" }, { "../../../../g", "http://a/g" }, { "/./g", "http://a/g" }, { "/../g", "http://a/g" }, { "g.", "http://a/b/c/g." }, { ".g", "http://a/b/c/.g" }, { "g..", "http://a/b/c/g.." }, { "..g", "http://a/b/c/..g" }, { "./../g", "http://a/b/g" }, { "./g/.", "http://a/b/c/g/" }, { "g/./h", "http://a/b/c/g/h" }, { "g/../h", "http://a/b/c/h" }, { "g;x=1/./y", "http://a/b/c/g;x=1/y" }, { "g;x=1/../y", "http://a/b/c/y" }, { "g?y/./x", "http://a/b/c/g?y/./x" }, { "g?y/../x", "http://a/b/c/g?y/../x" }, { "g#s/./x", "http://a/b/c/g#s/./x" }, { "g#s/../x", "http://a/b/c/g#s/../x" }, { "http:g", "http:g" /* [2] */ }, /* Extra tests */ { " g", "http://a/b/c/g" }, { "g ", "http://a/b/c/g" }, { " g ", "http://a/b/c/g" }, { "http:/b/c", "http://b/c" }, { "http://", "http:" }, { "http:/", "http:" }, { "http:", "http:" }, { " ", "http://a/b/c/d;p?q" }, { " ", "http://a/b/c/d;p?q" }, { "/", "http://a/" }, { " / ", "http://a/" }, { " ? ", "http://a/b/c/d;p" }, { " h ", "http://a/b/c/h" }, { "//foo?", "http://foo/" }, { "//foo#bar", "http://foo/#bar" }, { "//foo/", "http://foo/" }, { "http://