Completed
Pull Request — master (#178)
by ignace nyamagana
03:19
created

UriStringTest::testParseSucced()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
/**
4
 * League.Uri (https://uri.thephpleague.com)
5
 *
6
 * (c) Ignace Nyamagana Butera <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace LeagueTest\Uri;
13
14
use League\Uri\Exceptions\SyntaxError;
15
use League\Uri\UriString;
16
use PHPUnit\Framework\TestCase;
17
use TypeError;
18
19
class UriStringTest extends TestCase
20
{
21
    public function testParserFailedWithWrongArgumentType(): void
22
    {
23
        self::expectException(TypeError::class);
24
        UriString::parse(['scheme://user:pass@host:81/path?query#fragment']);
25
    }
26
27
    /**
28
     * @dataProvider validUriProvider
29
     *
30
     * @param mixed $uri a scalar or an object
31
     */
32
    public function testParseSucced($uri, array $expected): void
33
    {
34
        self::assertSame($expected, UriString::parse($uri));
35
    }
36
37
    public function validUriProvider(): array
38
    {
39
        return [
40
            'scheme with non-leading digit' => [
41
                's3://somebucket/somefile.txt',
42
                [
43
                    'scheme' => 's3',
44
                    'user' => null,
45
                    'pass' => null,
46
                    'host' => 'somebucket',
47
                    'port' => null,
48
                    'path' => '/somefile.txt',
49
                    'query' => null,
50
                    'fragment' => null,
51
                ],
52
            ],
53
            'uri with host ascii version' => [
54
                'scheme://user:[email protected]',
55
                [
56
                    'scheme' => 'scheme',
57
                    'user' => 'user',
58
                    'pass' => 'pass',
59
                    'host' => 'xn--mgbh0fb.xn--kgbechtv',
60
                    'port' => null,
61
                    'path' => '',
62
                    'query' => null,
63
                    'fragment' => null,
64
                ],
65
            ],
66
            'complete URI' => [
67
                'scheme://user:pass@host:81/path?query#fragment',
68
                [
69
                    'scheme' => 'scheme',
70
                    'user' => 'user',
71
                    'pass' => 'pass',
72
                    'host' => 'host',
73
                    'port' => 81,
74
                    'path' => '/path',
75
                    'query' => 'query',
76
                    'fragment' => 'fragment',
77
                ],
78
            ],
79
            'URI is not normalized' => [
80
                'ScheMe://user:pass@HoSt:81/path?query#fragment',
81
                [
82
                    'scheme' => 'ScheMe',
83
                    'user' => 'user',
84
                    'pass' => 'pass',
85
                    'host' => 'HoSt',
86
                    'port' => 81,
87
                    'path' => '/path',
88
                    'query' => 'query',
89
                    'fragment' => 'fragment',
90
                ],
91
            ],
92
            'URI without scheme' => [
93
                '//user:pass@HoSt:81/path?query#fragment',
94
                [
95
                    'scheme' => null,
96
                    'user' => 'user',
97
                    'pass' => 'pass',
98
                    'host' => 'HoSt',
99
                    'port' => 81,
100
                    'path' => '/path',
101
                    'query' => 'query',
102
                    'fragment' => 'fragment',
103
                ],
104
            ],
105
            'URI without empty authority only' => [
106
                '//',
107
                [
108
                    'scheme' => null,
109
                    'user' => null,
110
                    'pass' => null,
111
                    'host' => '',
112
                    'port' => null,
113
                    'path' => '',
114
                    'query' => null,
115
                    'fragment' => null,
116
                ],
117
            ],
118
            'URI without userinfo' => [
119
                'scheme://HoSt:81/path?query#fragment',
120
                [
121
                    'scheme' => 'scheme',
122
                    'user' => null,
123
                    'pass' => null,
124
                    'host' => 'HoSt',
125
                    'port' => 81,
126
                    'path' => '/path',
127
                    'query' => 'query',
128
                    'fragment' => 'fragment',
129
                ],
130
            ],
131
            'URI with empty userinfo' => [
132
                'scheme://@HoSt:81/path?query#fragment',
133
                [
134
                    'scheme' => 'scheme',
135
                    'user' => '',
136
                    'pass' => null,
137
                    'host' => 'HoSt',
138
                    'port' => 81,
139
                    'path' => '/path',
140
                    'query' => 'query',
141
                    'fragment' => 'fragment',
142
                ],
143
            ],
144
            'URI without port' => [
145
                'scheme://user:pass@host/path?query#fragment',
146
                [
147
                    'scheme' => 'scheme',
148
                    'user' => 'user',
149
                    'pass' => 'pass',
150
                    'host' => 'host',
151
                    'port' => null,
152
                    'path' => '/path',
153
                    'query' => 'query',
154
                    'fragment' => 'fragment',
155
                ],
156
            ],
157
            'URI with an empty port' => [
158
                'scheme://user:pass@host:/path?query#fragment',
159
                [
160
                    'scheme' => 'scheme',
161
                    'user' => 'user',
162
                    'pass' => 'pass',
163
                    'host' => 'host',
164
                    'port' => null,
165
                    'path' => '/path',
166
                    'query' => 'query',
167
                    'fragment' => 'fragment',
168
                ],
169
            ],
170
            'URI without user info and port' => [
171
                'scheme://host/path?query#fragment',
172
                [
173
                    'scheme' => 'scheme',
174
                    'user' => null,
175
                    'pass' => null,
176
                    'host' => 'host',
177
                    'port' => null,
178
                    'path' => '/path',
179
                    'query' => 'query',
180
                    'fragment' => 'fragment',
181
                ],
182
            ],
183
            'URI with host IP' => [
184
                'scheme://10.0.0.2/p?q#f',
185
                [
186
                    'scheme' => 'scheme',
187
                    'user' => null,
188
                    'pass' => null,
189
                    'host' => '10.0.0.2',
190
                    'port' => null,
191
                    'path' => '/p',
192
                    'query' => 'q',
193
                    'fragment' => 'f',
194
                ],
195
            ],
196
            'URI with scoped IP' => [
197
                'scheme://[fe80:1234::%251]/p?q#f',
198
                [
199
                    'scheme' => 'scheme',
200
                    'user' => null,
201
                    'pass' => null,
202
                    'host' => '[fe80:1234::%251]',
203
                    'port' => null,
204
                    'path' => '/p',
205
                    'query' => 'q',
206
                    'fragment' => 'f',
207
                ],
208
            ],
209
            'URI with IP future' => [
210
                'scheme://[vAF.1::2::3]/p?q#f',
211
                [
212
                    'scheme' => 'scheme',
213
                    'user' => null,
214
                    'pass' => null,
215
                    'host' => '[vAF.1::2::3]',
216
                    'port' => null,
217
                    'path' => '/p',
218
                    'query' => 'q',
219
                    'fragment' => 'f',
220
                ],
221
            ],
222
            'URI without authority' => [
223
                'scheme:path?query#fragment',
224
                [
225
                    'scheme' => 'scheme',
226
                    'user' => null,
227
                    'pass' => null,
228
                    'host' => null,
229
                    'port' => null,
230
                    'path' => 'path',
231
                    'query' => 'query',
232
                    'fragment' => 'fragment',
233
                ],
234
            ],
235
            'URI without authority and scheme' => [
236
                '/path',
237
                [
238
                    'scheme' => null,
239
                    'user' => null,
240
                    'pass' => null,
241
                    'host' => null,
242
                    'port' => null,
243
                    'path' => '/path',
244
                    'query' => null,
245
                    'fragment' => null,
246
                ],
247
            ],
248
            'URI with empty host' => [
249
                'scheme:///path?query#fragment',
250
                [
251
                    'scheme' => 'scheme',
252
                    'user' => null,
253
                    'pass' => null,
254
                    'host' => '',
255
                    'port' => null,
256
                    'path' => '/path',
257
                    'query' => 'query',
258
                    'fragment' => 'fragment',
259
                ],
260
            ],
261
            'URI with empty host and without scheme' => [
262
                '///path?query#fragment',
263
                [
264
                    'scheme' => null,
265
                    'user' => null,
266
                    'pass' => null,
267
                    'host' => '',
268
                    'port' => null,
269
                    'path' => '/path',
270
                    'query' => 'query',
271
                    'fragment' => 'fragment',
272
                ],
273
            ],
274
            'URI without path' => [
275
                'scheme://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]?query#fragment',
276
                [
277
                    'scheme' => 'scheme',
278
                    'user' => null,
279
                    'pass' => null,
280
                    'host' => '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]',
281
                    'port' => null,
282
                    'path' => '',
283
                    'query' => 'query',
284
                    'fragment' => 'fragment',
285
                ],
286
            ],
287
            'URI without path and scheme' => [
288
                '//[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]?query#fragment',
289
                [
290
                    'scheme' => null,
291
                    'user' => null,
292
                    'pass' => null,
293
                    'host' => '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]',
294
                    'port' => null,
295
                    'path' => '',
296
                    'query' => 'query',
297
                    'fragment' => 'fragment',
298
                ],
299
            ],
300
            'URI without scheme with IPv6 host and port' => [
301
                '//[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:42?query#fragment',
302
                [
303
                    'scheme' => null,
304
                    'user' => null,
305
                    'pass' => null,
306
                    'host' => '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]',
307
                    'port' => 42,
308
                    'path' => '',
309
                    'query' => 'query',
310
                    'fragment' => 'fragment',
311
                ],
312
            ],
313
            'complete URI without scheme' => [
314
                '//user@[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:42?q#f',
315
                [
316
                    'scheme' => null,
317
                    'user' => 'user',
318
                    'pass' => null,
319
                    'host' => '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]',
320
                    'port' => 42,
321
                    'path' => '',
322
                    'query' => 'q',
323
                    'fragment' => 'f',
324
                ],
325
            ],
326
            'URI without authority and query' => [
327
                'scheme:path#fragment',
328
                [
329
                    'scheme' => 'scheme',
330
                    'user' => null,
331
                    'pass' => null,
332
                    'host' => null,
333
                    'port' => null,
334
                    'path' => 'path',
335
                    'query' => null,
336
                    'fragment' => 'fragment',
337
                ],
338
            ],
339
            'URI with empty query' => [
340
                'scheme:path?#fragment',
341
                [
342
                    'scheme' => 'scheme',
343
                    'user' => null,
344
                    'pass' => null,
345
                    'host' => null,
346
                    'port' => null,
347
                    'path' => 'path',
348
                    'query' => '',
349
                    'fragment' => 'fragment',
350
                ],
351
            ],
352
            'URI with query only' => [
353
                '?query',
354
                [
355
                    'scheme' => null,
356
                    'user' => null,
357
                    'pass' => null,
358
                    'host' => null,
359
                    'port' => null,
360
                    'path' => '',
361
                    'query' => 'query',
362
                    'fragment' => null,
363
                ],
364
            ],
365
            'URI without fragment' => [
366
                'tel:05000',
367
                [
368
                    'scheme' => 'tel',
369
                    'user' => null,
370
                    'pass' => null,
371
                    'host' => null,
372
                    'port' => null,
373
                    'path' => '05000',
374
                    'query' => null,
375
                    'fragment' => null,
376
                ],
377
            ],
378
            'URI with empty fragment' => [
379
                'scheme:path#',
380
                [
381
                    'scheme' => 'scheme',
382
                    'user' => null,
383
                    'pass' => null,
384
                    'host' => null,
385
                    'port' => null,
386
                    'path' => 'path',
387
                    'query' => null,
388
                    'fragment' => '',
389
                ],
390
            ],
391
            'URI with fragment only' => [
392
                '#fragment',
393
                [
394
                    'scheme' => null,
395
                    'user' => null,
396
                    'pass' => null,
397
                    'host' => null,
398
                    'port' => null,
399
                    'path' => '',
400
                    'query' => null,
401
                    'fragment' => 'fragment',
402
                ],
403
            ],
404
            'URI with empty fragment only' => [
405
                '#',
406
                [
407
                    'scheme' => null,
408
                    'user' => null,
409
                    'pass' => null,
410
                    'host' => null,
411
                    'port' => null,
412
                    'path' => '',
413
                    'query' => null,
414
                    'fragment' => '',
415
                ],
416
            ],
417
            'URI without authority 2' => [
418
                'path#fragment',
419
                [
420
                    'scheme' => null,
421
                    'user' => null,
422
                    'pass' => null,
423
                    'host' => null,
424
                    'port' => null,
425
                    'path' => 'path',
426
                    'query' => null,
427
                    'fragment' => 'fragment',
428
                ],
429
            ],
430
            'URI with empty query and fragment' => [
431
                '?#',
432
                [
433
                    'scheme' => null,
434
                    'user' => null,
435
                    'pass' => null,
436
                    'host' => null,
437
                    'port' => null,
438
                    'path' => '',
439
                    'query' => '',
440
                    'fragment' => '',
441
                ],
442
            ],
443
            'URI with absolute path' => [
444
                '/?#',
445
                [
446
                    'scheme' => null,
447
                    'user' => null,
448
                    'pass' => null,
449
                    'host' => null,
450
                    'port' => null,
451
                    'path' => '/',
452
                    'query' => '',
453
                    'fragment' => '',
454
                ],
455
            ],
456
            'URI with absolute authority' => [
457
                'https://thephpleague.com./p?#f',
458
                [
459
                    'scheme' => 'https',
460
                    'user' => null,
461
                    'pass' => null,
462
                    'host' => 'thephpleague.com.',
463
                    'port' => null,
464
                    'path' => '/p',
465
                    'query' => '',
466
                    'fragment' => 'f',
467
                ],
468
            ],
469
            'URI with absolute path only' => [
470
                '/',
471
                [
472
                    'scheme' => null,
473
                    'user' => null,
474
                    'pass' => null,
475
                    'host' => null,
476
                    'port' => null,
477
                    'path' => '/',
478
                    'query' => null,
479
                    'fragment' => null,
480
                ],
481
            ],
482
            'URI with empty query only' => [
483
                '?',
484
                [
485
                    'scheme' => null,
486
                    'user' => null,
487
                    'pass' => null,
488
                    'host' => null,
489
                    'port' => null,
490
                    'path' => '',
491
                    'query' => '',
492
                    'fragment' => null,
493
                ],
494
            ],
495
            'relative path' => [
496
                '../relative/path',
497
                [
498
                    'scheme' => null,
499
                    'user' => null,
500
                    'pass' => null,
501
                    'host' => null,
502
                    'port' => null,
503
                    'path' => '../relative/path',
504
                    'query' => null,
505
                    'fragment' => null,
506
                ],
507
            ],
508
            'complex authority' => [
509
                'http://a_.!~*\'(-)n0123Di%25%26:pass;:&=+$,[email protected]',
510
                [
511
                    'scheme' => 'http',
512
                    'user' => 'a_.!~*\'(-)n0123Di%25%26',
513
                    'pass' => 'pass;:&=+$,word',
514
                    'host' => 'www.zend.com',
515
                    'port' => null,
516
                    'path' => '',
517
                    'query' => null,
518
                    'fragment' => null,
519
                ],
520
            ],
521
            'complex authority without scheme' => [
522
                '//a_.!~*\'(-)n0123Di%25%26:pass;:&=+$,[email protected]',
523
                [
524
                    'scheme' => null,
525
                    'user' => 'a_.!~*\'(-)n0123Di%25%26',
526
                    'pass' => 'pass;:&=+$,word',
527
                    'host' => 'www.zend.com',
528
                    'port' => null,
529
                    'path' => '',
530
                    'query' => null,
531
                    'fragment' => null,
532
                ],
533
            ],
534
            'single word is a path' => [
535
                'http',
536
                [
537
                    'scheme' => null,
538
                    'user' => null,
539
                    'pass' => null,
540
                    'host' => null,
541
                    'port' => null,
542
                    'path' => 'http',
543
                    'query' => null,
544
                    'fragment' => null,
545
                ],
546
            ],
547
            'URI scheme with an empty authority' => [
548
                'http://',
549
                [
550
                    'scheme' => 'http',
551
                    'user' => null,
552
                    'pass' => null,
553
                    'host' => '',
554
                    'port' => null,
555
                    'path' => '',
556
                    'query' => null,
557
                    'fragment' => null,
558
                ],
559
            ],
560
            'single word is a path, no' => [
561
                'http:::/path',
562
                [
563
                    'scheme' => 'http',
564
                    'user' => null,
565
                    'pass' => null,
566
                    'host' => null,
567
                    'port' => null,
568
                    'path' => '::/path',
569
                    'query' => null,
570
                    'fragment' => null,
571
                ],
572
            ],
573
            'fragment with pseudo segment' => [
574
                'http://example.com#foo=1/bar=2',
575
                [
576
                    'scheme' => 'http',
577
                    'user' => null,
578
                    'pass' => null,
579
                    'host' => 'example.com',
580
                    'port' => null,
581
                    'path' => '',
582
                    'query' => null,
583
                    'fragment' => 'foo=1/bar=2',
584
                ],
585
            ],
586
            'empty string' => [
587
                '',
588
                [
589
                    'scheme' => null,
590
                    'user' => null,
591
                    'pass' => null,
592
                    'host' => null,
593
                    'port' => null,
594
                    'path' => '',
595
                    'query' => null,
596
                    'fragment' => null,
597
                ],
598
            ],
599
            'complex URI' => [
600
                'htà+d/s:totot',
601
                [
602
                    'scheme' => null,
603
                    'user' => null,
604
                    'pass' => null,
605
                    'host' => null,
606
                    'port' => null,
607
                    'path' => 'htà+d/s:totot',
608
                    'query' => null,
609
                    'fragment' => null,
610
                ],
611
            ],
612
            'scheme only URI' => [
613
                'http:',
614
                [
615
                    'scheme' => 'http',
616
                    'user' => null,
617
                    'pass' => null,
618
                    'host' => null,
619
                    'port' => null,
620
                    'path' => '',
621
                    'query' => null,
622
                    'fragment' => null,
623
                ],
624
            ],
625
            'RFC3986 LDAP example' => [
626
                'ldap://[2001:db8::7]/c=GB?objectClass?one',
627
                [
628
                    'scheme' => 'ldap',
629
                    'user' => null,
630
                    'pass' => null,
631
                    'host' => '[2001:db8::7]',
632
                    'port' => null,
633
                    'path' => '/c=GB',
634
                    'query' => 'objectClass?one',
635
                    'fragment' => null,
636
                ],
637
            ],
638
            'RFC3987 example' => [
639
                'http://bébé.bé./有词法别名.zh',
640
                [
641
                    'scheme' => 'http',
642
                    'user' => null,
643
                    'pass' => null,
644
                    'host' => 'bébé.bé.',
645
                    'port' => null,
646
                    'path' => '/有词法别名.zh',
647
                    'query' => null,
648
                    'fragment' => null,
649
                ],
650
            ],
651
            'colon detection respect RFC3986 (1)' => [
652
                'http://example.org/hello:12?foo=bar#test',
653
                [
654
                    'scheme' => 'http',
655
                    'user' => null,
656
                    'pass' => null,
657
                    'host' => 'example.org',
658
                    'port' => null,
659
                    'path' => '/hello:12',
660
                    'query' => 'foo=bar',
661
                    'fragment' => 'test',
662
                ],
663
            ],
664
            'colon detection respect RFC3986 (2)' => [
665
                '/path/to/colon:34',
666
                [
667
                    'scheme' => null,
668
                    'user' => null,
669
                    'pass' => null,
670
                    'host' => null,
671
                    'port' => null,
672
                    'path' => '/path/to/colon:34',
673
                    'query' => null,
674
                    'fragment' => null,
675
                ],
676
            ],
677
            'scheme with hyphen' => [
678
                'android-app://org.wikipedia/http/en.m.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy',
679
                [
680
                    'scheme' => 'android-app',
681
                    'user' => null,
682
                    'pass' => null,
683
                    'host' => 'org.wikipedia',
684
                    'port' => null,
685
                    'path' => '/http/en.m.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy',
686
                    'query' => null,
687
                    'fragment' => null,
688
                ],
689
            ],
690
            'URI is a scalar value' => [
691
                1234,
692
                [
693
                    'scheme' => null,
694
                    'user' => null,
695
                    'pass' => null,
696
                    'host' => null,
697
                    'port' => null,
698
                    'path' => '1234',
699
                    'query' => null,
700
                    'fragment' => null,
701
                ],
702
            ],
703
            'URI is a object with __toString' => [
704
                new class() {
705
                    public function __toString()
706
                    {
707
                        return 'http://example.org/hello:12?foo=bar#test';
708
                    }
709
                },
710
                [
711
                    'scheme' => 'http',
712
                    'user' => null,
713
                    'pass' => null,
714
                    'host' => 'example.org',
715
                    'port' => null,
716
                    'path' => '/hello:12',
717
                    'query' => 'foo=bar',
718
                    'fragment' => 'test',
719
                ],
720
            ],
721
            'Authority is the colon' => [
722
                'ftp://:/p?q#f',
723
                [
724
                    'scheme' => 'ftp',
725
                    'user' => null,
726
                    'pass' => null,
727
                    'host' => '',
728
                    'port' => null,
729
                    'path' => '/p',
730
                    'query' => 'q',
731
                    'fragment' => 'f',
732
                ],
733
            ],
734
            'URI with 0 leading port' => [
735
                'scheme://user:pass@host:000000000081/path?query#fragment',
736
                [
737
                    'scheme' => 'scheme',
738
                    'user' => 'user',
739
                    'pass' => 'pass',
740
                    'host' => 'host',
741
                    'port' => 81,
742
                    'path' => '/path',
743
                    'query' => 'query',
744
                    'fragment' => 'fragment',
745
                ],
746
            ],
747
        ];
748
    }
749
750
    /**
751
     * @dataProvider invalidUriProvider
752
     */
753
    public function testParseFailed(string $uri): void
754
    {
755
        self::expectException(SyntaxError::class);
756
        UriString::parse($uri);
757
    }
758
759
    public function invalidUriProvider(): array
760
    {
761
        return [
762
            'invalid scheme' => ['0scheme://host/path?query#fragment'],
763
            'invalid path' => ['://host:80/p?q#f'],
764
            'invalid port (1)' => ['//host:port/path?query#fragment'],
765
            'invalid port (2)' => ['//host:-892358/path?query#fragment'],
766
            'invalid host' => ['http://exam ple.com'],
767
            'invalid ipv6 host (1)' => ['scheme://[127.0.0.1]/path?query#fragment'],
768
            'invalid ipv6 host (2)' => ['scheme://]::1[/path?query#fragment'],
769
            'invalid ipv6 host (3)' => ['scheme://[::1|/path?query#fragment'],
770
            'invalid ipv6 host (4)' => ['scheme://|::1]/path?query#fragment'],
771
            'invalid ipv6 host (5)' => ['scheme://[::1]./path?query#fragment'],
772
            'invalid ipv6 host (6)' => ['scheme://[[::1]]:80/path?query#fragment'],
773
            'invalid ipv6 scoped (1)' => ['scheme://[::1%25%23]/path?query#fragment'],
774
            'invalid ipv6 scoped (2)' => ['scheme://[fe80::1234::%251]/path?query#fragment'],
775
            'invalid char on URI' => ["scheme://host/path/\r\n/toto"],
776
            'invalid path only URI' => ['2620:0:1cfe:face:b00c::3'],
777
            'invalid path PHP bug #72811' => ['[::1]:80'],
778
            'invalid ipvfuture' => ['//[v6.::1]/p?q#f'],
779
            'invalid RFC3987 host' => ['//a⒈com/p?q#f'],
780
            'invalid RFC3987 host URL encoded' => ['//'.\rawurlencode('a⒈com').'/p?q#f'],
781
            'invalid Host with fullwith (1)' =>  ['http://%00.com'],
782
            'invalid host with fullwidth escaped' =>  ['http://%ef%bc%85%ef%bc%94%ef%bc%91.com],'],
783
            'invalid pseudo IDN to ASCII string' => ['http://xn--3/foo.'],
784
            'invalid IDN' => ['//:�@�����������������������������������������������������������������������������������������/'],
785
        ];
786
    }
787
788
    /**
789
     * @dataProvider buildUriProvider
790
     */
791
    public function testBuild(string $uri, string $expected): void
792
    {
793
        self::assertSame($expected, UriString::build(UriString::parse($uri)));
794
    }
795
796
    public function buildUriProvider(): array
797
    {
798
        return [
799
            'complete URI' => [
800
                'scheme://user:pass@host:81/path?query#fragment',
801
                'scheme://user:pass@host:81/path?query#fragment',
802
            ],
803
            'URI is not normalized' => [
804
                'ScheMe://user:pass@HoSt:81/path?query#fragment',
805
                'ScheMe://user:pass@HoSt:81/path?query#fragment',
806
            ],
807
            'URI without scheme' => [
808
                '//user:pass@HoSt:81/path?query#fragment',
809
                '//user:pass@HoSt:81/path?query#fragment',
810
            ],
811
            'URI without empty authority only' => [
812
                '//',
813
                '//',
814
            ],
815
            'URI without userinfo' => [
816
                'scheme://HoSt:81/path?query#fragment',
817
                'scheme://HoSt:81/path?query#fragment',
818
            ],
819
            'URI with empty userinfo' => [
820
                'scheme://@HoSt:81/path?query#fragment',
821
                'scheme://@HoSt:81/path?query#fragment',
822
            ],
823
            'URI without port' => [
824
                'scheme://user:pass@host/path?query#fragment',
825
                'scheme://user:pass@host/path?query#fragment',
826
            ],
827
            'URI with an empty port' => [
828
                'scheme://user:pass@host:/path?query#fragment',
829
                'scheme://user:pass@host/path?query#fragment',
830
            ],
831
            'URI without user info and port' => [
832
                'scheme://host/path?query#fragment',
833
                'scheme://host/path?query#fragment',
834
            ],
835
            'URI with host IP' => [
836
                'scheme://10.0.0.2/p?q#f',
837
                'scheme://10.0.0.2/p?q#f',
838
            ],
839
            'URI with scoped IP' => [
840
                'scheme://[fe80:1234::%251]/p?q#f',
841
                'scheme://[fe80:1234::%251]/p?q#f',
842
            ],
843
            'URI without authority' => [
844
                'scheme:path?query#fragment',
845
                'scheme:path?query#fragment',
846
            ],
847
            'URI without authority and scheme' => [
848
                '/path',
849
                '/path',
850
            ],
851
            'URI with empty host' => [
852
                'scheme:///path?query#fragment',
853
                'scheme:///path?query#fragment',
854
            ],
855
            'URI with empty host and without scheme' => [
856
                '///path?query#fragment',
857
                '///path?query#fragment',
858
            ],
859
            'URI without path' => [
860
                'scheme://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]?query#fragment',
861
                'scheme://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]?query#fragment',
862
            ],
863
            'URI without path and scheme' => [
864
                '//[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]?query#fragment',
865
                '//[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]?query#fragment',
866
            ],
867
            'URI without scheme with IPv6 host and port' => [
868
                '//[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:42?query#fragment',
869
                '//[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:42?query#fragment',
870
            ],
871
            'complete URI without scheme' => [
872
                '//user@[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:42?q#f',
873
                '//user@[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:42?q#f',
874
            ],
875
            'URI without authority and query' => [
876
                'scheme:path#fragment',
877
                'scheme:path#fragment',
878
            ],
879
            'URI with empty query' => [
880
                'scheme:path?#fragment',
881
                'scheme:path?#fragment',
882
            ],
883
            'URI with query only' => [
884
                '?query',
885
                '?query',
886
            ],
887
            'URI without fragment' => [
888
                'tel:05000',
889
                'tel:05000',
890
            ],
891
            'URI with empty fragment' => [
892
                'scheme:path#',
893
                'scheme:path#',
894
            ],
895
            'URI with fragment only' => [
896
                '#fragment',
897
                '#fragment',
898
            ],
899
            'URI with empty fragment only' => [
900
                '#',
901
                '#',
902
            ],
903
            'URI without authority 2' => [
904
                'path#fragment',
905
                'path#fragment',
906
            ],
907
            'URI with empty query and fragment' => [
908
                '?#',
909
                '?#',
910
            ],
911
            'URI with absolute path' => [
912
                '/?#',
913
                '/?#',
914
            ],
915
            'URI with absolute authority' => [
916
                'https://thephpleague.com./p?#f',
917
                'https://thephpleague.com./p?#f',
918
            ],
919
            'URI with absolute path only' => [
920
                '/',
921
                '/',
922
            ],
923
            'URI with empty query only' => [
924
                '?',
925
                '?',
926
            ],
927
            'relative path' => [
928
                '../relative/path',
929
                '../relative/path',
930
            ],
931
            'complex authority' => [
932
                'http://a_.!~*\'(-)n0123Di%25%26:pass;:&=+$,[email protected]',
933
                'http://a_.!~*\'(-)n0123Di%25%26:pass;:&=+$,[email protected]',
934
            ],
935
            'complex authority without scheme' => [
936
                '//a_.!~*\'(-)n0123Di%25%26:pass;:&=+$,[email protected]',
937
                '//a_.!~*\'(-)n0123Di%25%26:pass;:&=+$,[email protected]',
938
            ],
939
            'single word is a path' => [
940
                'http',
941
                'http',
942
            ],
943
            'URI scheme with an empty authority' => [
944
                'http://',
945
                'http://',
946
            ],
947
            'single word is a path, no' => [
948
                'http:::/path',
949
                'http:::/path',
950
            ],
951
            'fragment with pseudo segment' => [
952
                'http://example.com#foo=1/bar=2',
953
                'http://example.com#foo=1/bar=2',
954
            ],
955
            'empty string' => [
956
                '',
957
                '',
958
            ],
959
            'complex URI' => [
960
                'htà+d/s:totot',
961
                'htà+d/s:totot',
962
            ],
963
            'scheme only URI' => [
964
                'http:',
965
                'http:',
966
            ],
967
            'RFC3986 LDAP example' => [
968
                'ldap://[2001:db8::7]/c=GB?objectClass?one',
969
                'ldap://[2001:db8::7]/c=GB?objectClass?one',
970
            ],
971
            'RFC3987 example' => [
972
                'http://bébé.bé./有词法别名.zh',
973
                'http://bébé.bé./有词法别名.zh',
974
            ],
975
            'colon detection respect RFC3986 (1)' => [
976
                'http://example.org/hello:12?foo=bar#test',
977
                'http://example.org/hello:12?foo=bar#test',
978
            ],
979
            'colon detection respect RFC3986 (2)' => [
980
                '/path/to/colon:34',
981
                '/path/to/colon:34',
982
            ],
983
            'scheme with hyphen' => [
984
                'android-app://org.wikipedia/http/en.m.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy',
985
                'android-app://org.wikipedia/http/en.m.wikipedia.org/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy',
986
            ],
987
        ];
988
    }
989
}
990