PageRenderTime 52ms CodeModel.GetById 13ms app.highlight 33ms RepoModel.GetById 2ms app.codeStats 0ms

/mordor/tests/uri.cpp

http://github.com/mozy/mordor
C++ | 510 lines | 439 code | 53 blank | 18 comment | 3 complexity | 7f787a5a8f7f53212c30416363585571 MD5 | raw file
  1// Copyright (c) 2009 - Mozy, Inc.
  2
  3#include "mordor/uri.h"
  4#include "mordor/streams/buffer.h"
  5#include "mordor/test/test.h"
  6
  7using namespace Mordor;
  8using namespace Mordor::Test;
  9
 10static void serializeAndParse(const char *uri, const char *expected = NULL)
 11{
 12    if (!expected) expected = uri;
 13    MORDOR_TEST_ASSERT_EQUAL(URI(uri).toString(), expected);
 14}
 15
 16MORDOR_UNITTEST(URI, serializationAndParsing)
 17{
 18    MORDOR_TEST_ASSERT_EQUAL(URI::Path("/a/b/c/./../../g").toString(),
 19        "/a/b/c/./../../g");
 20    serializeAndParse("example://a/b/c/%7Bfoo%7D");
 21    serializeAndParse("eXAMPLE://a/./b/../b/%63/%7bfoo%7d", "eXAMPLE://a/./b/../b/c/%7Bfoo%7D");
 22    serializeAndParse("http://a/b/c/d;p?q");
 23    serializeAndParse("g:h");
 24    serializeAndParse("g");
 25    serializeAndParse("http://a/b/c/g");
 26    serializeAndParse("./g");
 27    serializeAndParse("g/");
 28    serializeAndParse("http://a/b/c/g/");
 29    serializeAndParse("/g");
 30    serializeAndParse("http://a/g");
 31    serializeAndParse("//g");
 32    serializeAndParse("http://g");
 33    serializeAndParse("?y");
 34    serializeAndParse("http://a/b/c/d;p?y");
 35    serializeAndParse("g?y");
 36    serializeAndParse("http://a/b/c/g?y");
 37    serializeAndParse("#s");
 38    serializeAndParse("http://a/b/c/d;p?q#s");
 39    serializeAndParse("g#s");
 40    serializeAndParse("http://a/b/c/g#s");
 41    serializeAndParse("g?y#s");
 42    serializeAndParse("http://a/b/c/g?y#s");
 43    serializeAndParse(";x");
 44    serializeAndParse("http://a/b/c/;x");
 45    serializeAndParse("g;x");
 46    serializeAndParse("http://a/b/c/g;x");
 47    serializeAndParse("g;x?y#s");
 48    serializeAndParse("http://a/b/c/g;x?y#s");
 49    serializeAndParse("");
 50    serializeAndParse("http://a/b/c/d;p?q");
 51    serializeAndParse(".");
 52    serializeAndParse("http://a/b/c/");
 53    serializeAndParse("./");
 54    serializeAndParse("..");
 55    serializeAndParse("http://a/b/");
 56    serializeAndParse("../");
 57    serializeAndParse("../g");
 58    serializeAndParse("http://a/b/g");
 59    serializeAndParse("../..");
 60    serializeAndParse("http://a/");
 61    serializeAndParse("../../");
 62    serializeAndParse("../../g");
 63    serializeAndParse("http://a/g");
 64    serializeAndParse("../../../g");
 65    serializeAndParse("../../../../g");
 66    serializeAndParse("/./g");
 67    serializeAndParse("/../g");
 68    serializeAndParse("g.");
 69    serializeAndParse("http://a/b/c/g.");
 70    serializeAndParse(".g");
 71    serializeAndParse("http://a/b/c/.g");
 72    serializeAndParse("g..");
 73    serializeAndParse("http://a/b/c/g..");
 74    serializeAndParse("..g");
 75    serializeAndParse("http://a/b/c/..g");
 76    serializeAndParse("./../g");
 77    serializeAndParse("./g/.");
 78    serializeAndParse("http://a/b/c/g/");
 79    serializeAndParse("g/./h");
 80    serializeAndParse("http://a/b/c/g/h");
 81    serializeAndParse("g/../h");
 82    serializeAndParse("http://a/b/c/h");
 83    serializeAndParse("g;x=1/./y");
 84    serializeAndParse("http://a/b/c/g;x=1/y");
 85    serializeAndParse("g;x=1/../y");
 86    serializeAndParse("http://a/b/c/y");
 87    serializeAndParse("g?y/./x");
 88    serializeAndParse("http://a/b/c/g?y/./x");
 89    serializeAndParse("g?y/../x");
 90    serializeAndParse("http://a/b/c/g?y/../x");
 91    serializeAndParse("g#s/./x");
 92    serializeAndParse("http://a/b/c/g#s/./x");
 93    serializeAndParse("g#s/../x");
 94    serializeAndParse("http://a/b/c/g#s/../x");
 95    serializeAndParse("http:g");
 96    serializeAndParse("http:/hi");
 97    serializeAndParse("http:////hi");
 98}
 99
