uri-tests.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /*
  2. URI handling tests
  3. Copyright (C) 2001-2006, Joe Orton <[email protected]>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "config.h"
  17. #ifdef HAVE_STDLIB_H
  18. #include <stdlib.h>
  19. #endif
  20. #ifdef HAVE_STRING_H
  21. #include <string.h>
  22. #endif
  23. #include "ne_uri.h"
  24. #include "ne_alloc.h"
  25. #include "tests.h"
  26. static int simple(void)
  27. {
  28. ne_uri p = {0};
  29. ON(ne_uri_parse("http://www.webdav.org/foo", &p));
  30. ON(strcmp(p.host, "www.webdav.org"));
  31. ON(strcmp(p.path, "/foo"));
  32. ON(strcmp(p.scheme, "http"));
  33. ON(p.port);
  34. ON(p.userinfo != NULL);
  35. ne_uri_free(&p);
  36. return 0;
  37. }
  38. static int simple_ssl(void)
  39. {
  40. ne_uri p = {0};
  41. ON(ne_uri_parse("https://webdav.org/", &p));
  42. ON(strcmp(p.scheme, "https"));
  43. ON(p.port);
  44. ne_uri_free(&p);
  45. return OK;
  46. }
  47. static int no_path(void)
  48. {
  49. ne_uri p = {0};
  50. ON(ne_uri_parse("https://webdav.org", &p));
  51. ON(strcmp(p.path, "/"));
  52. ne_uri_free(&p);
  53. return OK;
  54. }
  55. static int escapes(void)
  56. {
  57. static const struct {
  58. const char *plain, *escaped;
  59. unsigned int flags;
  60. } paths[] = {
  61. { "/foo%", "/foo%25", 0 },
  62. { "/foo bar", "/foo%20bar", 0, },
  63. { "/foo_bar", "/foo_bar", 0 },
  64. { "/foobar", "/foobar", 0 },
  65. { "/a\xb9\xb2\xb3\xbc\xbd/", "/a%b9%b2%b3%bc%bd/", 0 },
  66. { "/foo%20\xb9\xb2\xb3\xbc\xbd/", "/foo%20%b9%b2%b3%bc%bd/", NE_PATH_NONURI },
  67. { "/foo bar/", "/foo%20bar/", NE_PATH_NONURI },
  68. { "/foo:bar", "/foo:bar", NE_PATH_NONPC },
  69. { "/a#b:2", "/a%23b:2", NE_PATH_NONPC },
  70. { "/a#b:2", "/a%23b:2", 0 },
  71. { "/a?b:c$d", "/a%3fb:c$d", NE_PATH_NONPC },
  72. { NULL, NULL}
  73. };
  74. size_t n;
  75. for (n = 0; paths[n].plain; n++) {
  76. char *esc;
  77. if (paths[n].flags)
  78. esc = ne_path_escapef(paths[n].plain, paths[n].flags);
  79. else
  80. esc = ne_path_escape(paths[n].plain);
  81. ONCMP(paths[n].escaped, esc, paths[n].plain, "escaped form");
  82. if (!paths[n].flags) {
  83. char *un = ne_path_unescape(esc);
  84. ONCMP(paths[n].plain, un, paths[n].plain, "unescape");
  85. ne_free(un);
  86. }
  87. ne_free(esc);
  88. }
  89. ONN("unescape accepted invalid URI",
  90. ne_path_unescape("/foo%zzbar") != NULL);
  91. ONN("unescape accepted invalid URI",
  92. ne_path_unescape("/foo%1zbar") != NULL);
  93. return OK;
  94. }
  95. static int parents(void)
  96. {
  97. static const struct {
  98. const char *path, *parent;
  99. } ps[] = {
  100. { "/a/b/c", "/a/b/" },
  101. { "/a/b/c/", "/a/b/" },
  102. { "/alpha/beta", "/alpha/" },
  103. { "/foo", "/" },
  104. { "norman", NULL },
  105. { "/", NULL },
  106. { "", NULL },
  107. { NULL, NULL }
  108. };
  109. int n;
  110. for (n = 0; ps[n].path != NULL; n++) {
  111. char *p = ne_path_parent(ps[n].path);
  112. if (ps[n].parent == NULL) {
  113. ONV(p != NULL, ("parent of `%s' was `%s' not NULL",
  114. ps[n].path, p));
  115. } else {
  116. ONV(p == NULL, ("parent of `%s' was NULL", ps[n].path));
  117. ONV(strcmp(p, ps[n].parent),
  118. ("parent of `%s' was `%s' not `%s'",
  119. ps[n].path, p, ps[n].parent));
  120. ne_free(p);
  121. }
  122. }
  123. return OK;
  124. }
  125. static int compares(void)
  126. {
  127. const char *alpha = "/alpha";
  128. ON(ne_path_compare("/a", "/a/") != 0);
  129. ON(ne_path_compare("/a/", "/a") != 0);
  130. ON(ne_path_compare("/ab", "/a/") == 0);
  131. ON(ne_path_compare("/a/", "/ab") == 0);
  132. ON(ne_path_compare("/a/", "/a/") != 0);
  133. ON(ne_path_compare("/alpha/", "/beta/") == 0);
  134. ON(ne_path_compare("/alpha", "/b") == 0);
  135. ON(ne_path_compare("/alpha/", "/alphash") == 0);
  136. ON(ne_path_compare("/fish/", "/food") == 0);
  137. ON(ne_path_compare(alpha, alpha) != 0);
  138. ON(ne_path_compare("/a/b/c/d", "/a/b/c/") == 0);
  139. return OK;
  140. }
  141. static int cmp(void)
  142. {
  143. static const struct {
  144. const char *left, *right;
  145. } eq[] = {
  146. { "http://example.com/alpha", "http://example.com/alpha" },
  147. { "//example.com/alpha", "//example.com/alpha" },
  148. { "http://example.com/alpha#foo", "http://example.com/alpha#foo" },
  149. { "http://example.com/alpha?bar", "http://example.com/alpha?bar" },
  150. { "http://[email protected]/alpha", "http://[email protected]/alpha" },
  151. { "HTTP://example.com/alpha", "http://example.com/alpha" },
  152. { "http://example.com/", "http://example.com" },
  153. { "http://Example.Com/", "http://example.com" },
  154. { NULL, NULL}
  155. }, diff[] = {
  156. { "http://example.com/alpha", "http://example.com/beta" },
  157. { "http://example.com/alpha", "https://example.com/alpha" },
  158. { "http://example.com/alpha", "http://www.example.com/alpha" },
  159. { "http://example.com:443/alpha", "http://example.com:8080/alpha" },
  160. { "http://example.com/alpha", "http://[email protected]/alpha" },
  161. { "http://[email protected]/alpha", "http://[email protected]/alpha" },
  162. { "http://example.com/alpha", "http://example.com/alpha?fish" },
  163. { "http://example.com/alpha?fish", "http://example.com/alpha?food" },
  164. { "http://example.com/alpha", "http://example.com/alpha#foo" },
  165. { "http://example.com/alpha#bar", "http://example.com/alpha#foo" },
  166. { "http://example.com/alpha", "//example.com/alpha" },
  167. { "http://example.com/alpha", "///alpha" },
  168. { NULL, NULL}
  169. };
  170. size_t n;
  171. for (n = 0; eq[n].left; n++) {
  172. ne_uri alpha, beta;
  173. int r1, r2;
  174. ONV(ne_uri_parse(eq[n].left, &alpha),
  175. ("could not parse left URI '%s'", eq[n].left));
  176. ONV(ne_uri_parse(eq[n].right, &beta),
  177. ("could not parse right URI '%s'", eq[n].right));
  178. r1 = ne_uri_cmp(&alpha, &beta);
  179. r2 = ne_uri_cmp(&beta, &alpha);
  180. ONV(r1 != 0,
  181. ("cmp('%s', '%s') = %d not zero",
  182. eq[n].left, eq[n].right, r1));
  183. ONV(r2 != 0,
  184. ("cmp('%s', '%s') = %d not zero",
  185. eq[n].right, eq[n].left, r2));
  186. ne_uri_free(&alpha);
  187. ne_uri_free(&beta);
  188. }
  189. for (n = 0; diff[n].left; n++) {
  190. ne_uri alpha, beta;
  191. int r1, r2;
  192. ONV(ne_uri_parse(diff[n].left, &alpha),
  193. ("could not parse left URI '%s'", diff[n].left));
  194. ONV(ne_uri_parse(diff[n].right, &beta),
  195. ("could not parse right URI '%s'", diff[n].right));
  196. r1 = ne_uri_cmp(&alpha, &beta);
  197. r2 = ne_uri_cmp(&beta, &alpha);
  198. ONV(r1 == 0,
  199. ("'%s' and '%s' did not compare as different",
  200. diff[n].left, diff[n].right));
  201. ONV(((r1 > 0) != (r2 < 0) || (r1 < 0) != (r2 > 0)),
  202. ("'%s' and '%s' did not compare reflexively (%d vs %d)",
  203. diff[n].left, diff[n].right, r1, r2));
  204. ne_uri_free(&alpha);
  205. ne_uri_free(&beta);
  206. }
  207. return OK;
  208. }
  209. static int children(void)
  210. {
  211. ON(ne_path_childof("/a", "/a/b") == 0);
  212. ON(ne_path_childof("/a/", "/a/b") == 0);
  213. ON(ne_path_childof("/aa/b/c", "/a/b/c/d/e") != 0);
  214. ON(ne_path_childof("////", "/a") != 0);
  215. return OK;
  216. }
  217. static int slash(void)
  218. {
  219. ON(ne_path_has_trailing_slash("/a/") == 0);
  220. ON(ne_path_has_trailing_slash("/a") != 0);
  221. {
  222. /* check the uri == "" case. */
  223. char *foo = "/";
  224. ON(ne_path_has_trailing_slash(&foo[1]));
  225. }
  226. return OK;
  227. }
  228. static int default_port(void)
  229. {
  230. ONN("default http: port incorrect", ne_uri_defaultport("http") != 80);
  231. ONN("default https: port incorrect", ne_uri_defaultport("https") != 443);
  232. ONN("unspecified scheme: port incorrect", ne_uri_defaultport("ldap") != 0);
  233. return OK;
  234. }
  235. static int parse(void)
  236. {
  237. static const struct test_uri {
  238. const char *uri, *scheme, *host;
  239. unsigned int port;
  240. const char *path, *userinfo, *query, *fragment;
  241. } uritests[] = {
  242. { "http://webdav.org/norman", "http", "webdav.org", 0, "/norman", NULL, NULL, NULL },
  243. { "http://webdav.org:/norman", "http", "webdav.org", 0, "/norman", NULL, NULL, NULL },
  244. { "https://webdav.org/foo", "https", "webdav.org", 0, "/foo", NULL, NULL, NULL },
  245. { "http://webdav.org:8080/bar", "http", "webdav.org", 8080, "/bar", NULL, NULL, NULL },
  246. { "http://a/b", "http", "a", 0, "/b", NULL, NULL, NULL },
  247. { "http://webdav.org/bar:fish", "http", "webdav.org", 0, "/bar:fish", NULL, NULL, NULL },
  248. { "http://webdav.org", "http", "webdav.org", 0, "/", NULL, NULL, NULL },
  249. { "http://webdav.org/fish@food", "http", "webdav.org", 0, "/fish@food", NULL, NULL, NULL },
  250. /* query/fragments */
  251. { "http://foo/bar?alpha", "http", "foo", 0, "/bar", NULL, "alpha", NULL },
  252. { "http://foo/bar?alpha#beta", "http", "foo", 0, "/bar", NULL, "alpha", "beta" },
  253. { "http://foo/bar#alpha?beta", "http", "foo", 0, "/bar", NULL, NULL, "alpha?beta" },
  254. { "http://foo/bar#beta", "http", "foo", 0, "/bar", NULL, NULL, "beta" },
  255. { "http://foo/bar?#beta", "http", "foo", 0, "/bar", NULL, "", "beta" },
  256. { "http://foo/bar?alpha?beta", "http", "foo", 0, "/bar", NULL, "alpha?beta", NULL },
  257. { "http://foo?alpha", "http", "foo", 0, "/", NULL, "alpha", NULL },
  258. { "http://foo#beta", "http", "foo", 0, "/", NULL, NULL, "beta" },
  259. /* Examples from RFC3986§1.1.2: */
  260. { "ftp://ftp.is.co.za/rfc/rfc1808.txt", "ftp", "ftp.is.co.za", 0, "/rfc/rfc1808.txt", NULL, NULL, NULL },
  261. { "http://www.ietf.org/rfc/rfc2396.txt", "http", "www.ietf.org", 0, "/rfc/rfc2396.txt", NULL, NULL, NULL },
  262. { "ldap://[2001:db8::7]/c=GB?objectClass?one", "ldap", "[2001:db8::7]", 0, "/c=GB", NULL, "objectClass?one", NULL },
  263. { "mailto:[email protected]", "mailto", NULL, 0, "[email protected]", NULL, NULL, NULL },
  264. { "news:comp.infosystems.www.servers.unix", "news", NULL, 0, "comp.infosystems.www.servers.unix", NULL, NULL, NULL },
  265. { "tel:+1-816-555-1212", "tel", NULL, 0, "+1-816-555-1212", NULL, NULL, NULL },
  266. { "telnet://192.0.2.16:80/", "telnet", "192.0.2.16", 80, "/", NULL, NULL, NULL },
  267. { "urn:oasis:names:specification:docbook:dtd:xml:4.1.2", "urn", NULL, 0,
  268. "oasis:names:specification:docbook:dtd:xml:4.1.2", NULL},
  269. /* userinfo */
  270. { "ftp://jim:[email protected]", "ftp", "jim.com", 0, "/", "jim:bob", NULL, NULL },
  271. { "ldap://fred:[email protected]/foobar", "ldap", "fish.com", 0,
  272. "/foobar", "fred:bloggs", NULL, NULL },
  273. /* IPv6 literals: */
  274. { "http://[::1]/foo", "http", "[::1]", 0, "/foo", NULL, NULL, NULL },
  275. { "http://[a:a:a:a::0]/foo", "http", "[a:a:a:a::0]", 0, "/foo", NULL, NULL, NULL },
  276. { "http://[::1]:8080/bar", "http", "[::1]", 8080, "/bar", NULL, NULL, NULL },
  277. { "ftp://[feed::cafe]:555", "ftp", "[feed::cafe]", 555, "/", NULL, NULL, NULL },
  278. /* Test RFC 6874 syntax, an extension of RFC 3987. */
  279. { "http://[fe80::cafe%25eth0]:555", "http", "[fe80::cafe%25eth0]", 555, "/", NULL, NULL, NULL },
  280. { "http://[fe80::cafe%251]:555", "http", "[fe80::cafe%251]", 555, "/", NULL, NULL, NULL },
  281. { "DAV:", "DAV", NULL, 0, "", NULL, NULL, NULL },
  282. /* Some odd cases: heir-part and relative-ref will both match
  283. * with a zero-length expansion of "authority" (since *
  284. * reg-name can be zero-length); so a triple-slash URI-ref
  285. * will be matched as "//" followed by a zero-length authority
  286. * followed by a path of "/". */
  287. { "foo:///", "foo", "", 0, "/", NULL, NULL, NULL },
  288. { "///", NULL, "", 0, "/", NULL, NULL, NULL },
  289. /* port grammar is "*DIGIT" so may be empty: */
  290. { "ftp://[feed::cafe]:", "ftp", "[feed::cafe]", 0, "/", NULL, NULL, NULL },
  291. { "ftp://[feed::cafe]:/", "ftp", "[feed::cafe]", 0, "/", NULL, NULL, NULL },
  292. { "http://foo:/", "http", "foo", 0, "/", NULL, NULL, NULL },
  293. /* URI-references: */
  294. { "//foo.com/bar", NULL, "foo.com", 0, "/bar", NULL, NULL, NULL },
  295. { "//foo.com", NULL, "foo.com", 0, "/", NULL, NULL, NULL },
  296. { "//[::1]/foo", NULL, "[::1]", 0, "/foo", NULL, NULL, NULL },
  297. { "/bar", NULL, NULL, 0, "/bar", NULL, NULL, NULL }, /* path-absolute */
  298. { "foo/bar", NULL, NULL, 0, "foo/bar", NULL, NULL, NULL }, /* path-noscheme */
  299. { "", NULL, NULL, 0, "", NULL, NULL, NULL }, /* path-empty */
  300. /* CVE-2007-0157: buffer under-read in 0.26.[012]. */
  301. { "http://webdav.org\xFF", "http", "webdav.org\xFF", 0, "/", NULL, NULL, NULL },
  302. { NULL }
  303. };
  304. int n;
  305. for (n = 0; uritests[n].uri != NULL; n++) {
  306. ne_uri res;
  307. const struct test_uri *e = &uritests[n];
  308. ONV(ne_uri_parse(e->uri, &res) != 0,
  309. ("'%s': parse failed", e->uri));
  310. ONV(res.port != e->port,
  311. ("'%s': parsed port was %d not %d", e->uri, res.port, e->port));
  312. ONCMP(e->scheme, res.scheme, e->uri, "scheme");
  313. ONCMP(e->host, res.host, e->uri, "host");
  314. ONV(strcmp(res.path, e->path),
  315. ("'%s': parsed path was '%s' not '%s'", e->uri, res.path, e->path));
  316. ONCMP(e->userinfo, res.userinfo, e->uri, "userinfo");
  317. ONCMP(e->query, res.query, e->uri, "query");
  318. ONCMP(e->fragment, res.fragment, e->uri, "fragment");
  319. ne_uri_free(&res);
  320. }
  321. return OK;
  322. }
  323. static int failparse(void)
  324. {
  325. static const char *uris[] = {
  326. "http://[::1/",
  327. "http://[::1]f:80/",
  328. "http://[::1]]:80/",
  329. "http://foo/bar asda",
  330. "http://fish/[foo]/bar",
  331. "http://foo:80bar",
  332. "http://foo:80:80/bar",
  333. "http://foo:8000000000000000000000000000000000000000000000000/bar",
  334. "http://foo:65536/bar",
  335. NULL
  336. };
  337. int n;
  338. for (n = 0; uris[n] != NULL; n++) {
  339. ne_uri p;
  340. ONV(ne_uri_parse(uris[n], &p) == 0,
  341. ("`%s' did not fail to parse", uris[n]));
  342. ne_uri_free(&p);
  343. }
  344. return 0;
  345. }
  346. static int unparse(void)
  347. {
  348. const char *uris[] = {
  349. "http://foo.com/bar",
  350. "https://bar.com/foo/wishbone",
  351. "http://www.random.com:8000/",
  352. "http://[::1]:8080/",
  353. "ftp://ftp.foo.bar/abc/def",
  354. "ftp://[email protected]/abc/def",
  355. "http://a/b?c#d",
  356. "http://a/b?c",
  357. "http://a/b#d",
  358. "mailto:[email protected]",
  359. "//foo.com/bar",
  360. "//foo.com:8080/bar",
  361. NULL
  362. };
  363. int n;
  364. for (n = 0; uris[n] != NULL; n++) {
  365. ne_uri parsed;
  366. char *unp;
  367. ONV(ne_uri_parse(uris[n], &parsed),
  368. ("failed to parse %s", uris[n]));
  369. if (parsed.port == 0 && parsed.scheme)
  370. parsed.port = ne_uri_defaultport(parsed.scheme);
  371. unp = ne_uri_unparse(&parsed);
  372. ONV(strcmp(unp, uris[n]),
  373. ("unparse got %s from %s", unp, uris[n]));
  374. ne_uri_free(&parsed);
  375. ne_free(unp);
  376. }
  377. return OK;
  378. }
  379. #define BASE "http://a/b/c/d;p?q"
  380. static int resolve(void)
  381. {
  382. static const struct {
  383. const char *base, *relative, *expected;
  384. } ts[] = {
  385. /* Examples from RFC3986§5.4: */
  386. { BASE, "g:h", "g:h" },
  387. { BASE, "g", "http://a/b/c/g" },
  388. { BASE, "./g", "http://a/b/c/g" },
  389. { BASE, "g/", "http://a/b/c/g/" },
  390. { BASE, "/g", "http://a/g" },
  391. { BASE, "//g", "http://g/" }, /* NOTE: modified to mandate non-empty path */
  392. { BASE, "?y", "http://a/b/c/d;p?y" },
  393. { BASE, "g?y", "http://a/b/c/g?y" },
  394. { BASE, "#s", "http://a/b/c/d;p?q#s" },
  395. { BASE, "g#s", "http://a/b/c/g#s" },
  396. { BASE, "g?y#s", "http://a/b/c/g?y#s" },
  397. { BASE, ";x", "http://a/b/c/;x" },
  398. { BASE, "g;x", "http://a/b/c/g;x" },
  399. { BASE, "g;x?y#s", "http://a/b/c/g;x?y#s" },
  400. { BASE, "", "http://a/b/c/d;p?q" },
  401. { BASE, ".", "http://a/b/c/" },
  402. { BASE, "./", "http://a/b/c/" },
  403. { BASE, "..", "http://a/b/" },
  404. { BASE, "../", "http://a/b/" },
  405. { BASE, "../g", "http://a/b/g" },
  406. { BASE, "../..", "http://a/" },
  407. { BASE, "../../", "http://a/" },
  408. { BASE, "../../g", "http://a/g" },
  409. { BASE, "../../../g", "http://a/g" },
  410. { BASE, "../../../../g", "http://a/g" },
  411. { BASE, "/./g", "http://a/g" },
  412. { BASE, "/../g", "http://a/g" },
  413. { BASE, "g.", "http://a/b/c/g." },
  414. { BASE, ".g", "http://a/b/c/.g" },
  415. { BASE, "g..", "http://a/b/c/g.." },
  416. { BASE, "..g", "http://a/b/c/..g" },
  417. { BASE, "./../g", "http://a/b/g" },
  418. { BASE, "./g/.", "http://a/b/c/g/" },
  419. { BASE, "g/./h", "http://a/b/c/g/h" },
  420. { BASE, "g/../h", "http://a/b/c/h" },
  421. { BASE, "g;x=1/./y", "http://a/b/c/g;x=1/y" },
  422. { BASE, "g;x=1/../y", "http://a/b/c/y" },
  423. { BASE, "g?y/./x", "http://a/b/c/g?y/./x" },
  424. { BASE, "g?y/../x", "http://a/b/c/g?y/../x" },
  425. { BASE, "g#s/./x", "http://a/b/c/g#s/./x" },
  426. { BASE, "g#s/../x", "http://a/b/c/g#s/../x" },
  427. { BASE, "http:g", "http:g" },
  428. /* Additional examples: */
  429. { BASE, ".", "http://a/b/c/" },
  430. { "http://foo.com/alpha/beta", "../gamma", "http://foo.com/gamma" },
  431. { "http://foo.com/alpha//beta", "../gamma", "http://foo.com/alpha/gamma" },
  432. { "http://foo.com", "../gamma", "http://foo.com/gamma" },
  433. { "", "zzz:.", "zzz:" },
  434. { "", "zzz:./foo", "zzz:foo" },
  435. { "", "zzz:../foo", "zzz:foo" },
  436. { "", "zzz:/./foo", "zzz:/foo" },
  437. { "", "zzz:/.", "zzz:/" },
  438. { "", "zzz:/../", "zzz:/" },
  439. { "", "zzz:.", "zzz:" },
  440. { "", "zzz:..", "zzz:" },
  441. { "", "zzz://foo@bar/", "zzz://foo@bar/" },
  442. { "", "zzz://foo/?bar", "zzz://foo/?bar" },
  443. { "zzz://foo/?bar", "//baz/?jam", "zzz://baz/?jam" },
  444. { "zzz://foo/baz?biz", "", "zzz://foo/baz?biz" },
  445. { "zzz://foo/baz", "", "zzz://foo/baz" },
  446. { "//foo/baz", "", "//foo/baz" },
  447. { NULL, NULL, NULL }
  448. };
  449. size_t n;
  450. for (n = 0; ts[n].base; n++) {
  451. ne_uri base, relative, resolved;
  452. char *actual;
  453. ONV(ne_uri_parse(ts[n].base, &base),
  454. ("could not parse base URI '%s'", ts[n].base));
  455. ONV(ne_uri_parse(ts[n].relative, &relative),
  456. ("could not parse input URI '%s'", ts[n].relative));
  457. ONN("bad pointer was returned",
  458. ne_uri_resolve(&base, &relative, &resolved) != &resolved);
  459. ONN("NULL path after resolve", resolved.path == NULL);
  460. actual = ne_uri_unparse(&resolved);
  461. ONCMP(ts[n].expected, actual, ts[n].relative, "output mismatch");
  462. ne_uri_free(&relative);
  463. ne_uri_free(&resolved);
  464. ne_uri_free(&base);
  465. ne_free(actual);
  466. }
  467. return OK;
  468. }
  469. static int copy(void)
  470. {
  471. static const char *ts[] = {
  472. "http://[email protected]:8080/bar?baz#bee",
  473. "",
  474. NULL,
  475. };
  476. size_t n;
  477. for (n = 0; ts[n]; n++) {
  478. ne_uri parsed, parsed2;
  479. char *actual;
  480. ONV(ne_uri_parse(ts[n], &parsed), ("could not parse URI '%s'", ts[n]));
  481. ONN("ne_uri_copy returned wrong pointer",
  482. ne_uri_copy(&parsed2, &parsed) != &parsed2);
  483. actual = ne_uri_unparse(&parsed2);
  484. ONCMP(ts[n], actual, "copied URI", "unparsed URI");
  485. ne_uri_free(&parsed2);
  486. ne_uri_free(&parsed);
  487. ne_free(actual);
  488. }
  489. return OK;
  490. }
  491. ne_test tests[] = {
  492. T(simple),
  493. T(simple_ssl),
  494. T(no_path),
  495. T(escapes),
  496. T(parents),
  497. T(compares),
  498. T(cmp),
  499. T(children),
  500. T(slash),
  501. T(default_port),
  502. T(parse),
  503. T(failparse),
  504. T(unparse),
  505. T(resolve),
  506. T(copy),
  507. T(NULL)
  508. };