1//
2// Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// Official repository: https://github.com/boostorg/url
8//
9
10// Test that header file is self-contained.
11#include <boost/url/url_base.hpp>
12
13#include <boost/url/decode_view.hpp>
14#include <boost/url/url.hpp>
15#include "test_suite.hpp"
16
17/* Legend
18
19 '#' 0x23 '=' 0x3d
20 '%' 0x25 '@' 0x40
21 '&' 0x26 '[' 0x5b
22 '.' 0x2e ']' 0x5d
23 ':' 0x3a
24*/
25
26#ifdef BOOST_TEST_CSTR_EQ
27#undef BOOST_TEST_CSTR_EQ
28#define BOOST_TEST_CSTR_EQ(expr1,expr2) \
29 BOOST_TEST_EQ( boost::urls::detail::to_sv(expr1), boost::urls::detail::to_sv(expr2) )
30#endif
31
32namespace boost {
33namespace urls {
34
35struct url_base_test
36{
37 template<class F>
38 static
39 void
40 modify(
41 core::string_view before,
42 core::string_view after,
43 F&& f)
44 {
45 url u(before);
46 f(u);
47 auto s = u.buffer();
48 BOOST_TEST_EQ(s, after);
49 }
50
51 //--------------------------------------------
52 //
53 // Scheme
54 //
55 //--------------------------------------------
56
57 void
58 testSetScheme()
59 {
60 auto const remove = [](
61 core::string_view s1, core::string_view s2)
62 {
63 url u;
64 BOOST_TEST_NO_THROW(u = url(s1));
65 BOOST_TEST_EQ(u.remove_scheme().buffer(), s2);
66 BOOST_TEST_EQ(u.scheme_id(), scheme::none);
67 BOOST_TEST(u.scheme().empty());
68 };
69
70 auto const set = [](
71 scheme id, core::string_view s1,
72 core::string_view s2, core::string_view s3)
73 {
74 url u;
75 BOOST_TEST_NO_THROW(u = url(s2));
76 BOOST_TEST(u.set_scheme(s1).buffer() == s3);
77 BOOST_TEST_EQ(u.scheme(), s1);
78 BOOST_TEST_EQ(u.scheme_id(), id);
79 };
80
81 auto const setid = [](
82 scheme id, core::string_view s1, core::string_view s2)
83 {
84 url u;
85 BOOST_TEST_NO_THROW(u = url(s1));
86 BOOST_TEST(u.set_scheme_id(id).buffer() == s2);
87 BOOST_TEST_EQ(u.scheme_id(), id);
88 };
89
90 remove("", "");
91 remove("x", "x");
92 remove("x:", "");
93 remove("x:/", "/");
94 remove("x:a", "a");
95 remove("x:a/", "a/");
96 remove("x:/a", "/a");
97 remove("x://a", "//a");
98 remove("x:///a", "///a");
99 remove("x://", "//");
100 remove("x:a:", "a%3A");
101 remove("x:a:/", "a%3A/");
102 remove("yabba:dabba:doo", "dabba%3Adoo");
103 remove("yabba:dabba:doo:doo", "dabba%3Adoo%3Adoo");
104 remove("x::::", "%3A%3A%3A");
105
106
107 remove("x://a.b/1/2", "//a.b/1/2");
108 remove("x://a:b@c.d/1/?#", "//a:b@c.d/1/?#");
109
110 set(scheme::ftp, "ftp", "", "ftp:");
111 set(scheme::ws, "ws", "/", "ws:/");
112 set(scheme::ws, "ws", "a", "ws:a");
113 set(scheme::ws, "ws", "a/", "ws:a/");
114 set(scheme::ws, "ws", "//", "ws://");
115 set(scheme::ws, "ws", "a:/", "ws:/");
116 set(scheme::http, "http", "./a:", "http:a:");
117
118 set(scheme::ws, "ws", "//a.b/1/2", "ws://a.b/1/2");
119 set(scheme::ws, "ws", "//a:b@c.d/1/?#", "ws://a:b@c.d/1/?#");
120
121 setid(scheme::ftp, "", "ftp:");
122 setid(scheme::ws, "/", "ws:/");
123 setid(scheme::ws, "a", "ws:a");
124 setid(scheme::ws, "a/", "ws:a/");
125 setid(scheme::ws, "//", "ws://");
126 setid(scheme::ws, "a:/", "ws:/");
127
128 setid(scheme::ws,
129 "//a.b/1/2", "ws://a.b/1/2");
130
131 setid(scheme::ws,
132 "//a:b@c.d/1/?#", "ws://a:b@c.d/1/?#");
133
134 setid(scheme::none, "a:/", "/");
135
136 BOOST_TEST_THROWS(
137 url().set_scheme(""),
138 system::system_error);
139
140 BOOST_TEST_THROWS(
141 url().set_scheme("http~"),
142 system::system_error);
143
144 BOOST_TEST_THROWS(
145 url().set_scheme_id(scheme::unknown),
146 system::system_error);
147
148 // self-intersection
149 modify(
150 before: "x://?mailto",
151 after: "mailto://?mailto",
152 f: [](url_base& u)
153 {
154 u.set_scheme(
155 u.encoded_query());
156 });
157 }
158
159 //--------------------------------------------
160 //
161 // Authority
162 //
163 //--------------------------------------------
164
165 void
166 testSetAuthority()
167 {
168 auto const remove = [](
169 core::string_view s1, core::string_view s2)
170 {
171 url u;
172 BOOST_TEST_NO_THROW(u = url(s1));
173 BOOST_TEST_EQ(u.remove_authority().buffer(), s2);
174 BOOST_TEST(u.encoded_authority().empty());
175 BOOST_TEST(! u.has_authority());
176 BOOST_TEST(! u.has_userinfo());
177 BOOST_TEST(! u.has_password());
178 BOOST_TEST(! u.has_port());
179 BOOST_TEST(u.host_address().empty());
180 };
181
182 auto const set = [](core::string_view s1,
183 core::string_view s2, core::string_view s3)
184 {
185 url u;
186 BOOST_TEST_NO_THROW(u = url(s1));
187 BOOST_TEST(u.set_encoded_authority(s2).buffer() == s3);
188 BOOST_TEST_EQ(u.encoded_authority(), s2);
189 BOOST_TEST(u.has_authority());
190 };
191
192 BOOST_TEST_THROWS(
193 url().set_encoded_authority("x:y"),
194 system::system_error);
195
196 BOOST_TEST_THROWS(
197 url().set_encoded_authority("%2"),
198 system::system_error);
199
200 remove("", "");
201 remove("/", "/");
202 remove("/x", "/x");
203 remove("/x/", "/x/");
204 remove("/x/y", "/x/y");
205 remove("x/", "x/");
206 remove("x/y", "x/y");
207 remove("x/y/", "x/y/");
208 remove("x/y/?#", "x/y/?#");
209 remove("x/y/?#", "x/y/?#");
210
211
212
213 remove("z:", "z:");
214 remove("z:/", "z:/");
215 remove("z:/x", "z:/x");
216 remove("z:/x/", "z:/x/");
217 remove("z:/x/y", "z:/x/y");
218 remove("z:x/", "z:x/");
219 remove("z:x/y", "z:x/y");
220 remove("z:x/y/", "z:x/y/");
221 remove("z:x/y/?#", "z:x/y/?#");
222 remove("z:x:/y/?#", "z:x:/y/?#");
223
224 remove("//", "");
225 remove("///", "/");
226 remove("///x", "/x");
227 remove("///x/", "/x/");
228 remove("///x/y", "/x/y");
229 remove("//x/", "/");
230 remove("//x/y", "/y");
231 remove("//x/y/", "/y/");
232 remove("//x/y/?#", "/y/?#");
233
234 remove("z://", "z:");
235 remove("z:///", "z:/");
236 remove("z:///x", "z:/x");
237 remove("z:///x/", "z:/x/");
238 remove("z:///x/y", "z:/x/y");
239 remove("z://x/", "z:/");
240 remove("z://x/y", "z:/y");
241 remove("z://x/y/", "z:/y/");
242 remove("z://x/y/?#", "z:/y/?#");
243 remove("z://x:/y/?#", "z:/y/?#");
244 remove("z://x//y/?q#f", "z:/.//y/?q#f");
245
246 set("", "", "//");
247 set("", "x@", "//x@");
248 set("", ":x@", "//:x@");
249 set("", "x:y@", "//x:y@");
250 set("", "x", "//x");
251 set("", "x.y", "//x.y");
252 set("", "x:", "//x:");
253 set("", ":", "//:");
254 set("", ":0", "//:0");
255 set("", ":443", "//:443");
256 set("", ":65536", "//:65536");
257 set("", "1.2.3.4", "//1.2.3.4");
258 set("", "[v1.0]", "//[v1.0]");
259 set("", "[::]", "//[::]");
260 set("", "[::ffff:127.0.0.1]",
261 "//[::ffff:127.0.0.1]");
262 set("", "[::ffff:127.0.0.1]:80",
263 "//[::ffff:127.0.0.1]:80");
264 set("", "user:pass@example.com:80",
265 "//user:pass@example.com:80");
266 set("ws:",
267 "user:pass@example.com:80",
268 "ws://user:pass@example.com:80");
269
270 set("///a", "", "///a");
271 set("///a", "x@", "//x@/a");
272 set("///a", ":x@", "//:x@/a");
273 set("///a", "x:y@", "//x:y@/a");
274 set("///a", "x", "//x/a");
275 set("///a", "x.y", "//x.y/a");
276 set("///a", "x:", "//x:/a");
277 set("///a", ":", "//:/a");
278 set("///a", ":0", "//:0/a");
279 set("///a", ":443", "//:443/a");
280 set("///a", ":65536", "//:65536/a");
281 set("///a", "1.2.3.4", "//1.2.3.4/a");
282 set("///a", "[v1.0]", "//[v1.0]/a");
283 set("///a", "[::]", "//[::]/a");
284 set("///a", "[::ffff:127.0.0.1]",
285 "//[::ffff:127.0.0.1]/a");
286 set("///a", "[::ffff:127.0.0.1]:80",
287 "//[::ffff:127.0.0.1]:80/a");
288 set("///a", "user:pass@example.com:80",
289 "//user:pass@example.com:80/a");
290 set("ws:///a",
291 "user:pass@example.com:80",
292 "ws://user:pass@example.com:80/a");
293
294 // self-intersection
295 modify(
296 before: "x://@?user:pass@example.com:8080",
297 after: "x://user:pass@example.com:8080?user:pass@example.com:8080",
298 f: [](url_base& u)
299 {
300 u.set_encoded_authority(
301 u.encoded_query());
302 });
303 }
304
305 //--------------------------------------------
306 //
307 // Userinfo
308 //
309 //--------------------------------------------
310
311 void
312 testSetUserinfo()
313 {
314 auto const remove = [](
315 core::string_view s1, core::string_view s2)
316 {
317 url u;
318 BOOST_TEST_NO_THROW(u = url(s1));
319 BOOST_TEST_EQ(u.remove_userinfo().buffer(), s2);
320 BOOST_TEST(u.encoded_userinfo().empty());
321 BOOST_TEST(u.userinfo().empty());
322 BOOST_TEST(! u.has_userinfo());
323 };
324
325 auto const set = [](core::string_view s1,
326 core::string_view s2, core::string_view s3)
327 {
328 url u;
329 BOOST_TEST_NO_THROW(u = url(s1));
330 BOOST_TEST_EQ(u.set_userinfo(s2).buffer(), s3);
331 };
332
333 auto const enc = [](core::string_view s1,
334 core::string_view s2, core::string_view s3)
335 {
336 url u;
337 BOOST_TEST_NO_THROW(u = url(s1));
338 BOOST_TEST_EQ(u.set_encoded_userinfo(s2).buffer(), s3);
339 BOOST_TEST_EQ(u.encoded_userinfo(), s2);
340 BOOST_TEST(u.has_userinfo());
341 };
342
343 BOOST_TEST_THROWS(url().set_encoded_userinfo("%2"), std::exception);
344
345 remove("", "");
346 remove("/", "/");
347 remove("//", "//");
348 remove("//@", "//");
349 remove("//a@", "//");
350 remove("//a:@", "//");
351 remove("//a:b@", "//");
352 remove("//@x", "//x");
353 remove("//a@x", "//x");
354 remove("//a:b@x", "//x");
355 remove("//a:b@x/", "//x/");
356
357 remove("z:", "z:");
358 remove("z:/", "z:/");
359 remove("z://", "z://");
360 remove("z://@", "z://");
361 remove("z://a@", "z://");
362 remove("z://a:@", "z://");
363 remove("z://a:b@", "z://");
364 remove("z://@x", "z://x");
365 remove("z://a@x", "z://x");
366 remove("z://a:b@x", "z://x");
367
368 set("", "", "//@");
369 set("/", "", "//@/");
370 set("//", "", "//@");
371 set("//@", "", "//@");
372 set("//a@", "", "//@");
373 set("//a:@", "", "//@");
374 set("//a:b@", "", "//@");
375 set("//@x", "", "//@x");
376 set("//a@x", "", "//@x");
377 set("//a:b@x", "", "//@x");
378 set("//a:b@x/", "", "//@x/");
379
380 set("w:", "", "w://@");
381 set("w:/", "", "w://@/");
382 set("w://", "", "w://@");
383 set("w://@", "", "w://@");
384 set("w://a@", "", "w://@");
385 set("w://a:@", "", "w://@");
386 set("w://a:b@", "", "w://@");
387 set("w://@x", "", "w://@x");
388 set("w://a@x", "", "w://@x");
389 set("w://a:b@x", "", "w://@x");
390 set("w://a:b@x/", "", "w://@x/");
391
392 set("", ":", "//:@");
393 set("/", "a", "//a@/");
394 set("//", "@", "//%40@");
395 set("//@", "xyz", "//xyz@");
396 set("//a@", ":@", "//:%40@");
397 set("//a:@", "x", "//x@");
398 set("//a:b@", "p:q", "//p:q@");
399 set("//@x", "z", "//z@x");
400 set("//a@x", "42", "//42@x");
401 set("//a:b@x", "UV", "//UV@x");
402 set("//a:b@x/", "NR", "//NR@x/");
403
404 set("w:", ":", "w://:@");
405 set("w:/", "a", "w://a@/");
406 set("w://", "@", "w://%40@");
407 set("w://@", "xyz", "w://xyz@");
408 set("w://a@", ":@", "w://:%40@");
409 set("w://a:@", "x", "w://x@");
410 set("w://a:b@", "p:q", "w://p:q@");
411 set("w://@x", "z", "w://z@x");
412 set("w://a@x", "42", "w://42@x");
413 set("w://a:b@x", "UV", "w://UV@x");
414 set("w://a:b@x/", "NR", "w://NR@x/");
415
416 enc("", "", "//@");
417 enc("/", "", "//@/");
418 enc("//", "", "//@");
419 enc("//@", "", "//@");
420 enc("//a@", "", "//@");
421 enc("//a:@", "", "//@");
422 enc("//a:b@", "", "//@");
423 enc("//@x", "", "//@x");
424 enc("//a@x", "", "//@x");
425 enc("//a:b@x", "", "//@x");
426 enc("//a:b@x/", "", "//@x/");
427
428 enc("w:", "", "w://@");
429 enc("w:/", "", "w://@/");
430 enc("w://", "", "w://@");
431 enc("w://@", "", "w://@");
432 enc("w://a@", "", "w://@");
433 enc("w://a:@", "", "w://@");
434 enc("w://a:b@", "", "w://@");
435 enc("w://@x", "", "w://@x");
436 enc("w://a@x", "", "w://@x");
437 enc("w://a:b@x", "", "w://@x");
438 enc("w://a:b@x/", "", "w://@x/");
439
440 enc("", ":", "//:@");
441 enc("", "%3a", "//%3a@");
442 enc("/", "%41", "//%41@/");
443 enc("//", "x", "//x@");
444 enc("//@", "xyz", "//xyz@");
445 enc("//a@", "%3a%40", "//%3a%40@");
446 enc("//a:@", "x", "//x@");
447 enc("//a:b@", "p:q", "//p:q@");
448 enc("//@x", "z", "//z@x");
449 enc("//a@x", "42", "//42@x");
450 enc("//a:b@x", "UV", "//UV@x");
451 enc("//a:b@x/", "NR", "//NR@x/");
452
453 enc("w:", ":", "w://:@");
454 enc("w:", "%3a", "w://%3a@");
455 enc("w:/", "%41", "w://%41@/");
456 enc("w://", "x", "w://x@");
457 enc("w://@", "xyz", "w://xyz@");
458 enc("w://a@", "%3a%40", "w://%3a%40@");
459 enc("w://a:@", "x", "w://x@");
460 enc("w://a:b@", "p:q", "w://p:q@");
461 enc("w://@x", "z", "w://z@x");
462 enc("w://a@x", "42", "w://42@x");
463 enc("w://a:b@x", "UV", "w://UV@x");
464 enc("w://a:b@x/", "NR", "w://NR@x/");
465
466 // self-intersection
467 modify(
468 before: "x://?user:pass",
469 after: "x://user:pass@?user:pass",
470 f: [](url_base& u)
471 {
472 u.set_encoded_userinfo(u.encoded_query());
473 });
474 modify(
475 before: "x://?user:pass",
476 after: "x://user:pass@?user:pass",
477 f: [](url_base& u)
478 {
479 u.set_userinfo(
480 u.encoded_query());
481 });
482 modify(
483 before: "x://?user:pass",
484 after: "x://user:pass@?user:pass",
485 f: [](url_base& u)
486 {
487 u.set_userinfo(
488 u.query());
489 });
490 }
491
492 void
493 testSetUser()
494 {
495 auto const set = [](
496 core::string_view s0,
497 core::string_view s,
498 core::string_view s1)
499 {
500 modify(before: s0, after: s1,
501 f: [s](url_base& u)
502 {
503 u.set_user(s);
504 BOOST_TEST(u.user() == s);
505 BOOST_TEST(u.has_userinfo());
506 });
507 };
508
509 auto const enc = [](
510 core::string_view s0,
511 core::string_view s,
512 core::string_view s1)
513 {
514 modify(before: s0, after: s1,
515 f: [s](url_base& u)
516 {
517 BOOST_TEST_NO_THROW(u.set_encoded_user(s));
518 BOOST_TEST_EQ(
519 decode_view(s),
520 decode_view(u.encoded_user()));
521 BOOST_TEST(u.has_userinfo());
522 });
523 };
524
525 BOOST_TEST_THROWS(
526 url().set_encoded_user("%2"),
527 system::system_error);
528
529 set("", "", "//@");
530 set("/y", "", "//@/y");
531 set("//", "", "//@");
532 set("//y", "", "//@y");
533 set("//@", "", "//@");
534 set("//:@", "", "//:@");
535 set("//y@", "", "//@");
536 set("//y@z", "", "//@z");
537 set("//y:@", "", "//:@");
538 set("//y:z@", "", "//:z@");
539 set("//a:b@c", "", "//:b@c");
540 set("ws:", "", "ws://@");
541 set("ws:/y", "", "ws://@/y");
542 set("ws://", "", "ws://@");
543 set("ws://y", "", "ws://@y");
544 set("ws://@", "", "ws://@");
545 set("ws://:@", "", "ws://:@");
546 set("ws://y@", "", "ws://@");
547 set("ws://y@z", "", "ws://@z");
548 set("ws://y:@", "", "ws://:@");
549 set("ws://y:z@", "", "ws://:z@");
550 set("ws://a:b@c", "", "ws://:b@c");
551 set("", "", "//@");
552 set("", "x", "//x@");
553 set("/y", "x", "//x@/y");
554 set("//", "x", "//x@");
555 set("//y", "x", "//x@y");
556 set("//@", "x", "//x@");
557 set("//:@", "x", "//x:@");
558 set("//y@", "x", "//x@");
559 set("//y@z", "x", "//x@z");
560 set("//y:@", "x", "//x:@");
561 set("//y:z@", "x", "//x:z@");
562 set("//a:b@c", "x", "//x:b@c");
563 set("ws:", "x", "ws://x@");
564 set("ws:/y", "x", "ws://x@/y");
565 set("ws://", "x", "ws://x@");
566 set("ws://y", "x", "ws://x@y");
567 set("ws://@", "x", "ws://x@");
568 set("ws://:@", "x", "ws://x:@");
569 set("ws://y@", "x", "ws://x@");
570 set("ws://y@z", "x", "ws://x@z");
571 set("ws://y:@", "x", "ws://x:@");
572 set("ws://y:z@", "x", "ws://x:z@");
573 set("ws://a:b@c", "x", "ws://x:b@c");
574 set("ws://a:b@c", ":", "ws://%3A:b@c");
575 set("ws://a:b@c", "@", "ws://%40:b@c");
576
577 enc("", "", "//@");
578 enc("", "%41", "//%41@");
579 enc("/y", "%41", "//%41@/y");
580 enc("//", "%41", "//%41@");
581 enc("//y", "%41", "//%41@y");
582 enc("//@", "%41", "//%41@");
583 enc("//:@", "%41", "//%41:@");
584 enc("//y@", "%41", "//%41@");
585 enc("//y@z", "%41", "//%41@z");
586 enc("//y:@", "%41", "//%41:@");
587 enc("//y:z@", "%41", "//%41:z@");
588 enc("//a:b@c", "%41", "//%41:b@c");
589 enc("ws:", "%41", "ws://%41@");
590 enc("ws:/y", "%41", "ws://%41@/y");
591 enc("ws://", "%41", "ws://%41@");
592 enc("ws://y", "%41", "ws://%41@y");
593 enc("ws://@", "%41", "ws://%41@");
594 enc("ws://:@", "%41", "ws://%41:@");
595 enc("ws://y@", "%41", "ws://%41@");
596 enc("ws://y@z", "%41", "ws://%41@z");
597 enc("ws://y:@", "%41", "ws://%41:@");
598 enc("ws://y:z@", "%41", "ws://%41:z@");
599 enc("ws://a:b@c", "%41", "ws://%41:b@c");
600 enc("x:", "user%3apass", "x://user%3apass@");
601 enc("x:", "user@local", "x://user%40local@");
602
603 // self-intersection
604 modify(
605 before: "x://u@/?johndoe",
606 after: "x://johndoe@/?johndoe",
607 f: [](url_base& u)
608 {
609 u.set_encoded_user(
610 u.encoded_query());
611 });
612 modify(
613 before: "x://u@/?johndoe",
614 after: "x://johndoe@/?johndoe",
615 f: [](url_base& u)
616 {
617 u.set_user(
618 u.query());
619 });
620 modify(
621 before: "x://u@/?johndoe",
622 after: "x://johndoe@/?johndoe",
623 f: [](url_base& u)
624 {
625 u.set_user(
626 u.encoded_query());
627 });
628
629 // path doesn't become host
630 {
631 url u("mailto:example.net");
632 BOOST_TEST_NO_THROW(u.set_encoded_user("me"));
633 BOOST_TEST_CSTR_EQ(u, "mailto://me@/example.net");
634 BOOST_TEST_NOT(u.buffer() == "mailto://me@example.net");
635 BOOST_TEST_CSTR_EQ(u.encoded_user(), "me");
636 }
637 {
638 url u("mailto:you@example.net");
639 BOOST_TEST_NO_THROW(u.set_encoded_user("me"));
640 BOOST_TEST_CSTR_EQ(u, "mailto://me@/you@example.net");
641 BOOST_TEST_NOT(u.buffer() == "mailto://me@you@example.net");
642 BOOST_TEST_CSTR_EQ(u.encoded_user(), "me");
643 }
644 {
645 url u("mailto:a@b.c");
646 BOOST_TEST_NO_THROW(u.set_encoded_password("secret"));
647 BOOST_TEST_CSTR_EQ(u, "mailto://:secret@/a@b.c");
648 }
649 {
650 url u("mailto:a@b.c");
651 BOOST_TEST_NO_THROW(u.set_encoded_userinfo("u:p"));
652 BOOST_TEST_CSTR_EQ(u, "mailto://u:p@/a@b.c");
653 }
654 {
655 url u("mailto://h/a@b.c");
656 BOOST_TEST_NO_THROW(u.set_encoded_userinfo("u:p"));
657 BOOST_TEST_CSTR_EQ(u, "mailto://u:p@h/a@b.c");
658 }
659 {
660 url u("mailto:a@b.c");
661 BOOST_TEST_NO_THROW(u.set_encoded_userinfo("u"));
662 BOOST_TEST_CSTR_EQ(u, "mailto://u@/a@b.c");
663 }
664 {
665 url u("mailto://h/a@b.c");
666 BOOST_TEST_NO_THROW(u.set_encoded_userinfo("u"));
667 BOOST_TEST_CSTR_EQ(u, "mailto://u@h/a@b.c");
668 }
669 {
670 url u("mailto:a@b.c");
671 BOOST_TEST_NO_THROW(u.set_encoded_host("host"));
672 BOOST_TEST_CSTR_EQ(u, "mailto://host/a@b.c");
673 }
674 {
675 url u("mailto:a@b.c");
676 BOOST_TEST_NO_THROW(u.set_port("80"));
677 BOOST_TEST_CSTR_EQ(u, "mailto://:80/a@b.c");
678 }
679 }
680
681 void
682 testSetPassword()
683 {
684 auto const remove = [](
685 core::string_view s1, core::string_view s2)
686 {
687 url u;
688 BOOST_TEST_NO_THROW(u = url(s1));
689 BOOST_TEST(u.remove_password().buffer() == s2);
690 BOOST_TEST_EQ(u.encoded_password(), "");
691 BOOST_TEST_EQ(u.password(), "");
692 };
693
694 auto const set = [](
695 core::string_view s1, core::string_view s2,
696 core::string_view s3)
697 {
698 url u;
699 BOOST_TEST_NO_THROW(u = url(s1));
700 BOOST_TEST(u.set_password(s2).buffer() == s3);
701 };
702
703 auto const enc = [](
704 core::string_view s1, core::string_view s2,
705 core::string_view s3)
706 {
707 url u;
708 BOOST_TEST_NO_THROW(u = url(s1));
709 BOOST_TEST(u.set_encoded_password(
710 s2).buffer() == s3);
711 BOOST_TEST_EQ(u.encoded_password(), s2);
712 BOOST_TEST(u.has_userinfo());
713 };
714
715 BOOST_TEST_THROWS(url().set_encoded_password(
716 "%2"), system::system_error);
717
718 remove("", "");
719 remove("/", "/");
720 remove("//", "//");
721 remove("//", "//");
722 remove("//@", "//@");
723 remove("//y@", "//y@");
724 remove("//:y@", "//@");
725 remove("//y:z@", "//y@");
726 remove("//y:z@a", "//y@a");
727
728 remove("x:", "x:");
729 remove("x:/", "x:/");
730 remove("x://", "x://");
731 remove("x://", "x://");
732 remove("x://@", "x://@");
733 remove("x://y@", "x://y@");
734 remove("x://:y@", "x://@");
735 remove("x://y:z@", "x://y@");
736 remove("x://y:z@a", "x://y@a");
737
738 set("", "", "//:@");
739 set("/", "", "//:@/");
740 set("//", "", "//:@");
741 set("//@", "", "//:@");
742 set("//y@", "", "//y:@");
743 set("//:y@", "", "//:@");
744 set("//y:z@", "", "//y:@");
745 set("//y:z@a", "", "//y:@a");
746
747 set("x:", "", "x://:@");
748 set("x:/", "", "x://:@/");
749 set("x://", "", "x://:@");
750 set("x://@", "", "x://:@");
751 set("x://y@", "", "x://y:@");
752 set("x://:y@", "", "x://:@");
753 set("x://y:z@", "", "x://y:@");
754 set("x://y:z@a", "", "x://y:@a");
755
756 set("", "x", "//:x@");
757 set("/", "x", "//:x@/");
758 set("//", "x", "//:x@");
759 set("//x", "y", "//:y@x");
760 set("//x@", "y", "//x:y@");
761 set("//x:y@", "z", "//x:z@");
762 set("//x:abc@", "z", "//x:z@");
763 set("//x:z@", "abc", "//x:abc@");
764
765 set("w:", "x", "w://:x@");
766 set("w:/", "x", "w://:x@/");
767 set("w://", "x", "w://:x@");
768 set("w://x", "y", "w://:y@x");
769 set("w://x@", "y", "w://x:y@");
770 set("w://x:y@", "z", "w://x:z@");
771 set("w://x:abc@", "z", "w://x:z@");
772 set("w://x:z@", "abc", "w://x:abc@");
773
774 set("w://x:z@", ":", "w://x::@");
775 set("w://x:z@", "@", "w://x:%40@");
776
777 enc("", "", "//:@");
778 enc("", "%41", "//:%41@");
779 enc("/y", "%41", "//:%41@/y");
780 enc("//", "%41", "//:%41@");
781 enc("//y", "%41", "//:%41@y");
782 enc("//@", "%41", "//:%41@");
783 enc("//:@", "%41", "//:%41@");
784 enc("//y@", "%41", "//y:%41@");
785 enc("//y@z", "%41", "//y:%41@z");
786 enc("//y:@", "%41", "//y:%41@");
787 enc("//y:z@", "%41", "//y:%41@");
788 enc("//a:b@c", "%41", "//a:%41@c");
789
790 enc("ws:", "%41", "ws://:%41@");
791 enc("ws:/y", "%41", "ws://:%41@/y");
792 enc("ws://", "%41", "ws://:%41@");
793 enc("ws://y", "%41", "ws://:%41@y");
794 enc("ws://@", "%41", "ws://:%41@");
795 enc("ws://:@", "%41", "ws://:%41@");
796 enc("ws://y@", "%41", "ws://y:%41@");
797 enc("ws://y@z", "%41", "ws://y:%41@z");
798 enc("ws://y:@", "%41", "ws://y:%41@");
799 enc("ws://y:z@", "%41", "ws://y:%41@");
800 enc("ws://a:b@c", "%41", "ws://a:%41@c");
801
802 // self-intersection
803 modify(
804 before: "x://:p@/?johndoe",
805 after: "x://:johndoe@/?johndoe",
806 f: [](url_base& u)
807 {
808 u.set_encoded_password(
809 u.encoded_query());
810 });
811 modify(
812 before: "x://:p@/?johndoe",
813 after: "x://:johndoe@/?johndoe",
814 f: [](url_base& u)
815 {
816 u.set_password(
817 u.query());
818 });
819 modify(
820 before: "x://:p@/?johndoe",
821 after: "x://:johndoe@/?johndoe",
822 f: [](url_base& u)
823 {
824 u.set_password(
825 u.encoded_query());
826 });
827 }
828
829 //--------------------------------------------
830 //
831 // Host
832 //
833 //--------------------------------------------
834
835 static
836 std::string
837 bracketed(
838 std::string s)
839 {
840 return
841 std::string("[") + s +
842 std::string("]");
843 }
844
845 void
846 testSetHost()
847 {
848 auto const set_host = [](
849 core::string_view s,
850 core::string_view s1,
851 host_type ht)
852 {
853 url u;
854 BOOST_TEST_NO_THROW(u.set_host(s));
855 BOOST_TEST_EQ(u.host_type(), ht);
856 BOOST_TEST_EQ(u.buffer(), s1);
857 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
858 switch(ht)
859 {
860 case host_type::none:
861 BOOST_TEST_FAIL();
862 break;
863 case host_type::ipv4:
864 BOOST_TEST_EQ(u.encoded_host(), s);
865 BOOST_TEST_EQ(u.host_address(), s);
866 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address(s));
867 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
868 BOOST_TEST_EQ(u.host_ipvfuture(), "");
869 BOOST_TEST_EQ(u.host_name(), "");
870 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
871 break;
872 case host_type::ipv6:
873 BOOST_TEST_EQ(u.encoded_host(), s);
874 BOOST_TEST_EQ(bracketed(u.host_address()), s);
875 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
876 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address(u.host_address()));
877 BOOST_TEST_EQ(u.host_ipvfuture(), "");
878 BOOST_TEST_EQ(u.host_name(), "");
879 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
880 break;
881 case host_type::ipvfuture:
882 BOOST_TEST_EQ(u.encoded_host(), s);
883 BOOST_TEST_EQ(bracketed(u.host_address()), s);
884 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
885 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
886 BOOST_TEST_EQ(u.host_ipvfuture(), u.host_address());
887 BOOST_TEST_EQ(u.host_name(), "");
888 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
889 break;
890 case host_type::name:
891 BOOST_TEST_EQ(u.host_address(), s);
892 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
893 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
894 BOOST_TEST_EQ(u.host_ipvfuture(), "");
895 BOOST_TEST_EQ(u.host_name(), s);
896 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
897 break;
898 }
899 };
900
901 auto const set_encoded_host = [](
902 core::string_view s,
903 core::string_view s1,
904 host_type ht)
905 {
906 url u;
907 BOOST_TEST_NO_THROW(u.set_encoded_host(s));
908 BOOST_TEST_EQ(u.host_type(), ht);
909 BOOST_TEST_EQ(u.buffer(), s1);
910 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
911 switch(ht)
912 {
913 case host_type::none:
914 BOOST_TEST_FAIL();
915 break;
916 case host_type::ipv4:
917 BOOST_TEST_EQ(u.encoded_host(), s);
918 BOOST_TEST_EQ(u.host_address(), s);
919 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address(s));
920 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
921 BOOST_TEST_EQ(u.host_ipvfuture(), "");
922 BOOST_TEST_EQ(u.host_name(), "");
923 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
924 break;
925 case host_type::ipv6:
926 BOOST_TEST_EQ(u.encoded_host(), s);
927 BOOST_TEST_EQ(bracketed(u.host_address()), s);
928 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
929 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address(u.host_address()));
930 BOOST_TEST_EQ(u.host_ipvfuture(), "");
931 BOOST_TEST_EQ(u.host_name(), "");
932 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
933 break;
934 case host_type::ipvfuture:
935 BOOST_TEST_EQ(u.encoded_host(), s);
936 BOOST_TEST_EQ(bracketed(u.host_address()), s);
937 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
938 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
939 BOOST_TEST_EQ(u.host_ipvfuture(), u.host_address());
940 BOOST_TEST_EQ(u.host_name(), "");
941 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
942 break;
943 case host_type::name:
944 BOOST_TEST_EQ(u.host_address(), pct_string_view(s).decode());
945 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
946 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
947 BOOST_TEST_EQ(u.host_ipvfuture(), "");
948 BOOST_TEST_EQ(u.host_name(), pct_string_view(s).decode());
949 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
950 break;
951 }
952 };
953
954 auto const set_host_address = [](
955 core::string_view s,
956 core::string_view s1,
957 host_type ht)
958 {
959 url u;
960 BOOST_TEST_NO_THROW(u.set_host_address(s));
961 BOOST_TEST_EQ(u.host_type(), ht);
962 BOOST_TEST_EQ(u.buffer(), s1);
963 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
964 switch(ht)
965 {
966 case host_type::none:
967 BOOST_TEST_FAIL();
968 break;
969 case host_type::ipv4:
970 BOOST_TEST_EQ(u.encoded_host(), s);
971 BOOST_TEST_EQ(u.host_address(), s);
972 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address(s));
973 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
974 BOOST_TEST_EQ(u.host_ipvfuture(), "");
975 BOOST_TEST_EQ(u.host_name(), "");
976 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
977 break;
978 case host_type::ipv6:
979 BOOST_TEST_EQ(u.encoded_host(), bracketed(s));
980 BOOST_TEST_EQ(u.host_address(), s);
981 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
982 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address(s));
983 BOOST_TEST_EQ(u.host_ipvfuture(), "");
984 BOOST_TEST_EQ(u.host_name(), "");
985 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
986 break;
987 case host_type::ipvfuture:
988 BOOST_TEST_EQ(u.encoded_host(), bracketed(s));
989 BOOST_TEST_EQ(u.host_address(), s);
990 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
991 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
992 BOOST_TEST_EQ(u.host_ipvfuture(), s);
993 BOOST_TEST_EQ(u.host_name(), "");
994 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
995 break;
996 case host_type::name:
997 BOOST_TEST_EQ(u.host_address(), s);
998 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
999 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
1000 BOOST_TEST_EQ(u.host_ipvfuture(), "");
1001 BOOST_TEST_EQ(u.host_name(), s);
1002 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1003 break;
1004 }
1005 };
1006
1007 auto const set_encoded_host_address = [](
1008 core::string_view s,
1009 core::string_view s1,
1010 host_type ht)
1011 {
1012 url u;
1013 BOOST_TEST_NO_THROW(u.set_encoded_host_address(s));
1014 BOOST_TEST_EQ(u.host_type(), ht);
1015 BOOST_TEST_EQ(u.buffer(), s1);
1016 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
1017 switch(ht)
1018 {
1019 case host_type::none:
1020 BOOST_TEST_FAIL();
1021 break;
1022 case host_type::ipv4:
1023 BOOST_TEST_EQ(u.encoded_host(), s);
1024 BOOST_TEST_EQ(u.host_address(), s);
1025 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address(s));
1026 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
1027 BOOST_TEST_EQ(u.host_ipvfuture(), "");
1028 BOOST_TEST_EQ(u.host_name(), "");
1029 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1030 break;
1031 case host_type::ipv6:
1032 BOOST_TEST_EQ(u.encoded_host(), bracketed(s));
1033 BOOST_TEST_EQ(u.host_address(), s);
1034 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
1035 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address(s));
1036 BOOST_TEST_EQ(u.host_ipvfuture(), "");
1037 BOOST_TEST_EQ(u.host_name(), "");
1038 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1039 break;
1040 case host_type::ipvfuture:
1041 BOOST_TEST_EQ(u.encoded_host(), bracketed(s));
1042 BOOST_TEST_EQ(u.host_address(), s);
1043 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
1044 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
1045 BOOST_TEST_EQ(u.host_ipvfuture(), s);
1046 BOOST_TEST_EQ(u.host_name(), "");
1047 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1048 break;
1049 case host_type::name:
1050 BOOST_TEST_EQ(u.host_address(), pct_string_view(s).decode());
1051 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
1052 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
1053 BOOST_TEST_EQ(u.host_ipvfuture(), "");
1054 BOOST_TEST_EQ(u.host_name(), pct_string_view(s).decode());
1055 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1056 break;
1057 }
1058 };
1059
1060 auto const set_host_ipv4 = [](
1061 core::string_view s,
1062 core::string_view s1)
1063 {
1064 url u;
1065 BOOST_TEST_NO_THROW(u.set_host_ipv4(ipv4_address(s)));
1066 BOOST_TEST_EQ(u.host_type(), host_type::ipv4);
1067 BOOST_TEST_EQ(u.buffer(), s1);
1068 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
1069 BOOST_TEST_EQ(u.encoded_host(), s);
1070 BOOST_TEST_EQ(u.host_address(), s);
1071 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address(s));
1072 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
1073 BOOST_TEST_EQ(u.host_ipvfuture(), "");
1074 BOOST_TEST_EQ(u.host_name(), "");
1075 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1076 };
1077
1078 auto const set_host_ipv6 = [](
1079 core::string_view s,
1080 core::string_view s1)
1081 {
1082 url u;
1083 BOOST_TEST_NO_THROW(u.set_host_ipv6(ipv6_address(s)));
1084 BOOST_TEST_EQ(u.host_type(), host_type::ipv6);
1085 BOOST_TEST_EQ(u.buffer(), s1);
1086 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
1087 BOOST_TEST_EQ(u.encoded_host(), bracketed(s));
1088 BOOST_TEST_EQ(u.host_address(), s);
1089 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
1090 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address(s));
1091 BOOST_TEST_EQ(u.host_ipvfuture(), "");
1092 BOOST_TEST_EQ(u.host_name(), "");
1093 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1094 };
1095
1096 auto const set_host_ipvfuture = [](
1097 core::string_view s,
1098 core::string_view s1)
1099 {
1100 url u;
1101 BOOST_TEST_NO_THROW(u.set_host_ipvfuture(s))
1102 BOOST_TEST_EQ(u.host_type(), host_type::ipvfuture);
1103 BOOST_TEST_EQ(u.buffer(), s1);
1104 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
1105 BOOST_TEST_EQ(u.encoded_host(), bracketed(s));
1106 BOOST_TEST_EQ(u.host_address(), s);
1107 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
1108 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
1109 BOOST_TEST_EQ(u.host_ipvfuture(), s);
1110 BOOST_TEST_EQ(u.host_name(), "");
1111 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1112 };
1113
1114 auto const set_host_name = [](
1115 core::string_view s,
1116 core::string_view s1)
1117 {
1118 url u;
1119 BOOST_TEST_NO_THROW(u.set_host_name(s))
1120 BOOST_TEST_EQ(u.host_type(), host_type::name);
1121 BOOST_TEST_EQ(u.buffer(), s1);
1122 BOOST_TEST_EQ(u.host(), s);
1123 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
1124 BOOST_TEST_EQ(u.host_address(), s);
1125 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
1126 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
1127 BOOST_TEST_EQ(u.host_ipvfuture(), "");
1128 BOOST_TEST_EQ(u.host_name(), s);
1129 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1130 };
1131
1132 auto const set_encoded_host_name = [](
1133 core::string_view s,
1134 core::string_view s1)
1135 {
1136 url u;
1137 BOOST_TEST_NO_THROW(u.set_encoded_host_name(s))
1138 BOOST_TEST_EQ(u.host_type(), host_type::name);
1139 BOOST_TEST_EQ(u.buffer(), s1);
1140 BOOST_TEST_EQ(u.host(), u.encoded_host().decode());
1141 auto rv = parse_ipv4_address(s);
1142 if(! rv)
1143 BOOST_TEST_EQ(u.encoded_host(), s);
1144 else
1145 BOOST_TEST_EQ(u.host(), rv->to_string());
1146 BOOST_TEST_EQ(u.host_address(), pct_string_view(s).decode());
1147 BOOST_TEST_EQ(u.host_ipv4_address(), ipv4_address());
1148 BOOST_TEST_EQ(u.host_ipv6_address(), ipv6_address());
1149 BOOST_TEST_EQ(u.host_ipvfuture(), "");
1150 BOOST_TEST_EQ(u.host_name(), pct_string_view(s).decode());
1151 BOOST_TEST_EQ(u.host_name(), u.encoded_host_name().decode());
1152 };
1153
1154 set_host("", "//", host_type::name);
1155 set_host("127.0.0.1", "//127.0.0.1", host_type::ipv4);
1156 set_host("[1::6:c0a8:1]", "//[1::6:c0a8:1]", host_type::ipv6 );
1157 set_host("[v42.69]", "//[v42.69]", host_type::ipvfuture );
1158 set_host("www.example.com", "//www.example.com", host_type::name);
1159 set_host("%5b%3a", "//%255b%253a", host_type::name);
1160
1161 set_encoded_host("", "//", host_type::name);
1162 set_encoded_host("127.0.0.1", "//127.0.0.1", host_type::ipv4);
1163 set_encoded_host("10.2.201.1", "//10.2.201.1", host_type::ipv4);
1164 set_encoded_host("0.5.15.20", "//0.5.15.20", host_type::ipv4);
1165 set_encoded_host("100.101.110.115", "//100.101.110.115", host_type::ipv4);
1166 set_encoded_host("200.205.210.255", "//200.205.210.255", host_type::ipv4);
1167 set_encoded_host("[1::6:c0a8:1]", "//[1::6:c0a8:1]", host_type::ipv6 );
1168 set_encoded_host("[::ffff:192.168.102.0]", "//[::ffff:192.168.102.0]", host_type::ipv6 );
1169 set_encoded_host("[v42.69]", "//[v42.69]", host_type::ipvfuture );
1170 set_encoded_host("www.example.com", "//www.example.com", host_type::name);
1171 set_encoded_host("%5b%3a", "//%5b%3a", host_type::name);
1172 set_encoded_host("%00", "//%00", host_type::name);
1173
1174 set_host_address("", "//", host_type::name);
1175 set_host_address("127.0.0.1", "//127.0.0.1", host_type::ipv4);
1176 set_host_address("1::6:c0a8:1", "//[1::6:c0a8:1]", host_type::ipv6 );
1177 set_host_address("v42.69", "//[v42.69]", host_type::ipvfuture );
1178 set_host_address("www.example.com", "//www.example.com", host_type::name);
1179 set_host_address("%5b%3a", "//%255b%253a", host_type::name);
1180
1181 set_encoded_host_address("", "//", host_type::name);
1182 set_encoded_host_address("127.0.0.1", "//127.0.0.1", host_type::ipv4);
1183 set_encoded_host_address("127%2e0.0.1", "//127%2e0.0.1", host_type::name);
1184 set_encoded_host_address("1::6:c0a8:1", "//[1::6:c0a8:1]", host_type::ipv6 );
1185 set_encoded_host_address("v42.69", "//[v42.69]", host_type::ipvfuture );
1186 set_encoded_host_address("www.example.com", "//www.example.com", host_type::name);
1187 set_encoded_host_address("%5b%3a", "//%5b%3a", host_type::name);
1188
1189 set_host_ipv4("0.0.0.0", "//0.0.0.0");
1190 set_host_ipv4("127.0.0.1", "//127.0.0.1");
1191 set_host_ipv4("255.255.255.255", "//255.255.255.255");
1192
1193 set_host_ipv6("1::6:c0a8:1", "//[1::6:c0a8:1]");
1194
1195 set_host_ipvfuture("v42.69", "//[v42.69]");
1196 BOOST_TEST_THROWS(url().set_host_ipvfuture("127.0.0.1"), system::system_error);
1197
1198 set_host_name("www.example.com", "//www.example.com");
1199 set_host_name("%5b%3a", "//%255b%253a");
1200 set_host_name("127.0.0.1", "//127%2E0%2E0%2E1");
1201
1202 set_encoded_host_name("www.example.com", "//www.example.com");
1203 set_encoded_host_name("%5b%3a", "//%5b%3a");
1204 set_encoded_host_name("127.0.0.1", "//127%2E0%2E0%2E1");
1205 BOOST_TEST_THROWS(url().set_encoded_host_name("%go"), system::system_error);
1206
1207 // self-intersection
1208 modify(
1209 before: "x://@?www.example.com",
1210 after: "x://@www.example.com?www.example.com",
1211 f: [](url_base& u)
1212 {
1213 u.set_encoded_host(
1214 u.encoded_query());
1215 });
1216 modify(
1217 before: "x://@?www.example.com",
1218 after: "x://@www.example.com?www.example.com",
1219 f: [](url_base& u)
1220 {
1221 u.set_host(
1222 u.encoded_query());
1223 });
1224 modify(
1225 before: "x://@?www.example.com",
1226 after: "x://@www.example.com?www.example.com",
1227 f: [](url_base& u)
1228 {
1229 u.set_host(
1230 u.query());
1231 });
1232
1233 {
1234 // issue #755
1235 url u1;
1236 u1.set_scheme("http");
1237 u1.set_host("127.0.0.1.org");
1238 BOOST_TEST_EQ(u1.buffer(), "http://127.0.0.1.org");
1239 BOOST_TEST_EQ(u1.host_type(), host_type::name);
1240 url u2(u1.buffer());
1241 BOOST_TEST_EQ(u2.host_type(), u1.host_type());
1242 BOOST_TEST_EQ(u2.host_type(), host_type::name);
1243 }
1244 }
1245
1246 void
1247 testSetPort()
1248 {
1249 auto const remove = [](
1250 core::string_view s1, core::string_view s2)
1251 {
1252 url u;
1253 BOOST_TEST_NO_THROW(u = url(s1));
1254 BOOST_TEST(u.remove_port().buffer() == s2);
1255 BOOST_TEST(! u.has_port());
1256 BOOST_TEST(u.port().empty());
1257 BOOST_TEST_EQ(u.port_number(), 0);
1258 };
1259
1260 auto const setn = [](core::string_view s1,
1261 std::uint16_t n, core::string_view s2)
1262 {
1263 url u;
1264 BOOST_TEST_NO_THROW(u = url(s1));
1265 BOOST_TEST(u.set_port_number(n).buffer() == s2);
1266 BOOST_TEST(u.has_port());
1267 BOOST_TEST_EQ(u.port_number(), n);
1268 };
1269
1270 auto const set = [](core::string_view s1,
1271 std::uint16_t n, core::string_view s2,
1272 core::string_view s3)
1273 {
1274 url u;
1275 BOOST_TEST_NO_THROW(u = url(s1));
1276 BOOST_TEST(u.set_port(s2).buffer() == s3);
1277 BOOST_TEST(u.has_port());
1278 BOOST_TEST_EQ(u.port_number(), n);
1279 BOOST_TEST_EQ(u.port(), s2);
1280 };
1281
1282 BOOST_TEST_THROWS(
1283 url().set_port("x"),
1284 std::exception);
1285
1286 remove("", "");
1287 remove("/", "/");
1288 remove("//", "//");
1289 remove("//:0", "//");
1290 remove("//:80", "//");
1291 remove("//:65535", "//");
1292 remove("//:999999", "//");
1293 remove("//:999999/", "///");
1294 remove("//x:999999/", "//x/");
1295 remove("//a:b@x.y:8080/path/to/file.txt?#",
1296 "//a:b@x.y/path/to/file.txt?#");
1297
1298 remove("x:", "x:");
1299 remove("x:/", "x:/");
1300 remove("x://", "x://");
1301 remove("x://:0", "x://");
1302 remove("x://:80", "x://");
1303 remove("x://:65535", "x://");
1304 remove("x://:999999", "x://");
1305 remove("x://:999999/", "x:///");
1306 remove("x://x:999999/", "x://x/");
1307 remove("x://a:b@x.y:8080/path/to/file.txt?#",
1308 "x://a:b@x.y/path/to/file.txt?#");
1309
1310 setn("", 0, "//:0");
1311 setn("", 443, "//:443");
1312 setn("", 65535, "//:65535");
1313 setn("/", 0, "//:0/");
1314 setn("//", 0, "//:0");
1315 setn("///", 0, "//:0/");
1316 setn("//x/", 0, "//x:0/");
1317 setn("//x/y", 0, "//x:0/y");
1318 setn("//a:b@/y", 0, "//a:b@:0/y");
1319 setn("//a:b@c/y", 0, "//a:b@c:0/y");
1320 setn("//a:b@x.y/path/to/file.txt?#", 8080,
1321 "//a:b@x.y:8080/path/to/file.txt?#");
1322
1323 setn("g:", 0, "g://:0");
1324 setn("g:", 443, "g://:443");
1325 setn("g:", 65535, "g://:65535");
1326 setn("g:/", 0, "g://:0/");
1327 setn("g://", 0, "g://:0");
1328 setn("g:///", 0, "g://:0/");
1329 setn("g://x/", 0, "g://x:0/");
1330 setn("g://x/y", 0, "g://x:0/y");
1331 setn("g://a:b@/y", 0, "g://a:b@:0/y");
1332 setn("g://a:b@c/y", 0, "g://a:b@c:0/y");
1333 setn("g://a:b@x.y/path/to/file.txt?#", 8080,
1334 "g://a:b@x.y:8080/path/to/file.txt?#");
1335
1336 set("", 0, "", "//:");
1337 set("/", 0, "", "//:/");
1338 set("//", 0, "", "//:");
1339 set("///", 0, "", "//:/");
1340 set("//x/", 0, "", "//x:/");
1341 set("//x/y", 0, "", "//x:/y");
1342 set("//a:b@/y", 0, "", "//a:b@:/y");
1343 set("//a:b@c/y", 0, "", "//a:b@c:/y");
1344 set("//a:b@x.y/path/to/file.txt?#", 0, "",
1345 "//a:b@x.y:/path/to/file.txt?#");
1346
1347 set("g:", 0, "", "g://:");
1348 set("g:/", 0, "", "g://:/");
1349 set("g://", 0, "", "g://:");
1350 set("g:///", 0, "", "g://:/");
1351 set("g://x/", 0, "", "g://x:/");
1352 set("g://x/y", 0, "", "g://x:/y");
1353 set("g://a:b@/y", 0, "", "g://a:b@:/y");
1354 set("g://a:b@c/y", 0, "", "g://a:b@c:/y");
1355 set("g://a:b@x.y/path/to/file.txt?#", 0, "",
1356 "g://a:b@x.y:/path/to/file.txt?#");
1357
1358 set("", 0, "0", "//:0");
1359 set("", 443, "443", "//:443");
1360 set("", 65535, "65535", "//:65535");
1361 set("/", 0, "0", "//:0/");
1362 set("//", 0, "0", "//:0");
1363 set("///", 0, "0", "//:0/");
1364 set("//x/", 0, "0", "//x:0/");
1365 set("//x/y", 0, "0", "//x:0/y");
1366 set("//a:b@/y", 0, "0", "//a:b@:0/y");
1367 set("//a:b@c/y", 0, "0", "//a:b@c:0/y");
1368 set("//a:b@x.y/path/to/file.txt?#", 8080, "8080",
1369 "//a:b@x.y:8080/path/to/file.txt?#");
1370
1371 set("g:", 0, "0", "g://:0");
1372 set("g:", 443, "443", "g://:443");
1373 set("g:", 65535, "65535", "g://:65535");
1374 set("g:/", 0, "0", "g://:0/");
1375 set("g://", 0, "0", "g://:0");
1376 set("g:///", 0, "0", "g://:0/");
1377 set("g://x/", 0, "0", "g://x:0/");
1378 set("g://x/y", 0, "0", "g://x:0/y");
1379 set("g://a:b@/y", 0, "0", "g://a:b@:0/y");
1380 set("g://a:b@c/y", 0, "0", "g://a:b@c:0/y");
1381 set("g://a:b@x.y/path/to/file.txt?#", 8080, "8080",
1382 "g://a:b@x.y:8080/path/to/file.txt?#");
1383
1384 // self-intersection
1385 modify(
1386 before: "x://@?65535",
1387 after: "x://@:65535?65535",
1388 f: [](url_base& u)
1389 {
1390 u.set_port(u.encoded_query());
1391 });
1392 }
1393
1394 //--------------------------------------------
1395
1396 void
1397 testQuery()
1398 {
1399 // has_query
1400 {
1401 {
1402 url u;
1403 BOOST_TEST(! u.has_query());
1404 }
1405 {
1406 url u("?");
1407 BOOST_TEST(u.has_query());
1408 }
1409 {
1410 url u("?x");
1411 BOOST_TEST(u.has_query());
1412 }
1413 }
1414
1415 // set_encoded_query
1416 {
1417 {
1418 url u;
1419 u.set_encoded_query("");
1420 BOOST_TEST(u.has_query());
1421 BOOST_TEST_EQ(u.buffer(), "?");
1422 BOOST_TEST_EQ(u.encoded_query(), "");
1423 }
1424 {
1425 url u;
1426 u.set_encoded_query("x");
1427 BOOST_TEST(u.has_query());
1428 BOOST_TEST_EQ(u.buffer(), "?x");
1429 BOOST_TEST_EQ(u.encoded_query(), "x");
1430 }
1431 {
1432 url u;
1433 u.set_encoded_query("%41");
1434 BOOST_TEST(u.has_query());
1435 BOOST_TEST_EQ(u.buffer(), "?%41");
1436 BOOST_TEST_EQ(u.encoded_query(), "%41");
1437 BOOST_TEST_EQ(u.query(), "A");
1438 }
1439 {
1440 url u;
1441 BOOST_TEST_THROWS(
1442 u.set_encoded_query("%%"),
1443 system::system_error);
1444 BOOST_TEST_THROWS(
1445 u.set_encoded_query("%fg"),
1446 system::system_error);
1447 }
1448 }
1449
1450 // set_query
1451 {
1452 auto good = [](
1453 core::string_view q, core::string_view us)
1454 {
1455 url u;
1456 u.set_query(q);
1457 BOOST_TEST(u.has_query());
1458 BOOST_TEST_EQ(u.buffer(), us);
1459 BOOST_TEST_EQ(u.query(), q);
1460 };
1461 good("", "?");
1462 good("x", "?x");
1463 good("%41", "?%2541");
1464 good("%%fg", "?%25%25fg");
1465 good("{}", "?%7B%7D");
1466
1467 // issue #245
1468 {
1469 url u;
1470 u.set_query("");
1471 u.set_query("");
1472 BOOST_TEST_EQ(u.buffer(), "?");
1473 }
1474 }
1475
1476 // has_query
1477 {
1478 url u;
1479 BOOST_TEST_NO_THROW(u = url("?query"));
1480 BOOST_TEST(u.has_query());
1481 u.clear();
1482 BOOST_TEST(! u.has_query());
1483 BOOST_TEST_NO_THROW(u = url("?"));
1484 BOOST_TEST(u.has_query());
1485 }
1486
1487 // remove_query
1488 {
1489 url u;
1490 BOOST_TEST_NO_THROW(u = url("?query"));
1491 BOOST_TEST(u.has_query());
1492 BOOST_TEST_EQ(u.encoded_query(), "query");
1493 BOOST_TEST_EQ(u.params().size(), 1u);
1494 BOOST_TEST_EQ(u.remove_query().has_query(), false);
1495 BOOST_TEST_EQ(u.encoded_query(), "");
1496 BOOST_TEST_EQ(u.query(), "");
1497 BOOST_TEST_EQ(u.params().size(), 0u);
1498 BOOST_TEST_EQ(u.encoded_params().size(), 0u);
1499 }
1500
1501 // set_encoded_query
1502 {
1503 url u;
1504 BOOST_TEST(! u.has_query());
1505 u.set_encoded_query("k1=v1&k2=#v2");
1506 BOOST_TEST(u.has_query());
1507 BOOST_TEST_EQ(u.params().size(), 2u);
1508 BOOST_TEST_EQ((*u.params().begin()).key, "k1");
1509 BOOST_TEST_EQ((*u.params().begin()).value, "v1");
1510 BOOST_TEST_EQ((*std::next(u.params().begin())).key, "k2");
1511 BOOST_TEST_EQ((*std::next(u.params().begin())).value, "#v2");
1512
1513 u.set_encoded_query("");
1514 BOOST_TEST(u.has_query());
1515 BOOST_TEST(u.encoded_query().empty());
1516 BOOST_TEST_EQ(u.params().size(), 1);
1517 }
1518
1519 // set_query
1520 {
1521 url u;
1522 BOOST_TEST(! u.has_query());
1523 u.set_query("!@#$%^&*()_+=-;:'{}[]|\\?/>.<,");
1524 BOOST_TEST(u.has_query());
1525 BOOST_TEST(u.encoded_query() ==
1526 "!@%23$%25%5E&*()_+=-;:'%7B%7D[]%7C%5C?/%3E.%3C,");
1527 BOOST_TEST_EQ(u.params().size(), 2u);
1528 BOOST_TEST_EQ((*u.params().begin()).key, "!@#$%^");
1529 BOOST_TEST_EQ((*u.params().begin()).value, "");
1530 BOOST_TEST_EQ((*std::next(u.params().begin())).key, "*()_ ");
1531 BOOST_TEST_EQ((*std::next(u.params().begin())).value,
1532 "-;:'{}[]|\\?/>.<,");
1533 }
1534
1535 // remove_query
1536 {
1537 {
1538 url u;
1539 u.remove_query();
1540 BOOST_TEST(! u.has_query());
1541 }
1542 {
1543 url u("?");
1544 u.remove_query();
1545 BOOST_TEST(! u.has_query());
1546 }
1547 {
1548 url u("?x");
1549 u.remove_query();
1550 BOOST_TEST(! u.has_query());
1551 }
1552 }
1553
1554 // self-intersection
1555 modify(
1556 before: "#abracadabra",
1557 after: "?abracadabra#abracadabra",
1558 f: [](url_base& u)
1559 {
1560 u.set_encoded_query(
1561 u.encoded_fragment());
1562 });
1563 modify(
1564 before: "#abracadabra",
1565 after: "?abracadabra#abracadabra",
1566 f: [](url_base& u)
1567 {
1568 u.set_query(
1569 u.encoded_fragment());
1570 });
1571 }
1572
1573 void
1574 testJavadocs()
1575 {
1576 //----------------------------------------
1577 //
1578 // Scheme
1579 //
1580 //----------------------------------------
1581
1582 // set_scheme
1583 assert( url( "http://www.example.com" ).set_scheme( "https" ).scheme_id() == scheme::https );
1584
1585 // set_scheme_id
1586 assert( url( "http://example.com/echo.cgi" ).set_scheme_id( scheme::wss ).buffer() == "wss://example.com/echo.cgi" );
1587
1588 // remove_scheme
1589 assert( url("http://www.example.com/index.htm" ).remove_scheme().buffer() == "//www.example.com/index.htm" );
1590
1591 //----------------------------------------
1592 //
1593 // Authority
1594 //
1595 //----------------------------------------
1596
1597 // set_encoded_authority
1598 assert( url().set_encoded_authority( "My%20Computer" ).has_authority() );
1599
1600 // remove_authority
1601 assert( url( "http://example.com/echo.cgi" ).remove_authority().buffer() == "http:/echo.cgi" );
1602
1603 //----------------------------------------
1604 //
1605 // Userinfo
1606 //
1607 //----------------------------------------
1608
1609 // set_userinfo
1610 assert( url( "http://example.com" ).set_userinfo( "user:pass" ).encoded_user() == "user" );
1611
1612 // set_encoded_userinfo
1613 assert( url( "http://example.com" ).set_encoded_userinfo( "john%20doe" ).user() == "john doe" );
1614
1615 // remove_userinfo
1616 assert( url( "http://user@example.com" ).remove_userinfo().has_userinfo() == false );
1617
1618 //----------------------------------------
1619
1620 // set_user
1621 assert( url().set_user("john doe").encoded_userinfo() == "john%20doe" );
1622
1623 // set_encoded_user
1624 assert( url().set_encoded_user("john%20doe").userinfo() == "john doe" );
1625
1626 // set_password
1627 assert( url("http://user@example.com").set_password( "pass" ).encoded_userinfo() == "user:pass" );
1628
1629 // set_encoded_password
1630 assert( url("http://user@example.com").set_encoded_password( "pass" ).encoded_userinfo() == "user:pass" );
1631
1632 // remove_password
1633 assert( url( "http://user:pass@example.com" ).remove_password().encoded_authority() == "user@example.com" );
1634
1635 //----------------------------------------
1636 //
1637 // Host
1638 //
1639 //----------------------------------------
1640
1641 // set_host
1642 assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
1643
1644 // set_encoded_host
1645 assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
1646
1647 // set_host_address
1648 assert( url( "http://www.example.com" ).set_host_address( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
1649
1650 // set_encoded_host_address
1651 assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
1652
1653 // set_host_ipv4
1654 assert( url("http://www.example.com").set_host_ipv4( ipv4_address( "127.0.0.1" ) ).buffer() == "http://127.0.0.1" );
1655
1656 // set_host_ipv6
1657 assert( url().set_host_ipv6( ipv6_address( "1::6:c0a8:1" ) ).encoded_authority() == "[1::6:c0a8:1]" );
1658
1659 // set_host_ipvfuture
1660 assert( url().set_host_ipvfuture( "v42.bis" ).buffer() == "//[v42.bis]" );
1661
1662 // set_host_name
1663 assert( url( "http://www.example.com/index.htm").set_host_name( "localhost" ).host_address() == "localhost" );
1664
1665 // set_encoded_host_name
1666 assert( url( "http://www.example.com/index.htm").set_encoded_host_name( "localhost" ).host_address() == "localhost" );
1667
1668 //----------------------------------------
1669 //
1670 // Port
1671 //
1672 //----------------------------------------
1673
1674 // set_port
1675 assert( url( "http://www.example.com" ).set_port_number( 8080 ).encoded_authority() == "www.example.com:8080" );
1676
1677 // set_port
1678 assert( url( "http://www.example.com" ).set_port( "8080" ).encoded_authority() == "www.example.com:8080" );
1679
1680 // remove_port
1681 assert( url( "http://www.example.com:80" ).remove_port().encoded_authority() == "www.example.com" );
1682
1683 //----------------------------------------
1684 //
1685 // Path
1686 //
1687 //----------------------------------------
1688
1689 // set_path_absolute
1690 {
1691 url u( "path/to/file.txt" );
1692 assert( u.set_path_absolute( true ) );
1693 assert( u.buffer() == "/path/to/file.txt" );
1694 }
1695
1696 // set_path
1697 {
1698 url u( "http://www.example.com" );
1699
1700 u.set_path( "path/to/file.txt" );
1701
1702 assert( u.path() == "/path/to/file.txt" );
1703 }
1704
1705 // set_encoded_path
1706 {
1707 url u( "http://www.example.com" );
1708
1709 u.set_encoded_path( "path/to/file.txt" );
1710
1711 assert( u.encoded_path() == "/path/to/file.txt" );
1712 }
1713
1714 // segments
1715 {
1716 url u( "http://example.com/path/to/file.txt" );
1717
1718 segments_ref sv = u.segments();
1719
1720 (void)sv;
1721 }
1722
1723 // encoded_segments
1724 {
1725 url u( "http://example.com/path/to/file.txt" );
1726
1727 segments_encoded_ref sv = u.encoded_segments();
1728
1729 (void)sv;
1730 }
1731
1732 //----------------------------------------
1733 //
1734 // Query
1735 //
1736 //----------------------------------------
1737
1738 // set_query
1739 assert( url( "http://example.com" ).set_query( "id=42" ).query() == "id=42" );
1740
1741 // set_encoded_query
1742 assert( url( "http://example.com" ).set_encoded_query( "id=42" ).encoded_query() == "id=42" );
1743
1744 // params
1745 {
1746 params_ref pv = url( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).params();
1747
1748 (void)pv;
1749 }
1750
1751 // encoded_params
1752 {
1753 params_encoded_ref pv = url( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).encoded_params();
1754
1755 (void)pv;
1756 }
1757
1758 // set_params
1759 assert( url( "http://example.com" ).set_params( {{"id", "42"}} ).encoded_query() == "id=42" );
1760
1761 // set_encoded_params
1762 assert( url( "http://example.com" ).set_encoded_params( {{"id", "42"}} ).encoded_query() == "id=42" );
1763
1764
1765 // remove_query
1766 assert( url( "http://www.example.com?id=42" ).remove_query().buffer() == "http://www.example.com" );
1767
1768 //----------------------------------------
1769 //
1770 // Fragment
1771 //
1772 //----------------------------------------
1773
1774 // remove_fragment
1775 assert( url( "?first=john&last=doe#anchor" ).remove_fragment().buffer() == "?first=john&last=doe" );
1776
1777 // set_fragment
1778 assert( url("?first=john&last=doe" ).set_encoded_fragment( "john doe" ).encoded_fragment() == "john%20doe" );
1779
1780 // set_encoded_fragment
1781 assert( url("?first=john&last=doe" ).set_encoded_fragment( "john%2Ddoe" ).fragment() == "john-doe" );
1782
1783 //----------------------------------------
1784 //
1785 // Compound Fields
1786 //
1787 //----------------------------------------
1788
1789 // remove_origin
1790 assert( url( "http://www.example.com/index.htm" ).remove_origin().buffer() == "/index.htm" );
1791 }
1792
1793 void
1794 run()
1795 {
1796 testSetScheme();
1797 testSetAuthority();
1798 testSetUserinfo();
1799 testSetUser();
1800 testSetPassword();
1801 testSetHost();
1802 testSetPort();
1803 testQuery();
1804 testJavadocs();
1805 }
1806};
1807
1808TEST_SUITE(
1809 url_base_test,
1810 "boost.url.url_base");
1811
1812} // urls
1813} // boost
1814

source code of boost/libs/url/test/unit/url_base.cpp