View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.utils;
18  
19  import static org.apache.juneau.UriRelativity.*;
20  import static org.apache.juneau.UriResolution.*;
21  import static org.apache.juneau.commons.utils.Utils.*;
22  import static org.apache.juneau.junit.bct.BctAssertions.*;
23  import static org.junit.jupiter.api.Assertions.*;
24  
25  import org.apache.juneau.*;
26  import org.junit.jupiter.params.*;
27  import org.junit.jupiter.params.provider.*;
28  
29  /**
30   * Verifies that the resolveUri() methods in UriContext work correctly.
31   */
32  class UriContextResolutionCombo_Test extends TestBase {
33  
34  	private static final Tester[] TESTERS = {
35  
36  		// Happy cases - All URL parts known.
37  		tester(1,
38  			"Happy-1a",
39  			input(
40  				"http://host:port","/context","/resource","/path",
41  				"http://foo.com:123/foobar"
42  			),
43  			results(
44  				"http://foo.com:123/foobar",
45  				"http://foo.com:123/foobar",
46  				"http://foo.com:123/foobar",
47  				"http://foo.com:123/foobar",
48  				"http://foo.com:123/foobar",
49  				"http://foo.com:123/foobar"
50  			)
51  		),
52  		tester(2,
53  			"Happy-2",
54  			input(
55  				"http://host:port","/context","/resource","/path",
56  				"http://foo.com:123"
57  			),
58  			results(
59  				"http://foo.com:123",
60  				"http://foo.com:123",
61  				"http://foo.com:123",
62  				"http://foo.com:123",
63  				"http://foo.com:123",
64  				"http://foo.com:123"
65  			)
66  		),
67  		tester(3,
68  			"Happy-3",
69  			input(
70  				"http://host:port","/context","/resource","/path",
71  				"/foobar"
72  			),
73  			results(
74  				"http://host:port/foobar",
75  				"http://host:port/foobar",
76  				"/foobar",
77  				"/foobar",
78  				"/foobar",
79  				"/foobar"
80  			)
81  		),
82  		tester(4,
83  			"Happy-4",
84  			input(
85  				"http://host:port","/context","/resource","/path",
86  				"/"
87  			),
88  			results(
89  				"http://host:port",
90  				"http://host:port",
91  				"/",
92  				"/",
93  				"/",
94  				"/"
95  			)
96  		),
97  		tester(5,
98  			"Happy-5",
99  			input(
100 				"http://host:port","/context","/resource","/path",
101 				"foobar"
102 			),
103 			results(
104 				"http://host:port/context/resource/foobar",
105 				"http://host:port/context/resource/foobar",
106 				"/context/resource/foobar",
107 				"/context/resource/foobar",
108 				"foobar",
109 				"foobar"
110 			)
111 		),
112 		tester(6,
113 			"Happy-6",
114 			input(
115 				"http://host:port","/context","/resource","/path",
116 				""
117 			),
118 			results(
119 				"http://host:port/context/resource",
120 				"http://host:port/context/resource/path",
121 				"/context/resource",
122 				"/context/resource/path",
123 				"",
124 				""
125 			)
126 		),
127 		tester(7,
128 			"Happy-7",
129 			input(
130 				"http://host:port","/context","/resource","/path",
131 				"context:/foo"
132 			),
133 			results(
134 				"http://host:port/context/foo",
135 				"http://host:port/context/foo",
136 				"/context/foo",
137 				"/context/foo",
138 				"/context/foo",
139 				"/context/foo"
140 			)
141 		),
142 		tester(8,
143 			"Happy-8",
144 			input(
145 				"http://host:port","/context","/resource","/path",
146 				"context:/"
147 			),
148 			results(
149 				"http://host:port/context",
150 				"http://host:port/context",
151 				"/context",
152 				"/context",
153 				"/context",
154 				"/context"
155 			)
156 		),
157 		tester(9,
158 			"Happy-9",
159 			input(
160 				"http://host:port","/context","/resource","/path",
161 				"servlet:/foo"
162 			),
163 			results(
164 				"http://host:port/context/resource/foo",
165 				"http://host:port/context/resource/foo",
166 				"/context/resource/foo",
167 				"/context/resource/foo",
168 				"/context/resource/foo",
169 				"/context/resource/foo"
170 			)
171 		),
172 		tester(10,
173 			"Happy-10",
174 			input(
175 				"http://host:port","/context","/resource","/path",
176 				"servlet:/"
177 			),
178 			results(
179 				"http://host:port/context/resource",
180 				"http://host:port/context/resource",
181 				"/context/resource",
182 				"/context/resource",
183 				"/context/resource",
184 				"/context/resource"
185 			)
186 		),
187 
188 		// Multiple context and resource parts
189 		tester(11,
190 			"MultiContextResource-1",
191 			input(
192 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
193 				"http://foo.com:123/foobar"
194 			),
195 			results(
196 				"http://foo.com:123/foobar",
197 				"http://foo.com:123/foobar",
198 				"http://foo.com:123/foobar",
199 				"http://foo.com:123/foobar",
200 				"http://foo.com:123/foobar",
201 				"http://foo.com:123/foobar"
202 			)
203 		),
204 		tester(12,
205 			"MultiContextResource-2",
206 			input(
207 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
208 				"http://foo.com:123"
209 			),
210 			results(
211 				"http://foo.com:123",
212 				"http://foo.com:123",
213 				"http://foo.com:123",
214 				"http://foo.com:123",
215 				"http://foo.com:123",
216 				"http://foo.com:123"
217 			)
218 		),
219 		tester(13,
220 			"MultiContextResource-3",
221 			input(
222 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
223 				"/foobar"
224 			),
225 			results(
226 				"http://host:port/foobar",
227 				"http://host:port/foobar",
228 				"/foobar",
229 				"/foobar",
230 				"/foobar",
231 				"/foobar"
232 			)
233 		),
234 		tester(14,
235 			"MultiContextResource-4",
236 			input(
237 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
238 				"/"
239 			),
240 			results(
241 				"http://host:port",
242 				"http://host:port",
243 				"/",
244 				"/",
245 				"/",
246 				"/"
247 			)
248 		),
249 		tester(15,
250 			"MultiContextResource-5",
251 			input(
252 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
253 				"foobar"
254 			),
255 			results(
256 				"http://host:port/c1/c2/r1/r2/foobar",
257 				"http://host:port/c1/c2/r1/r2/p1/foobar",
258 				"/c1/c2/r1/r2/foobar",
259 				"/c1/c2/r1/r2/p1/foobar",
260 				"foobar",
261 				"foobar"
262 			)
263 		),
264 		tester(16,
265 			"MultiContextResource-6",
266 			input(
267 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
268 				""
269 			),
270 			results(
271 				"http://host:port/c1/c2/r1/r2",
272 				"http://host:port/c1/c2/r1/r2/p1/p2",
273 				"/c1/c2/r1/r2",
274 				"/c1/c2/r1/r2/p1/p2",
275 				"",
276 				""
277 			)
278 		),
279 		tester(17,
280 			"MultiContextResource-7",
281 			input(
282 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
283 				"context:/foo"
284 			),
285 			results(
286 				"http://host:port/c1/c2/foo",
287 				"http://host:port/c1/c2/foo",
288 				"/c1/c2/foo",
289 				"/c1/c2/foo",
290 				"/c1/c2/foo",
291 				"/c1/c2/foo"
292 			)
293 		),
294 		tester(18,
295 			"MultiContextResource-8",
296 			input(
297 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
298 				"context:/"
299 			),
300 			results(
301 				"http://host:port/c1/c2",
302 				"http://host:port/c1/c2",
303 				"/c1/c2",
304 				"/c1/c2",
305 				"/c1/c2",
306 				"/c1/c2"
307 			)
308 		),
309 		tester(19,
310 			"MultiContextResource-9",
311 			input(
312 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
313 				"servlet:/foo"
314 			),
315 			results(
316 				"http://host:port/c1/c2/r1/r2/foo",
317 				"http://host:port/c1/c2/r1/r2/foo",
318 				"/c1/c2/r1/r2/foo",
319 				"/c1/c2/r1/r2/foo",
320 				"/c1/c2/r1/r2/foo",
321 				"/c1/c2/r1/r2/foo"
322 			)
323 		),
324 		tester(20,
325 			"MultiContextResource-10",
326 			input(
327 				"http://host:port","/c1/c2","/r1/r2","/p1/p2",
328 				"servlet:/"
329 			),
330 			results(
331 				"http://host:port/c1/c2/r1/r2",
332 				"http://host:port/c1/c2/r1/r2",
333 				"/c1/c2/r1/r2",
334 				"/c1/c2/r1/r2",
335 				"/c1/c2/r1/r2",
336 				"/c1/c2/r1/r2"
337 			)
338 		),
339 
340 		// No authority given
341 		tester(21,
342 			"NoAuthority-1",
343 			input(
344 				"","/context","/resource","/path",
345 				"http://foo.com:123/foobar"
346 			),
347 			results(
348 				"http://foo.com:123/foobar",
349 				"http://foo.com:123/foobar",
350 				"http://foo.com:123/foobar",
351 				"http://foo.com:123/foobar",
352 				"http://foo.com:123/foobar",
353 				"http://foo.com:123/foobar"
354 			)
355 		),
356 		tester(22,
357 			"NoAuthority-2",
358 			input(
359 				"","/context","/resource","/path",
360 				"http://foo.com:123"
361 			),
362 			results(
363 				"http://foo.com:123",
364 				"http://foo.com:123",
365 				"http://foo.com:123",
366 				"http://foo.com:123",
367 				"http://foo.com:123",
368 				"http://foo.com:123"
369 			)
370 		),
371 		tester(23,
372 			"NoAuthority-3",
373 			input(
374 				"","/context","/resource","/path",
375 				"/foobar"
376 			),
377 			results(
378 				"/foobar",
379 				"/foobar",
380 				"/foobar",
381 				"/foobar",
382 				"/foobar",
383 				"/foobar"
384 			)
385 		),
386 		tester(24,
387 			"NoAuthority-4",
388 			input(
389 				"","/context","/resource","/path",
390 				"/"
391 			),
392 			results(
393 				"/",
394 				"/",
395 				"/",
396 				"/",
397 				"/",
398 				"/"
399 			)
400 		),
401 		tester(25,
402 			"NoAuthority-5",
403 			input(
404 				"","/context","/resource","/path",
405 				"foobar"
406 			),
407 			results(
408 				"/context/resource/foobar",
409 				"/context/resource/foobar",
410 				"/context/resource/foobar",
411 				"/context/resource/foobar",
412 				"foobar",
413 				"foobar"
414 			)
415 		),
416 		tester(26,
417 			"NoAuthority-6",
418 			input(
419 				"","/context","/resource","/path",
420 				""
421 			),
422 			results(
423 				"/context/resource",
424 				"/context/resource/path",
425 				"/context/resource",
426 				"/context/resource/path",
427 				"",
428 				""
429 			)
430 		),
431 		tester(27,
432 			"NoAuthority-7",
433 			input(
434 				"","/context","/resource","/path",
435 				"context:/foo"
436 			),
437 			results(
438 				"/context/foo",
439 				"/context/foo",
440 				"/context/foo",
441 				"/context/foo",
442 				"/context/foo",
443 				"/context/foo"
444 			)
445 		),
446 		tester(28,
447 			"NoAuthority-8",
448 			input(
449 				"","/context","/resource","/path",
450 				"context:/"
451 			),
452 			results(
453 				"/context",
454 				"/context",
455 				"/context",
456 				"/context",
457 				"/context",
458 				"/context"
459 			)
460 		),
461 		tester(29,
462 			"NoAuthority-9",
463 			input(
464 				"","/context","/resource","/path",
465 				"servlet:/foo"
466 			),
467 			results(
468 				"/context/resource/foo",
469 				"/context/resource/foo",
470 				"/context/resource/foo",
471 				"/context/resource/foo",
472 				"/context/resource/foo",
473 				"/context/resource/foo"
474 			)
475 		),
476 		tester(30,
477 			"NoAuthority-10",
478 			input(
479 				"","/context","/resource","/path",
480 				"servlet:/"
481 			),
482 			results(
483 				"/context/resource",
484 				"/context/resource",
485 				"/context/resource",
486 				"/context/resource",
487 				"/context/resource",
488 				"/context/resource"
489 			)
490 		),
491 
492 		// No authority or context given
493 		tester(31,
494 			"NoAuthorityOrContext-1",
495 			input(
496 				"","","/resource","/path",
497 				"http://foo.com:123/foobar"
498 			),
499 			results(
500 				"http://foo.com:123/foobar",
501 				"http://foo.com:123/foobar",
502 				"http://foo.com:123/foobar",
503 				"http://foo.com:123/foobar",
504 				"http://foo.com:123/foobar",
505 				"http://foo.com:123/foobar"
506 			)
507 		),
508 		tester(32,
509 			"NoAuthorityOrContext-2",
510 			input(
511 				"","","/resource","/path",
512 				"http://foo.com:123"
513 			),
514 			results(
515 				"http://foo.com:123",
516 				"http://foo.com:123",
517 				"http://foo.com:123",
518 				"http://foo.com:123",
519 				"http://foo.com:123",
520 				"http://foo.com:123"
521 			)
522 		),
523 		tester(33,
524 			"NoAuthorityOrContext-3",
525 			input(
526 				"","","/resource","/path",
527 				"/foobar"
528 			),
529 			results(
530 				"/foobar",
531 				"/foobar",
532 				"/foobar",
533 				"/foobar",
534 				"/foobar",
535 				"/foobar"
536 			)
537 		),
538 		tester(34,
539 			"NoAuthorityOrContext-4",
540 			input(
541 				"","","/resource","/path",
542 				"/"
543 			),
544 			results(
545 				"/",
546 				"/",
547 				"/",
548 				"/",
549 				"/",
550 				"/"
551 			)
552 		),
553 		tester(35,
554 			"NoAuthorityOrContext-5",
555 			input(
556 				"","","/resource","/path",
557 				"foobar"
558 			),
559 			results(
560 				"/resource/foobar",
561 				"/resource/foobar",
562 				"/resource/foobar",
563 				"/resource/foobar",
564 				"foobar",
565 				"foobar"
566 			)
567 		),
568 		tester(36,
569 			"NoAuthorityOrContext-6",
570 			input(
571 				"","","/resource","/path",
572 				""
573 			),
574 			results(
575 				"/resource",
576 				"/resource/path",
577 				"/resource",
578 				"/resource/path",
579 				"",
580 				""
581 			)
582 		),
583 		tester(37,
584 			"NoAuthorityOrContext-7",
585 			input(
586 				"","","/resource","/path",
587 				"context:/foo"
588 			),
589 			results(
590 				"/foo",
591 				"/foo",
592 				"/foo",
593 				"/foo",
594 				"/foo",
595 				"/foo"
596 			)
597 		),
598 		tester(38,
599 			"NoAuthorityOrContext-8",
600 			input(
601 				"","","/resource","/path",
602 				"context:/"
603 			),
604 			results(
605 				"/",
606 				"/",
607 				"/",
608 				"/",
609 				"/",
610 				"/"
611 			)
612 		),
613 		tester(39,
614 			"NoAuthorityOrContext-9",
615 			input(
616 				"","","/resource","/path",
617 				"servlet:/foo"
618 			),
619 			results(
620 				"/resource/foo",
621 				"/resource/foo",
622 				"/resource/foo",
623 				"/resource/foo",
624 				"/resource/foo",
625 				"/resource/foo"
626 			)
627 		),
628 		tester(40,
629 			"NoAuthorityOrContext-10",
630 			input(
631 				"","","/resource","/path",
632 				"servlet:/"
633 			),
634 			results(
635 				"/resource",
636 				"/resource",
637 				"/resource",
638 				"/resource",
639 				"/resource",
640 				"/resource"
641 			)
642 		),
643 
644 		// No authority or context or resource given
645 		tester(41,
646 			"NoAuthorityOrContextOrResource-1",
647 			input(
648 				"","","","/path",
649 				"http://foo.com:123/foobar"
650 			),
651 			results(
652 				"http://foo.com:123/foobar",
653 				"http://foo.com:123/foobar",
654 				"http://foo.com:123/foobar",
655 				"http://foo.com:123/foobar",
656 				"http://foo.com:123/foobar",
657 				"http://foo.com:123/foobar"
658 			)
659 		),
660 		tester(42,
661 			"NoAuthorityOrContextOrResource-2",
662 			input(
663 				"","","","/path",
664 				"http://foo.com:123"
665 			),
666 			results(
667 				"http://foo.com:123",
668 				"http://foo.com:123",
669 				"http://foo.com:123",
670 				"http://foo.com:123",
671 				"http://foo.com:123",
672 				"http://foo.com:123"
673 			)
674 		),
675 		tester(43,
676 			"NoAuthorityOrContextOrResource-3",
677 			input(
678 				"","","","/path",
679 				"/foobar"
680 			),
681 			results(
682 				"/foobar",
683 				"/foobar",
684 				"/foobar",
685 				"/foobar",
686 				"/foobar",
687 				"/foobar"
688 			)
689 		),
690 		tester(44,
691 			"NoAuthorityOrContextOrResource-4",
692 			input(
693 				"","","","/path",
694 				"/"
695 			),
696 			results(
697 				"/",
698 				"/",
699 				"/",
700 				"/",
701 				"/",
702 				"/"
703 			)
704 		),
705 		tester(45,
706 			"NoAuthorityOrContextOrResource-5",
707 			input(
708 				"","","","/path",
709 				"foobar"
710 			),
711 			results(
712 				"/foobar",
713 				"/foobar",
714 				"/foobar",
715 				"/foobar",
716 				"foobar",
717 				"foobar"
718 			)
719 		),
720 		tester(46,
721 			"NoAuthorityOrContextOrResource-6",
722 			input(
723 				"","","","/path",
724 				""
725 			),
726 			results(
727 				"/",
728 				"/path",
729 				"/",
730 				"/path",
731 				"",
732 				""
733 			)
734 		),
735 		tester(47,
736 			"NoAuthorityOrContextOrResource-7",
737 			input(
738 				"","","","/path",
739 				"context:/foo"
740 			),
741 			results(
742 				"/foo",
743 				"/foo",
744 				"/foo",
745 				"/foo",
746 				"/foo",
747 				"/foo"
748 			)
749 		),
750 		tester(48,
751 			"NoAuthorityOrContextOrResource-8",
752 			input(
753 				"","","","/path",
754 				"context:/"
755 			),
756 			results(
757 				"/",
758 				"/",
759 				"/",
760 				"/",
761 				"/",
762 				"/"
763 			)
764 		),
765 		tester(49,
766 			"NoAuthorityOrContextOrResource-9",
767 			input(
768 				"","","","/path",
769 				"servlet:/foo"
770 			),
771 			results(
772 				"/foo",
773 				"/foo",
774 				"/foo",
775 				"/foo",
776 				"/foo",
777 				"/foo"
778 			)
779 		),
780 		tester(50,
781 			"NoAuthorityOrContextOrResource-10",
782 			input(
783 				"","","","/path",
784 				"servlet:/"
785 			),
786 			results(
787 				"/",
788 				"/",
789 				"/",
790 				"/",
791 				"/",
792 				"/"
793 			)
794 		),
795 
796 		// No context or resource given.
797 		tester(51,
798 			"NoContextOrResource-1",
799 			input(
800 				"http://host:port","","","/path",
801 				"http://foo.com:123/foobar"
802 			),
803 			results(
804 				"http://foo.com:123/foobar",
805 				"http://foo.com:123/foobar",
806 				"http://foo.com:123/foobar",
807 				"http://foo.com:123/foobar",
808 				"http://foo.com:123/foobar",
809 				"http://foo.com:123/foobar"
810 			)
811 		),
812 		tester(52,
813 			"NoContextOrResource-2",
814 			input(
815 				"http://host:port","","","/path",
816 				"http://foo.com:123"
817 			),
818 			results(
819 				"http://foo.com:123",
820 				"http://foo.com:123",
821 				"http://foo.com:123",
822 				"http://foo.com:123",
823 				"http://foo.com:123",
824 				"http://foo.com:123"
825 			)
826 		),
827 		tester(53,
828 			"NoContextOrResource-3",
829 			input(
830 				"http://host:port","","","/path",
831 				"/foobar"
832 			),
833 			results(
834 				"http://host:port/foobar",
835 				"http://host:port/foobar",
836 				"/foobar",
837 				"/foobar",
838 				"/foobar",
839 				"/foobar"
840 			)
841 		),
842 		tester(54,
843 			"NoContextOrResource-4",
844 			input(
845 				"http://host:port","","","/path",
846 				"/"
847 			),
848 			results(
849 				"http://host:port",
850 				"http://host:port",
851 				"/",
852 				"/",
853 				"/",
854 				"/"
855 			)
856 		),
857 		tester(55,
858 			"NoContextOrResource-5",
859 			input(
860 				"http://host:port","","","/path",
861 				"foobar"
862 			),
863 			results(
864 				"http://host:port/foobar",
865 				"http://host:port/foobar",
866 				"/foobar",
867 				"/foobar",
868 				"foobar",
869 				"foobar"
870 			)
871 		),
872 		tester(56,
873 			"NoContextOrResource-6",
874 			input(
875 				"http://host:port","","","/path",
876 				""
877 			),
878 			results(
879 				"http://host:port",
880 				"http://host:port/path",
881 				"/",
882 				"/path",
883 				"",
884 				""
885 			)
886 		),
887 		tester(57,
888 			"NoContextOrResource-7",
889 			input(
890 				"http://host:port","","","/path",
891 				"context:/foo"
892 			),
893 			results(
894 				"http://host:port/foo",
895 				"http://host:port/foo",
896 				"/foo",
897 				"/foo",
898 				"/foo",
899 				"/foo"
900 			)
901 		),
902 		tester(58,
903 			"NoContextOrResource-8",
904 			input(
905 				"http://host:port","","","/path",
906 				"context:/"
907 			),
908 			results(
909 				"http://host:port",
910 				"http://host:port",
911 				"/",
912 				"/",
913 				"/",
914 				"/"
915 			)
916 		),
917 		tester(59,
918 			"NoContextOrResource-9",
919 			input(
920 				"http://host:port","","","/path",
921 				"servlet:/foo"
922 			),
923 			results(
924 				"http://host:port/foo",
925 				"http://host:port/foo",
926 				"/foo",
927 				"/foo",
928 				"/foo",
929 				"/foo"
930 			)
931 		),
932 		tester(60,
933 			"NoContextOrResource-10",
934 			input(
935 				"http://host:port","","","/path",
936 				"servlet:/"
937 			),
938 			results(
939 				"http://host:port",
940 				"http://host:port",
941 				"/",
942 				"/",
943 				"/",
944 				"/"
945 			)
946 		),
947 
948 		// Test query string support (JUNEAU-117)
949 		tester(61,
950 			"request:?query",
951 			input(
952 				"http://host:port","/context","/resource","/path",
953 				"request:?foo=bar"
954 			),
955 			results(
956 				"http://host:port/context/resource/path?foo=bar",
957 				"http://host:port/context/resource/path?foo=bar",
958 				"/context/resource/path?foo=bar",
959 				"/context/resource/path?foo=bar",
960 				"/context/resource/path?foo=bar",
961 				"/context/resource/path?foo=bar"
962 			)
963 		),
964 		tester(62,
965 			"servlet:?query",
966 			input(
967 				"http://host:port","/context","/resource","/path",
968 				"servlet:?foo=bar"
969 			),
970 			results(
971 				"http://host:port/context/resource?foo=bar",
972 				"http://host:port/context/resource?foo=bar",
973 				"/context/resource?foo=bar",
974 				"/context/resource?foo=bar",
975 				"/context/resource?foo=bar",
976 				"/context/resource?foo=bar"
977 			)
978 		),
979 		tester(63,
980 			"context:?query",
981 			input(
982 				"http://host:port","/context","/resource","/path",
983 				"context:?foo=bar"
984 			),
985 			results(
986 				"http://host:port/context?foo=bar",
987 				"http://host:port/context?foo=bar",
988 				"/context?foo=bar",
989 				"/context?foo=bar",
990 				"/context?foo=bar",
991 				"/context?foo=bar"
992 			)
993 		),
994 		tester(64,
995 			"request:#hash",
996 			input(
997 				"http://host:port","/context","/resource","/path",
998 				"request:#section"
999 			),
1000 			results(
1001 				"http://host:port/context/resource/path#section",
1002 				"http://host:port/context/resource/path#section",
1003 				"/context/resource/path#section",
1004 				"/context/resource/path#section",
1005 				"/context/resource/path#section",
1006 				"/context/resource/path#section"
1007 			)
1008 		),
1009 		tester(65,
1010 			"request:pathOnly",
1011 			input(
1012 				"http://host:port","/context","/resource","/path",
1013 				"request:foo"
1014 			),
1015 			results(
1016 				"http://host:port/context/resource/path/foo",
1017 				"http://host:port/context/resource/path/foo",
1018 				"/context/resource/path/foo",
1019 				"/context/resource/path/foo",
1020 				"/context/resource/path/foo",
1021 				"/context/resource/path/foo"
1022 			)
1023 		),
1024 		tester(66,
1025 			"request:empty",
1026 			input(
1027 				"http://host:port","/context","/resource","/path",
1028 				"request:"
1029 			),
1030 			results(
1031 				"http://host:port/context/resource/path",
1032 				"http://host:port/context/resource/path",
1033 				"/context/resource/path",
1034 				"/context/resource/path",
1035 				"/context/resource/path",
1036 				"/context/resource/path"
1037 			)
1038 		)
1039 	};
1040 
1041 	private static class Tester {
1042 		final String label;
1043 		final Input input;
1044 		final Results results;
1045 
1046 		Tester(int index, String label, Input input, Results results) {
1047 			this.label = "[" + index + "] " + label;
1048 			this.input = input;
1049 			this.results = results;
1050 		}
1051 	}
1052 
1053 	private static class Input {
1054 		final String uri;
1055 		final String authority, context, resource, path;
1056 
1057 		Input(String authority, String context, String resource, String path, String uri) {
1058 			this.authority = authority;
1059 			this.context = context;
1060 			this.resource = resource;
1061 			this.path = path;
1062 			this.uri = uri;
1063 		}
1064 	}
1065 
1066 	private static class Results {
1067 		final String aResource, aPathInfo, rrResource, rrPathInfo, nResource, nPathInfo;
1068 
1069 		public Results(String aResource, String aPathInfo, String rrResource, String rrPathInfo, String nResource, String nPathInfo) {
1070 			this.aResource = aResource;
1071 			this.aPathInfo = aPathInfo;
1072 			this.rrResource = rrResource;
1073 			this.rrPathInfo = rrPathInfo;
1074 			this.nResource = nResource;
1075 			this.nPathInfo = nPathInfo;
1076 		}
1077 	}
1078 
1079 	public static Tester tester(int index, String label, Input input, Results results) {
1080 		return new Tester(index, label, input, results);
1081 	}
1082 
1083 	public static Input input(String authority, String context, String resource, String path, String uri) {
1084 		return new Input(authority, context, resource, path, uri);
1085 	}
1086 
1087 	public static Results results(String eAbsResource, String eAbsPathInfo, String eRrResource, String eRrPathInfo, String eNoneResource, String eNonePathInfo) {
1088 		return new Results(eAbsResource, eAbsPathInfo, eRrResource, eRrPathInfo, eNoneResource, eNonePathInfo);
1089 	}
1090 
1091 	static Tester[] testers() {
1092 		return TESTERS;
1093 	}
1094 
1095 	@ParameterizedTest
1096 	@MethodSource("testers")
1097 	void a01_testAbsoluteResource(Tester t) {
1098 		var x = UriResolver.of(ABSOLUTE, RESOURCE, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).resolve(t.input.uri);
1099 		assertEquals(t.results.aResource, x, fs("{0}: testAbsolute() failed", t.label));
1100 	}
1101 
1102 	@ParameterizedTest
1103 	@MethodSource("testers")
1104 	void a02_testAppendAbsoluteResource(Tester t) {
1105 		var x = UriResolver.of(ABSOLUTE, RESOURCE, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).append(new StringBuilder(), t.input.uri);
1106 		assertString(t.results.aResource, x);
1107 	}
1108 
1109 	@ParameterizedTest
1110 	@MethodSource("testers")
1111 	void a03_testAbsolutePathInfo(Tester t) {
1112 		var x = UriResolver.of(ABSOLUTE, PATH_INFO, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).resolve(t.input.uri);
1113 		assertEquals(t.results.aPathInfo, x);
1114 	}
1115 
1116 	@ParameterizedTest
1117 	@MethodSource("testers")
1118 	void a04_testAppendAbsolutePathInfo(Tester t) {
1119 		var x = UriResolver.of(ABSOLUTE, PATH_INFO, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).append(new StringBuilder(), t.input.uri);
1120 		assertString(t.results.aPathInfo, x);
1121 	}
1122 
1123 	@ParameterizedTest
1124 	@MethodSource("testers")
1125 	void a05_testRootRelativeResource(Tester t) {
1126 		var x = UriResolver.of(ROOT_RELATIVE, RESOURCE, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).resolve(t.input.uri);
1127 		assertEquals(t.results.rrResource, x);
1128 	}
1129 
1130 	@ParameterizedTest
1131 	@MethodSource("testers")
1132 	void a06_testAppendRootRelativeResource(Tester t) {
1133 		var x = UriResolver.of(ROOT_RELATIVE, RESOURCE, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).append(new StringBuilder(), t.input.uri);
1134 		assertString(t.results.rrResource, x);
1135 	}
1136 
1137 	@ParameterizedTest
1138 	@MethodSource("testers")
1139 	void a07_testRootRelativePathInfo(Tester t) {
1140 		var x = UriResolver.of(ROOT_RELATIVE, PATH_INFO, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).resolve(t.input.uri);
1141 		assertEquals(t.results.rrPathInfo, x);
1142 	}
1143 
1144 	@ParameterizedTest
1145 	@MethodSource("testers")
1146 	void a08_testAppendRootRelativePathInfo(Tester t) {
1147 		var x = UriResolver.of(ROOT_RELATIVE, PATH_INFO, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).append(new StringBuilder(), t.input.uri);
1148 		assertString(t.results.rrPathInfo, x);
1149 	}
1150 
1151 	@ParameterizedTest
1152 	@MethodSource("testers")
1153 	void a09_testNoneResource(Tester t) {
1154 		var x = UriResolver.of(NONE, RESOURCE, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).resolve(t.input.uri);
1155 		assertEquals(t.results.nResource, x);
1156 	}
1157 
1158 	@ParameterizedTest
1159 	@MethodSource("testers")
1160 	void a10_testAppendNoneResource(Tester t) {
1161 		var x = UriResolver.of(NONE, RESOURCE, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).append(new StringBuilder(), t.input.uri);
1162 		assertString(t.results.nResource, x);
1163 	}
1164 
1165 	@ParameterizedTest
1166 	@MethodSource("testers")
1167 	void a11_testNonePathInfo(Tester t) {
1168 		var x = UriResolver.of(NONE, PATH_INFO, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).resolve(t.input.uri);
1169 		assertEquals(t.results.nPathInfo, x);
1170 	}
1171 
1172 	@ParameterizedTest
1173 	@MethodSource("testers")
1174 	void a12_testAppendNonePathInfo(Tester t) {
1175 		var x = UriResolver.of(NONE, PATH_INFO, UriContext.of(t.input.authority, t.input.context, t.input.resource, t.input.path)).append(new StringBuilder(), t.input.uri);
1176 		assertString(t.results.nPathInfo, x);
1177 	}
1178 }