100MORDOR_UNITTEST(URI, pathNormalization)
101{
102    URI::Path p("/a/b/c/./../../g");
103    p.removeDotComponents();
104    MORDOR_TEST_ASSERT_EQUAL(p, URI::Path("/a/g"));
105}
106
107MORDOR_UNITTEST(URI, normalization)
108{
109    URI lhs("example://a/b/c/%7Bfoo%7D");
110    URI rhs("eXAMPLE://a/./b/../b/%63/%7bfoo%7d");
111
112    lhs.normalize();
113    rhs.normalize();
114
115    MORDOR_TEST_ASSERT(lhs.isDefined());
116    MORDOR_TEST_ASSERT(rhs.isDefined());
117    MORDOR_TEST_ASSERT(lhs.schemeDefined());
118    MORDOR_TEST_ASSERT(rhs.schemeDefined());
119    MORDOR_TEST_ASSERT_EQUAL(lhs.scheme(), rhs.scheme());
120    MORDOR_TEST_ASSERT(!lhs.authority.portDefined());
121    MORDOR_TEST_ASSERT(!rhs.authority.portDefined());
122    MORDOR_TEST_ASSERT(lhs.authority.hostDefined());
123    MORDOR_TEST_ASSERT(rhs.authority.hostDefined());
124    MORDOR_TEST_ASSERT_EQUAL(lhs.authority.host(), rhs.authority.host());
125    MORDOR_TEST_ASSERT(!lhs.authority.userinfoDefined());
126    MORDOR_TEST_ASSERT(!rhs.authority.userinfoDefined());
127    MORDOR_TEST_ASSERT_EQUAL(lhs.authority, rhs.authority);
128    MORDOR_TEST_ASSERT_EQUAL(lhs.path.segments, rhs.path.segments);
129    MORDOR_TEST_ASSERT_EQUAL(lhs.path, rhs.path);
130    MORDOR_TEST_ASSERT(!lhs.queryDefined());
131    MORDOR_TEST_ASSERT(!rhs.queryDefined());
132    MORDOR_TEST_ASSERT(!lhs.fragmentDefined());
133    MORDOR_TEST_ASSERT(!rhs.fragmentDefined());
134    MORDOR_TEST_ASSERT_EQUAL(lhs, rhs);
135}
136
137MORDOR_UNITTEST(URI, transform)
138{
139    URI base("http://a/b/c/d;p?q");
140    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g:h")), URI("g:h"));
141    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g")), URI("http://a/b/c/g"));
142    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("./g")), URI("http://a/b/c/g"));
143    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g/")), URI("http://a/b/c/g/"));
144    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("/g")), URI("http://a/g"));
145    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("//g")), URI("http://g"));
146    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("?y")), URI("http://a/b/c/d;p?y"));
147    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g?y")), URI("http://a/b/c/g?y"));
148    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("#s")), URI("http://a/b/c/d;p?q#s"));
149    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g#s")), URI("http://a/b/c/g#s"));
150    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g?y#s")), URI("http://a/b/c/g?y#s"));
151    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI(";x")), URI("http://a/b/c/;x"));
152    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g;x")), URI("http://a/b/c/g;x"));
153    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g;x?y#s")), URI("http://a/b/c/g;x?y#s"));
154    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("")), URI("http://a/b/c/d;p?q"));
155    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI(".")), URI("http://a/b/c/"));
156    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("./")), URI("http://a/b/c/"));
157    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("..")), URI("http://a/b/"));
158    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("../")), URI("http://a/b/"));
159    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("../g")), URI("http://a/b/g"));
160    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("../..")), URI("http://a/"));
161    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("../../")), URI("http://a/"));
162    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("../../g")), URI("http://a/g"));
163
164    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("../../../g")), URI("http://a/g"));
165    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("../../../../g")), URI("http://a/g"));
166
167    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("/./g")), URI("http://a/g"));
168    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("/../g")), URI("http://a/g"));
169    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g.")), URI("http://a/b/c/g."));
170    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI(".g")), URI("http://a/b/c/.g"));
171    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g..")), URI("http://a/b/c/g.."));
172    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("..g")), URI("http://a/b/c/..g"));
173
174    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("./../g")), URI("http://a/b/g"));
175    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("./g/.")), URI("http://a/b/c/g/"));
176    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g/./h")), URI("http://a/b/c/g/h"));
177    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g/../h")), URI("http://a/b/c/h"));
178    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g;x=1/./y")), URI("http://a/b/c/g;x=1/y"));
179    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g;x=1/../y")), URI("http://a/b/c/y"));
180
181    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g?y/./x")), URI("http://a/b/c/g?y/./x"));
182    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g?y/../x")), URI("http://a/b/c/g?y/../x"));
183    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g#s/./x")), URI("http://a/b/c/g#s/./x"));
184    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("g#s/../x")), URI("http://a/b/c/g#s/../x"));
185
186    MORDOR_TEST_ASSERT_EQUAL(URI::transform(base, URI("http:g")), URI("http:g"));
187
188    MORDOR_TEST_ASSERT_EQUAL(URI::transform("http:hi", "bob"), "http:bob");
189    MORDOR_TEST_ASSERT_EQUAL(URI::transform("http://authority", "bob"), "http://authority/bob");
190}
191
192MORDOR_UNITTEST(URI, serializeCompleteOnBlockBoundary)
193{
194    Buffer b("http://abc/");
195    b.copyIn("more");
196    URI uri(b);
197    MORDOR_TEST_ASSERT_EQUAL(URI(b), "http://abc/more");
198}
199
200MORDOR_UNITTEST(URI, bigBase64URI)
201{
202    serializeAndParse("/partialObjects/"
203        "49ZtbkNPlEEi8T+sQLb5mh9zm1DcyaaRoyHUOC9sEfaKIgLh+eKZNUrqR+j3Iybhx321iz"
204        "y3J+Mw7gZmIlVcZrP0qHNDxuEQHMUHLqxhXoXcN18+x4XedNLqc8KhnJtHLXndcKMJu5Cg"
205        "xp2BI9NXDDDuBmYiVVxms/Soc0PG4RAcxQcurGFehSY0Wf0fG5eWquA0b0hozVjE4xxyAF"
206        "TkSU39Hl3XcsUUMO4GZiJVXGaz9KhzQ8bhEBzFBy6sYV6F9718Fox0OiJ3PqBvo2gr352W"
207        "vZBqmEeUV1n0CkcClc0w7gZmIlVcZrP0qHNDxuEQHMUHLqxhXoWapmDUfha0WO9SjTUn4F"
208        "Jeht8Gjdy6mYpDqvUbB+3OoDDuBmYiVVxms/Soc0PG4RAcxQcurGFehcefjKkVeAR2HShU"
209        "2UpBh5g/89ZP9czSJ8qKSKCPGyHWMO4GZiJVXGaz9KhzQ8bhEBzFBy6sYV6FAig0fJADqV"
210        "eInu5RU/pgEXJlZ1MBce/F+rv7MI3g5jgw7gZmIlVcZrP0qHNDxuEQHMUHLqxhXoW4GIxe"
211        "C1lnhkTtrAv3jhk17r3ZwL8Fq7CvpUHeAQl/JTDuBmYiVVxms/Soc0PG4RAcxQcurGFehc"
212        "s4fMw9uBwTihHQAPFbcyDTjZtTMGlaovGaP6xe1H1TMO4GZiJVXGaz9KhzQ8bhEBzFBy6s"
213        "YV6FFAhiH0dzP8E0IRZP+oxeL2JkfxiO5v8r7eWnYtMY8d4w7gZmIlVcZrP0qHNDxuEQHM"
214        "UHLqxhXoUgoQ1pQreM2tYMR9QaJ7CsSOSJs+Qi5KIzV50DBUYLDjDuBmYiVVxms/Soc0PG"
215        "4RAcxQcurGFehdeUg8nHldHqihIknc3OP/QRtBawAyEFY4p0RKlRxnA0MO4GZiJVXGaz9K"
216        "hzQ8bhEBzFBy6sYV6FbRY5v48No3N72yRSA9JiYPhS/YTYcUFz");
217}
218
219MORDOR_UNITTEST(URI, queryString)
220{
221    URI uri("http://a/b?a&b");
222    MORDOR_TEST_ASSERT(uri.queryDefined());
223    MORDOR_TEST_ASSERT_EQUAL(uri.query(), "a&b");
224    uri = "http://a/b?a%20b";
225    MORDOR_TEST_ASSERT(uri.queryDefined());
226    MORDOR_TEST_ASSERT_EQUAL(uri.query(), "a b");
227    URI::QueryString qs = uri.queryString();
228
229    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 1u);
230    MORDOR_TEST_ASSERT_EQUAL(qs.begin()->first, "a b");
231    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a+b");
232
233    qs = "a%2Bb";
234    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 1u);
235    MORDOR_TEST_ASSERT_EQUAL(qs.begin()->first, "a+b");
236    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a%2Bb");
237
238    qs = "a&b;c";
239    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 3u);
240    URI::QueryString::iterator it = qs.begin();
241    MORDOR_TEST_ASSERT_EQUAL(it->first, "a");
242    ++it;
243    MORDOR_TEST_ASSERT_EQUAL(it->first, "b");
244    ++it;
245    MORDOR_TEST_ASSERT_EQUAL(it->first, "c");
246
247    qs = "a+b";
248    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 1u);
249    MORDOR_TEST_ASSERT_EQUAL(qs.begin()->first, "a b");
250    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a+b");
251
252    qs = "";
253    MORDOR_TEST_ASSERT(qs.empty());
254    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "");
255
256    qs = "&&;&&;;&";
257    MORDOR_TEST_ASSERT(qs.empty());
258    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "");
259
260    qs = "a=b&c";
261    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 2u);
262    it = qs.begin();
263    MORDOR_TEST_ASSERT_EQUAL(it->first, "a");
264    MORDOR_TEST_ASSERT_EQUAL(it->second, "b");
265    ++it;
266    MORDOR_TEST_ASSERT_EQUAL(it->first, "c");
267
268    qs = "a=b=c=d&e=f=g=h";
269    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 2u);
270    it = qs.begin();
271    MORDOR_TEST_ASSERT_EQUAL(it->first, "a");
272    MORDOR_TEST_ASSERT_EQUAL(it->second, "b=c=d");
273    ++it;
274    MORDOR_TEST_ASSERT_EQUAL(it->first, "e");
275    MORDOR_TEST_ASSERT_EQUAL(it->second, "f=g=h");
276
277    qs = "a=";
278    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 1u);
279    it = qs.begin();
280    MORDOR_TEST_ASSERT_EQUAL(it->first, "a");
281    MORDOR_TEST_ASSERT(it->second.empty());
282
283    qs = "a=&=b&=";
284    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 2u);
285    it = qs.begin();
286    MORDOR_TEST_ASSERT(it->first.empty());
287    MORDOR_TEST_ASSERT_EQUAL(it->second, "b");
288    ++it;
289    MORDOR_TEST_ASSERT_EQUAL(it->first, "a");
290    MORDOR_TEST_ASSERT(it->second.empty());
291
292    qs.clear();
293    qs.insert(std::make_pair("ampersand", "and&and"));
294    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "ampersand=and%26and");
295
296    uri = URI();
297    uri.query(qs);
298    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "?ampersand=and%26and");
299}
300
301MORDOR_UNITTEST(URI, encoding)
302{
303    URI uri;
304    uri.path.segments.push_back(std::string());
305    uri.path.segments.push_back("WiX Tutorial \xe2\x80\x94 Introduction to the Windows Installer XML Toolset.URL");
306    MORDOR_TEST_ASSERT_EQUAL(uri.toString(),
307        "/WiX%20Tutorial%20%E2%80%94%20Introduction%20to%20the%20Windows%20Installer%20XML%20Toolset.URL");
308
309    uri.path.segments[1] = "\xe5\xa4\x9a\xe8\xa8\x80\xe8\xaa\x9e\xe5\xaf\xbe\xe5\xbf\x9c\xe3\x82"
310        "\xb5\xe3\x83\xbc\xe3\x83\x81\xe3\x82\xa8\xe3\x83\xb3\xe3\x82\xb8\xe3"
311        "\x83\xb3\xe3\x81\xae\xe6\x97\xa5\xe6\x9c\xac\xe7\x89\x88\xe3\x80\x82"
312        "\xe3\x82\xa6\xe3\x82\xa7\xe3\x83\x96\xe3\x80\x81\xe3\x82\xa4\xe3\x83"
313        "\xa1\xe3\x83\xbc\xe3\x82\xb8\xe3\x81\x8a\xe3\x82\x88\xe3\x81\xb3\xe3"
314        "\x83\x8b\xe3\x83\xa5\xe3\x83\xbc\xe3\x82\xb9\xe6\xa4\x9c\xe7\xb4\xa2.txt";
315    MORDOR_TEST_ASSERT_EQUAL(uri.toString(),
316        "/%E5%A4%9A%E8%A8%80%E8%AA%9E%E5%AF%BE%E5%BF%9C%E3%82"
317        "%B5%E3%83%BC%E3%83%81%E3%82%A8%E3%83%B3%E3%82%B8%E3"
318        "%83%B3%E3%81%AE%E6%97%A5%E6%9C%AC%E7%89%88%E3%80%82"
319        "%E3%82%A6%E3%82%A7%E3%83%96%E3%80%81%E3%82%A4%E3%83"
320        "%A1%E3%83%BC%E3%82%B8%E3%81%8A%E3%82%88%E3%81%B3%E3"
321        "%83%8B%E3%83%A5%E3%83%BC%E3%82%B9%E6%A4%9C%E7%B4%A2.txt");
322}
323
324MORDOR_UNITTEST(URI, emptyFirstComponent)
325{
326    serializeAndParse("/");
327    serializeAndParse("http://localhost/");
328    serializeAndParse("http://localhost//");
329    serializeAndParse("http://localhost///");
330
331    URI::Path path;
332    path = "/";
333    MORDOR_TEST_ASSERT_EQUAL(path.segments.size(), 2u);
334    MORDOR_TEST_ASSERT(path.isAbsolute());
335    MORDOR_TEST_ASSERT(path.segments.front().empty());
336    MORDOR_TEST_ASSERT(path.segments.back().empty());
337    path = "";
338    MORDOR_TEST_ASSERT(path.isRelative());
339    MORDOR_TEST_ASSERT(path.segments.empty());
340    path = "//";
341    MORDOR_TEST_ASSERT(path.isAbsolute());
342    MORDOR_TEST_ASSERT_EQUAL(path.segments.size(), 3u);
343    path = "a//";
344    MORDOR_TEST_ASSERT(path.isRelative());
345    MORDOR_TEST_ASSERT_EQUAL(path.segments.size(), 3u);
346
347    URI uri = "http://localhost/";
348    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "http://localhost/");
349    uri.path.append("hi");
350    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "http://localhost/hi");
351    uri.path.segments.push_back("");
352    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "http://localhost/hi/");
353    uri.path.segments.push_back("bye");
354    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "http://localhost/hi//bye");
355    uri.path.segments.push_back("");
356    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "http://localhost/hi//bye/");
357    uri.path.append("adios");
358    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "http://localhost/hi//bye/adios");
359    uri = "http://localhost/";
360    uri.path.append("hi");
361    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "http://localhost/hi");
362
363    // scheme == http, authority is not defined, path = "//hi";
364    // serialization has to add an extra // so it's not ambiguous with
365    // authority
366    uri = URI();
367    uri.scheme("http");
368    uri.path.segments.push_back(std::string());
369    uri.path.segments.push_back(std::string());
370    uri.path.segments.push_back("hi");
371    MORDOR_TEST_ASSERT_EQUAL(uri.toString(), "http:////hi");
372}
373
374MORDOR_UNITTEST(URI, append)
375{
376    URI uri = "http://localhost";
377    uri.path.append("hi");
378    MORDOR_TEST_ASSERT_EQUAL(uri, "http://localhost/hi");
379    uri.path.append("bye");
380    MORDOR_TEST_ASSERT_EQUAL(uri, "http://localhost/hi/bye");
381    uri.path.append(std::string());
382    MORDOR_TEST_ASSERT_EQUAL(uri, "http://localhost/hi/bye/");
383    uri.path.append(std::string());
384    MORDOR_TEST_ASSERT_EQUAL(uri, "http://localhost/hi/bye/");
385
386    uri = "http:";
387    uri.path.append("hi");
388    MORDOR_TEST_ASSERT_EQUAL(uri, "http:hi");
389    uri.path.append("bye");
390    MORDOR_TEST_ASSERT_EQUAL(uri, "http:hi/bye");
391
392    URI::Path path;
393    path.append("hi");
394    MORDOR_TEST_ASSERT_EQUAL(path, "hi");
395    path.append("bye");
396    MORDOR_TEST_ASSERT_EQUAL(path, "hi/bye");
397
398    // The following four tests ensure that path's hidden pointer back to the
399    // URI owning it is copied/assigned correctly through URI and Path's
400    // copy constructors and assignement operators
401
402    // Force operator=(const URI &uri)
403    URI uri2 = "http://localhost";
404    uri = uri2;
405    uri2.authority.hostDefined(false);
406    uri.path.append("hi");
407    MORDOR_TEST_ASSERT_EQUAL(uri, "http://localhost/hi");
408
409    // Force URI::URI(const URI &uri)
410    uri2.authority.host("localhost");
411    URI uri3(uri2);
412    uri2.authority.hostDefined(false);
413    uri3.path.append("hi");
414    MORDOR_TEST_ASSERT_EQUAL(uri3, "http://localhost/hi");
415
416    // Force operator=(const Path &path)
417    path = uri3.path;
418    path.segments.clear();
419    path.append("hi");
420    MORDOR_TEST_ASSERT_EQUAL(path, "hi");
421
422    // Force Path::Path(const Path &path)
423    URI::Path path2(uri3.path);
424    path2.segments.clear();
425    path2.append("hi");
426    MORDOR_TEST_ASSERT_EQUAL(path2, "hi");
427}
428
429MORDOR_UNITTEST(URI, makeAbsolute)
430{
431    URI::Path path;
432    path.makeAbsolute();
433    MORDOR_TEST_ASSERT_EQUAL(path, "/");
434    path.makeAbsolute();
435    MORDOR_TEST_ASSERT_EQUAL(path, "/");
436    path.makeRelative();
437    MORDOR_TEST_ASSERT(path.segments.empty());
438    path.makeRelative();
439    MORDOR_TEST_ASSERT(path.segments.empty());
440    path.append("hi");
441    MORDOR_TEST_ASSERT_EQUAL(path, "hi");
442    path.makeAbsolute();
443    MORDOR_TEST_ASSERT_EQUAL(path, "/hi");
444    path.makeAbsolute();
445    MORDOR_TEST_ASSERT_EQUAL(path, "/hi");
446    path.makeRelative();
447    MORDOR_TEST_ASSERT_EQUAL(path, "hi");
448    path.makeRelative();
449    MORDOR_TEST_ASSERT_EQUAL(path, "hi");
450}
451
452MORDOR_UNITTEST(URI, queryStringConvenience)
453{
454    URI::QueryString qs;
455    qs["a"] = "1";
456
457    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 1u);
458    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a=1");
459    qs.insert(std::make_pair("a", "2"));
460    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 2u);
461    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a=1&a=2");
462    // Returns only the first item (removing others)
463    qs["a"] = "3";
464    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 1u);
465    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a=3");
466    qs.insert(std::make_pair("a", "4"));
467    // Implicitly creates the item, even though we don't assign to it
468    MORDOR_TEST_ASSERT(qs["b"].empty());
469    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 3u);
470    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a=3&a=4&b");
471
472    // Make sure we're using equal_range correctly (insert between existing elements)
473    qs["a2"] = "5";
474    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 4u);
475    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a=3&a=4&a2=5&b");
476
477    // Create a const reference, so we call the const version
478    const URI::QueryString &qs2 = qs;
479    // Does not create a new item
480    MORDOR_TEST_ASSERT(qs2["c"].empty());
481    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 4u);
482    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a=3&a=4&a2=5&b");
483
484    // Returns the first item, but keeps the rest
485    MORDOR_TEST_ASSERT_EQUAL(qs2["a"], "3");
486    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 4u);
487    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a=3&a=4&a2=5&b");
488
489    // Does not create a new item (in between)
490    MORDOR_TEST_ASSERT(qs2["a3"].empty());
491    MORDOR_TEST_ASSERT_EQUAL(qs.size(), 4u);
492    MORDOR_TEST_ASSERT_EQUAL(qs.toString(), "a=3&a=4&a2=5&b");
493}
494
495MORDOR_UNITTEST(URI, decodeOK)
496{
497    std::string str("https%3A%2F%2Fredmine.mozycorp.com%2Fissues%2F118200");
498    MORDOR_TEST_ASSERT_EQUAL(URI::decode(str), "https://redmine.mozycorp.com/issues/118200");
499}
500
501MORDOR_UNITTEST(URI, decodeInvalidURL)
502{
503    std::vector<std::string> invalidStr;
504    invalidStr.push_back("%4"); // invalid length, should have 2 chars after %
505    invalidStr.push_back("%3xpath"); // invalid first char after %
506    invalidStr.push_back("%x3path"); // invalid second char after %
507    for (std::vector<std::string>::iterator it = invalidStr.begin(); it != invalidStr.end(); ++it) {
508        MORDOR_TEST_ASSERT_EXCEPTION(URI::decode(*it), std::invalid_argument);
509    }
510}