diff --git a/upnp/Makefile.am b/upnp/Makefile.am index bafe105..b624e41 100644 --- a/upnp/Makefile.am +++ b/upnp/Makefile.am @@ -154,9 +154,10 @@ libupnp_la_SOURCES += \ # check / distcheck tests -check_PROGRAMS = test_init -TESTS = test_init +check_PROGRAMS = test_init test_url +TESTS = test_init test_url test_init_SOURCES = test/test_init.c +test_url_SOURCES = test/test_url.c EXTRA_DIST = \ diff --git a/upnp/test/test_url.c b/upnp/test/test_url.c new file mode 100644 index 0000000..84136e7 --- /dev/null +++ b/upnp/test/test_url.c @@ -0,0 +1,131 @@ + +#include +#include +#include +#include "upnp.h" +#include "upnptools.h" + +struct test { + const char *base; + const char *rel; + const char *expect; + int line; + int error; +}; +#define TEST(BaseURL, RelURL, expect, ...) {BaseURL, RelURL, expect, __LINE__, ##__VA_ARGS__} + +static int +result(const struct test *test) +{ + char *absurl = NULL; + int ret = 0; + + ret = UpnpResolveURL2(test->base, test->rel, &absurl); + if (ret == test->error && (test->expect == NULL || strcmp(test->expect, absurl) == 0)) { + ret = 0; + } else { + printf("%s:%d: '%s' | '%s' -> '%s' != '%s' (%d)\n", __FILE__, test->line, test->base, test->rel, absurl, test->expect, ret); + ret = 1; + } + free(absurl); + return ret; +} + +/* The URLs must be resolvale! */ +static const char ABS_URL1[] = "http://www.libupnp.org/path1/"; +static const char ABS_URL2[] = "http://www.libupnp.org/path1/path1"; +static const char ABS_URL3[] = "http://localhost/path1/"; +static const char ABS_URL4[] = "http://127.0.0.1/path1/"; +static const char ABS_URL5[] = "http://127.0.0.1:6544/path1/"; +static const char ABS_URL6[] = "http://[::1]:6544/path1/"; + +static const char REL_URL1[] = "//localhost/path2"; +static const char REL_URL2[] = "/path3"; +static const char REL_URL3[] = "path4"; +static const char REL_URL4[] = "../path5"; +static const char REL_URL5[] = "?query1"; +static const char REL_URL6[] = "#frag1"; + +static const char ABS_RFC[] = "http://localhost/b/c/d;p?q"; +// s,\,localhost, +// s,//g\>,//127.0.0.1, + +static const struct test RFC3986[] = { + // Errors + TEST(NULL, NULL, NULL, UPNP_E_INVALID_PARAM), + TEST(ABS_URL1, NULL, NULL, UPNP_E_INVALID_PARAM), + TEST("foo", "bar", NULL, UPNP_E_INVALID_URL), + // Custom + TEST(NULL, ABS_URL1, ABS_URL1), + TEST(ABS_URL1, ABS_URL2, ABS_URL2), + TEST(ABS_URL1, "", ABS_URL1), + TEST(ABS_URL1, REL_URL1, "http://localhost/path2"), + TEST(ABS_URL2, REL_URL1, "http://localhost/path2"), + TEST(ABS_URL1, REL_URL2, "http://www.libupnp.org/path3"), + TEST(ABS_URL2, REL_URL2, "http://www.libupnp.org/path3"), + TEST(ABS_URL1, REL_URL3, "http://www.libupnp.org/path1/path4"), + TEST(ABS_URL2, REL_URL3, "http://www.libupnp.org/path1/path4"), + TEST(ABS_URL1, REL_URL4, "http://www.libupnp.org/path5"), + TEST(ABS_URL2, REL_URL4, "http://www.libupnp.org/path5"), + TEST(ABS_URL1, REL_URL6, "http://www.libupnp.org/path1/#frag1"), + TEST(ABS_URL2, REL_URL6, "http://www.libupnp.org/path1/path1#frag1"), + TEST("http://127.0.0.1:6544/getDeviceDesc", "CDS_Event", "http://127.0.0.1:6544/CDS_Event"), + // Normal Examples + TEST(ABS_RFC, "g:h", "g:h"), + TEST(ABS_RFC, "g", "http://localhost/b/c/g"), + TEST(ABS_RFC, "./g", "http://localhost/b/c/g"), + TEST(ABS_RFC, "g/", "http://localhost/b/c/g/"), + TEST(ABS_RFC, "/g", "http://localhost/g"), + TEST(ABS_RFC, "//127.0.0.1", "http://127.0.0.1"), + TEST(ABS_RFC, "?y", "http://localhost/b/c/d;p?y"), + TEST(ABS_RFC, "g?y", "http://localhost/b/c/g?y"), + TEST(ABS_RFC, "#s", "http://localhost/b/c/d;p?q#s"), + TEST(ABS_RFC, "g#s", "http://localhost/b/c/g#s"), + TEST(ABS_RFC, "g?y#s", "http://localhost/b/c/g?y#s"), + TEST(ABS_RFC, ";x", "http://localhost/b/c/;x"), + TEST(ABS_RFC, "g;x", "http://localhost/b/c/g;x"), + TEST(ABS_RFC, "g;x?y#s", "http://localhost/b/c/g;x?y#s"), + TEST(ABS_RFC, "", "http://localhost/b/c/d;p?q"), + TEST(ABS_RFC, ".", "http://localhost/b/c/"), + TEST(ABS_RFC, "./", "http://localhost/b/c/"), + TEST(ABS_RFC, "..", "http://localhost/b/"), + TEST(ABS_RFC, "../", "http://localhost/b/"), + TEST(ABS_RFC, "../g", "http://localhost/b/g"), + TEST(ABS_RFC, "../..", "http://localhost/"), + TEST(ABS_RFC, "../../", "http://localhost/"), + TEST(ABS_RFC, "../../g", "http://localhost/g"), + // Abnormal Examples + TEST(ABS_RFC, "../../../g", "http://localhost/g"), + TEST(ABS_RFC, "../../../../g", "http://localhost/g"), + TEST(ABS_RFC, "/./g", "http://localhost/g"), + TEST(ABS_RFC, "/../g", "http://localhost/g"), + TEST(ABS_RFC, "g.", "http://localhost/b/c/g."), + TEST(ABS_RFC, ".g", "http://localhost/b/c/.g"), + TEST(ABS_RFC, "g..", "http://localhost/b/c/g.."), + TEST(ABS_RFC, "..g", "http://localhost/b/c/..g"), + TEST(ABS_RFC, "./../g", "http://localhost/b/g"), + TEST(ABS_RFC, "./g/.", "http://localhost/b/c/g/"), + TEST(ABS_RFC, "g/./h", "http://localhost/b/c/g/h"), + TEST(ABS_RFC, "g/../h", "http://localhost/b/c/h"), + TEST(ABS_RFC, "g;x=1/./y", "http://localhost/b/c/g;x=1/y"), + TEST(ABS_RFC, "g;x=1/../y", "http://localhost/b/c/y"), + TEST(ABS_RFC, "g?y/./x", "http://localhost/b/c/g?y/./x"), + TEST(ABS_RFC, "g?y/../x", "http://localhost/b/c/g?y/../x"), + TEST(ABS_RFC, "g#s/./x", "http://localhost/b/c/g#s/./x"), + TEST(ABS_RFC, "g#s/../x", "http://localhost/b/c/g#s/../x"), + TEST(ABS_RFC, "http:g", "http:g"), + }; +#define ARRAY_SIZE(a) (sizeof (a) / sizeof *(a)) + +int +main (int argc, char* argv[]) +{ + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(RFC3986); i++) + ret += result(&RFC3986[i]); + + exit (ret ? EXIT_FAILURE : EXIT_SUCCESS); +} + +// gcc -o url-test -g url-test.c -I ixml/inc -I threadutil/inc -I upnp/inc upnp/.libs/libupnp.a -L ixml/.libs -lixml -L threadutil/.libs -lthreadutil -lpthread