PathTest::provideCanonicalizationTests()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 122
Code Lines 99

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 99
nc 1
nop 0
dl 0
loc 122
rs 8.0218
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the webmozart/path-util package.
5
 *
6
 * (c) Bernhard Schussek <[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 DaveLiddament\StaticAnalysisResultsBaseliner\Tests\Unit\Core\Utils;
13
14
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Common\InvalidPathException;
15
use DaveLiddament\StaticAnalysisResultsBaseliner\Domain\Utils\Path;
16
use PHPUnit\Framework\TestCase;
17
18
/**
19
 * @author Bernhard Schussek <[email protected]>
20
 * @author Thomas Schulz <[email protected]>
21
 */
22
final class PathTest extends TestCase
23
{
24
    /** @var array<string,string> */
25
    protected $storedEnv = [];
26
27
    protected function setUp(): void
28
    {
29
        $this->storedEnv['HOME'] = $this->getEnv('HOME');
30
        $this->storedEnv['HOMEDRIVE'] = $this->getEnv('HOMEDRIVE');
31
        $this->storedEnv['HOMEPATH'] = $this->getEnv('HOMEPATH');
32
33
        putenv('HOME=/home/webmozart');
34
        putenv('HOMEDRIVE=');
35
        putenv('HOMEPATH=');
36
    }
37
38
    private function getEnv(string $key): string
39
    {
40
        $value = getenv($key);
41
        if (false === $value) {
42
            return '';
43
        }
44
45
        return $value;
46
    }
47
48
    protected function tearDown(): void
49
    {
50
        putenv('HOME='.$this->storedEnv['HOME']);
51
        putenv('HOMEDRIVE='.$this->storedEnv['HOMEDRIVE']);
52
        putenv('HOMEPATH='.$this->storedEnv['HOMEPATH']);
53
    }
54
55
    /** @return array<int,array{string,string}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string,string}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
56
    public function provideCanonicalizationTests(): array
57
    {
58
        return [
59
            // relative paths (forward slash)
60
            ['css/./style.css', 'css/style.css'],
61
            ['css/../style.css', 'style.css'],
62
            ['css/./../style.css', 'style.css'],
63
            ['css/.././style.css', 'style.css'],
64
            ['css/../../style.css', '../style.css'],
65
            ['./css/style.css', 'css/style.css'],
66
            ['../css/style.css', '../css/style.css'],
67
            ['./../css/style.css', '../css/style.css'],
68
            ['.././css/style.css', '../css/style.css'],
69
            ['../../css/style.css', '../../css/style.css'],
70
            ['', ''],
71
            ['.', ''],
72
            ['..', '..'],
73
            ['./..', '..'],
74
            ['../.', '..'],
75
            ['../..', '../..'],
76
77
            // relative paths (backslash)
78
            ['css\\.\\style.css', 'css/style.css'],
79
            ['css\\..\\style.css', 'style.css'],
80
            ['css\\.\\..\\style.css', 'style.css'],
81
            ['css\\..\\.\\style.css', 'style.css'],
82
            ['css\\..\\..\\style.css', '../style.css'],
83
            ['.\\css\\style.css', 'css/style.css'],
84
            ['..\\css\\style.css', '../css/style.css'],
85
            ['.\\..\\css\\style.css', '../css/style.css'],
86
            ['..\\.\\css\\style.css', '../css/style.css'],
87
            ['..\\..\\css\\style.css', '../../css/style.css'],
88
89
            // absolute paths (forward slash, UNIX)
90
            ['/css/style.css', '/css/style.css'],
91
            ['/css/./style.css', '/css/style.css'],
92
            ['/css/../style.css', '/style.css'],
93
            ['/css/./../style.css', '/style.css'],
94
            ['/css/.././style.css', '/style.css'],
95
            ['/./css/style.css', '/css/style.css'],
96
            ['/../css/style.css', '/css/style.css'],
97
            ['/./../css/style.css', '/css/style.css'],
98
            ['/.././css/style.css', '/css/style.css'],
99
            ['/../../css/style.css', '/css/style.css'],
100
101
            // absolute paths (backslash, UNIX)
102
            ['\\css\\style.css', '/css/style.css'],
103
            ['\\css\\.\\style.css', '/css/style.css'],
104
            ['\\css\\..\\style.css', '/style.css'],
105
            ['\\css\\.\\..\\style.css', '/style.css'],
106
            ['\\css\\..\\.\\style.css', '/style.css'],
107
            ['\\.\\css\\style.css', '/css/style.css'],
108
            ['\\..\\css\\style.css', '/css/style.css'],
109
            ['\\.\\..\\css\\style.css', '/css/style.css'],
110
            ['\\..\\.\\css\\style.css', '/css/style.css'],
111
            ['\\..\\..\\css\\style.css', '/css/style.css'],
112
113
            // absolute paths (forward slash, Windows)
114
            ['C:/css/style.css', 'C:/css/style.css'],
115
            ['C:/css/./style.css', 'C:/css/style.css'],
116
            ['C:/css/../style.css', 'C:/style.css'],
117
            ['C:/css/./../style.css', 'C:/style.css'],
118
            ['C:/css/.././style.css', 'C:/style.css'],
119
            ['C:/./css/style.css', 'C:/css/style.css'],
120
            ['C:/../css/style.css', 'C:/css/style.css'],
121
            ['C:/./../css/style.css', 'C:/css/style.css'],
122
            ['C:/.././css/style.css', 'C:/css/style.css'],
123
            ['C:/../../css/style.css', 'C:/css/style.css'],
124
125
            // absolute paths (backslash, Windows)
126
            ['C:\\css\\style.css', 'C:/css/style.css'],
127
            ['C:\\css\\.\\style.css', 'C:/css/style.css'],
128
            ['C:\\css\\..\\style.css', 'C:/style.css'],
129
            ['C:\\css\\.\\..\\style.css', 'C:/style.css'],
130
            ['C:\\css\\..\\.\\style.css', 'C:/style.css'],
131
            ['C:\\.\\css\\style.css', 'C:/css/style.css'],
132
            ['C:\\..\\css\\style.css', 'C:/css/style.css'],
133
            ['C:\\.\\..\\css\\style.css', 'C:/css/style.css'],
134
            ['C:\\..\\.\\css\\style.css', 'C:/css/style.css'],
135
            ['C:\\..\\..\\css\\style.css', 'C:/css/style.css'],
136
137
            // Windows special case
138
            ['C:', 'C:/'],
139
140
            // Don't change malformed path
141
            ['C:css/style.css', 'C:css/style.css'],
142
143
            // absolute paths (stream, UNIX)
144
            ['phar:///css/style.css', 'phar:///css/style.css'],
145
            ['phar:///css/./style.css', 'phar:///css/style.css'],
146
            ['phar:///css/../style.css', 'phar:///style.css'],
147
            ['phar:///css/./../style.css', 'phar:///style.css'],
148
            ['phar:///css/.././style.css', 'phar:///style.css'],
149
            ['phar:///./css/style.css', 'phar:///css/style.css'],
150
            ['phar:///../css/style.css', 'phar:///css/style.css'],
151
            ['phar:///./../css/style.css', 'phar:///css/style.css'],
152
            ['phar:///.././css/style.css', 'phar:///css/style.css'],
153
            ['phar:///../../css/style.css', 'phar:///css/style.css'],
154
155
            // absolute paths (stream, Windows)
156
            ['phar://C:/css/style.css', 'phar://C:/css/style.css'],
157
            ['phar://C:/css/./style.css', 'phar://C:/css/style.css'],
158
            ['phar://C:/css/../style.css', 'phar://C:/style.css'],
159
            ['phar://C:/css/./../style.css', 'phar://C:/style.css'],
160
            ['phar://C:/css/.././style.css', 'phar://C:/style.css'],
161
            ['phar://C:/./css/style.css', 'phar://C:/css/style.css'],
162
            ['phar://C:/../css/style.css', 'phar://C:/css/style.css'],
163
            ['phar://C:/./../css/style.css', 'phar://C:/css/style.css'],
164
            ['phar://C:/.././css/style.css', 'phar://C:/css/style.css'],
165
            ['phar://C:/../../css/style.css', 'phar://C:/css/style.css'],
166
167
            // paths with "~" UNIX
168
            ['~/css/style.css', '/home/webmozart/css/style.css'],
169
            ['~/css/./style.css', '/home/webmozart/css/style.css'],
170
            ['~/css/../style.css', '/home/webmozart/style.css'],
171
            ['~/css/./../style.css', '/home/webmozart/style.css'],
172
            ['~/css/.././style.css', '/home/webmozart/style.css'],
173
            ['~/./css/style.css', '/home/webmozart/css/style.css'],
174
            ['~/../css/style.css', '/home/css/style.css'],
175
            ['~/./../css/style.css', '/home/css/style.css'],
176
            ['~/.././css/style.css', '/home/css/style.css'],
177
            ['~/../../css/style.css', '/css/style.css'],
178
        ];
179
    }
180
181
    /**
182
     * @dataProvider provideCanonicalizationTests
183
     */
184
    public function testCanonicalize(string $path, string $canonicalized): void
185
    {
186
        $this->assertSame($canonicalized, Path::canonicalize($path));
187
    }
188
189
    /** @return array<int,array{string,bool}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string,bool}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
190
    public function provideIsAbsolutePathTests(): array
191
    {
192
        return [
193
            ['/css/style.css', true],
194
            ['/', true],
195
            ['css/style.css', false],
196
            ['', false],
197
198
            ['\\css\\style.css', true],
199
            ['\\', true],
200
            ['css\\style.css', false],
201
202
            ['C:/css/style.css', true],
203
            ['D:/', true],
204
205
            ['E:\\css\\style.css', true],
206
            ['F:\\', true],
207
208
            ['phar:///css/style.css', true],
209
            ['phar:///', true],
210
211
            // Windows special case
212
            ['C:', true],
213
214
            // Not considered absolute
215
            ['C:css/style.css', false],
216
        ];
217
    }
218
219
    /**
220
     * @dataProvider provideIsAbsolutePathTests
221
     */
222
    public function testIsAbsolute(string $path, bool $isAbsolute): void
223
    {
224
        $this->assertSame($isAbsolute, Path::isAbsolute($path));
225
    }
226
227
    /** @return array<int,array{string,string,string}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string,string,string}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
228
    public function providePathTests(): array
229
    {
230
        return [
231
            // relative to absolute path
232
            ['css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'],
233
            ['../css/style.css', '/webmozart/puli', '/webmozart/css/style.css'],
234
            ['../../css/style.css', '/webmozart/puli', '/css/style.css'],
235
236
            // relative to root
237
            ['css/style.css', '/', '/css/style.css'],
238
            ['css/style.css', 'C:', 'C:/css/style.css'],
239
            ['css/style.css', 'C:/', 'C:/css/style.css'],
240
241
            // same sub directories in different base directories
242
            ['../../puli/css/style.css', '/webmozart/css', '/puli/css/style.css'],
243
244
            ['', '/webmozart/puli', '/webmozart/puli'],
245
            ['..', '/webmozart/puli', '/webmozart'],
246
        ];
247
    }
248
249
    /** @return array<int,array{string,string,string}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string,string,string}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
250
    public function provideMakeAbsoluteTests(): array
251
    {
252
        return array_merge($this->providePathTests(), [
253
            // collapse dots
254
            ['css/./style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'],
255
            ['css/../style.css', '/webmozart/puli', '/webmozart/puli/style.css'],
256
            ['css/./../style.css', '/webmozart/puli', '/webmozart/puli/style.css'],
257
            ['css/.././style.css', '/webmozart/puli', '/webmozart/puli/style.css'],
258
            ['./css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'],
259
260
            ['css\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'],
261
            ['css\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'],
262
            ['css\\.\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'],
263
            ['css\\..\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'],
264
            ['.\\css\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'],
265
266
            // collapse dots on root
267
            ['./css/style.css', '/', '/css/style.css'],
268
            ['../css/style.css', '/', '/css/style.css'],
269
            ['../css/./style.css', '/', '/css/style.css'],
270
            ['../css/../style.css', '/', '/style.css'],
271
            ['../css/./../style.css', '/', '/style.css'],
272
            ['../css/.././style.css', '/', '/style.css'],
273
274
            ['.\\css\\style.css', '\\', '/css/style.css'],
275
            ['..\\css\\style.css', '\\', '/css/style.css'],
276
            ['..\\css\\.\\style.css', '\\', '/css/style.css'],
277
            ['..\\css\\..\\style.css', '\\', '/style.css'],
278
            ['..\\css\\.\\..\\style.css', '\\', '/style.css'],
279
            ['..\\css\\..\\.\\style.css', '\\', '/style.css'],
280
281
            ['./css/style.css', 'C:/', 'C:/css/style.css'],
282
            ['../css/style.css', 'C:/', 'C:/css/style.css'],
283
            ['../css/./style.css', 'C:/', 'C:/css/style.css'],
284
            ['../css/../style.css', 'C:/', 'C:/style.css'],
285
            ['../css/./../style.css', 'C:/', 'C:/style.css'],
286
            ['../css/.././style.css', 'C:/', 'C:/style.css'],
287
288
            ['.\\css\\style.css', 'C:\\', 'C:/css/style.css'],
289
            ['..\\css\\style.css', 'C:\\', 'C:/css/style.css'],
290
            ['..\\css\\.\\style.css', 'C:\\', 'C:/css/style.css'],
291
            ['..\\css\\..\\style.css', 'C:\\', 'C:/style.css'],
292
            ['..\\css\\.\\..\\style.css', 'C:\\', 'C:/style.css'],
293
            ['..\\css\\..\\.\\style.css', 'C:\\', 'C:/style.css'],
294
295
            ['./css/style.css', 'phar:///', 'phar:///css/style.css'],
296
            ['../css/style.css', 'phar:///', 'phar:///css/style.css'],
297
            ['../css/./style.css', 'phar:///', 'phar:///css/style.css'],
298
            ['../css/../style.css', 'phar:///', 'phar:///style.css'],
299
            ['../css/./../style.css', 'phar:///', 'phar:///style.css'],
300
            ['../css/.././style.css', 'phar:///', 'phar:///style.css'],
301
302
            ['./css/style.css', 'phar://C:/', 'phar://C:/css/style.css'],
303
            ['../css/style.css', 'phar://C:/', 'phar://C:/css/style.css'],
304
            ['../css/./style.css', 'phar://C:/', 'phar://C:/css/style.css'],
305
            ['../css/../style.css', 'phar://C:/', 'phar://C:/style.css'],
306
            ['../css/./../style.css', 'phar://C:/', 'phar://C:/style.css'],
307
            ['../css/.././style.css', 'phar://C:/', 'phar://C:/style.css'],
308
309
            // absolute paths
310
            ['/css/style.css', '/webmozart/puli', '/css/style.css'],
311
            ['\\css\\style.css', '/webmozart/puli', '/css/style.css'],
312
            ['C:/css/style.css', 'C:/webmozart/puli', 'C:/css/style.css'],
313
            ['D:\\css\\style.css', 'D:/webmozart/puli', 'D:/css/style.css'],
314
        ]);
315
    }
316
317
    /**
318
     * @dataProvider provideMakeAbsoluteTests
319
     */
320
    public function testMakeAbsolute(string $relativePath, string $basePath, string $absolutePath): void
321
    {
322
        $this->assertSame($absolutePath, Path::makeAbsolute($relativePath, $basePath));
323
    }
324
325
    /** @return array<int,array{string,string}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string,string}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
326
    public function provideAbsolutePathsWithDifferentRoots(): array
327
    {
328
        return [
329
            ['C:/css/style.css', '/webmozart/puli'],
330
            ['C:/css/style.css', '\\webmozart\\puli'],
331
            ['C:\\css\\style.css', '/webmozart/puli'],
332
            ['C:\\css\\style.css', '\\webmozart\\puli'],
333
334
            ['/css/style.css', 'C:/webmozart/puli'],
335
            ['/css/style.css', 'C:\\webmozart\\puli'],
336
            ['\\css\\style.css', 'C:/webmozart/puli'],
337
            ['\\css\\style.css', 'C:\\webmozart\\puli'],
338
339
            ['D:/css/style.css', 'C:/webmozart/puli'],
340
            ['D:/css/style.css', 'C:\\webmozart\\puli'],
341
            ['D:\\css\\style.css', 'C:/webmozart/puli'],
342
            ['D:\\css\\style.css', 'C:\\webmozart\\puli'],
343
344
            ['phar:///css/style.css', '/webmozart/puli'],
345
            ['/css/style.css', 'phar:///webmozart/puli'],
346
347
            ['phar://C:/css/style.css', 'C:/webmozart/puli'],
348
            ['phar://C:/css/style.css', 'C:\\webmozart\\puli'],
349
            ['phar://C:\\css\\style.css', 'C:/webmozart/puli'],
350
            ['phar://C:\\css\\style.css', 'C:\\webmozart\\puli'],
351
        ];
352
    }
353
354
    /**
355
     * @dataProvider provideAbsolutePathsWithDifferentRoots
356
     */
357
    public function testMakeAbsoluteDoesNotFailIfDifferentRoot(string $basePath, string $absolutePath): void
358
    {
359
        // If a path in partition D: is passed, but $basePath is in partition
360
        // C:, the path should be returned unchanged
361
        $this->assertSame(Path::canonicalize($absolutePath), Path::makeAbsolute($absolutePath, $basePath));
362
    }
363
364
    public function testMakeAbsoluteFailsIfBasePathNotAbsolute(): void
365
    {
366
        $this->expectException(\InvalidArgumentException::class);
367
        $this->expectExceptionMessage('The base path "webmozart/puli" is not an absolute path.');
368
        Path::makeAbsolute('css/style.css', 'webmozart/puli');
369
    }
370
371
    public function testMakeAbsoluteFailsIfBasePathEmpty(): void
372
    {
373
        $this->expectException(\InvalidArgumentException::class);
374
        $this->expectExceptionMessage('The base path must be a non-empty string. Got: ""');
375
        Path::makeAbsolute('css/style.css', '');
376
    }
377
378
    /** @return array<int,array{string,string, string}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string,string, string}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
379
    public function provideMakeRelativeTests(): array
380
    {
381
        $paths = array_map(function (array $arguments) {
382
            return [$arguments[2], $arguments[1], $arguments[0]];
383
        }, $this->providePathTests());
384
385
        return array_merge($paths, [
386
            ['/webmozart/puli/./css/style.css', '/webmozart/puli', 'css/style.css'],
387
            ['/webmozart/puli/../css/style.css', '/webmozart/puli', '../css/style.css'],
388
            ['/webmozart/puli/.././css/style.css', '/webmozart/puli', '../css/style.css'],
389
            ['/webmozart/puli/./../css/style.css', '/webmozart/puli', '../css/style.css'],
390
            ['/webmozart/puli/../../css/style.css', '/webmozart/puli', '../../css/style.css'],
391
            ['/webmozart/puli/css/style.css', '/webmozart/./puli', 'css/style.css'],
392
            ['/webmozart/puli/css/style.css', '/webmozart/../puli', '../webmozart/puli/css/style.css'],
393
            ['/webmozart/puli/css/style.css', '/webmozart/./../puli', '../webmozart/puli/css/style.css'],
394
            ['/webmozart/puli/css/style.css', '/webmozart/.././puli', '../webmozart/puli/css/style.css'],
395
            ['/webmozart/puli/css/style.css', '/webmozart/../../puli', '../webmozart/puli/css/style.css'],
396
397
            // first argument shorter than second
398
            ['/css', '/webmozart/puli', '../../css'],
399
400
            // second argument shorter than first
401
            ['/webmozart/puli', '/css', '../webmozart/puli'],
402
403
            ['\\webmozart\\puli\\css\\style.css', '\\webmozart\\puli', 'css/style.css'],
404
            ['\\webmozart\\css\\style.css', '\\webmozart\\puli', '../css/style.css'],
405
            ['\\css\\style.css', '\\webmozart\\puli', '../../css/style.css'],
406
407
            ['C:/webmozart/puli/css/style.css', 'C:/webmozart/puli', 'css/style.css'],
408
            ['C:/webmozart/css/style.css', 'C:/webmozart/puli', '../css/style.css'],
409
            ['C:/css/style.css', 'C:/webmozart/puli', '../../css/style.css'],
410
411
            ['C:\\webmozart\\puli\\css\\style.css', 'C:\\webmozart\\puli', 'css/style.css'],
412
            ['C:\\webmozart\\css\\style.css', 'C:\\webmozart\\puli', '../css/style.css'],
413
            ['C:\\css\\style.css', 'C:\\webmozart\\puli', '../../css/style.css'],
414
415
            ['phar:///webmozart/puli/css/style.css', 'phar:///webmozart/puli', 'css/style.css'],
416
            ['phar:///webmozart/css/style.css', 'phar:///webmozart/puli', '../css/style.css'],
417
            ['phar:///css/style.css', 'phar:///webmozart/puli', '../../css/style.css'],
418
419
            ['phar://C:/webmozart/puli/css/style.css', 'phar://C:/webmozart/puli', 'css/style.css'],
420
            ['phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/puli', '../css/style.css'],
421
            ['phar://C:/css/style.css', 'phar://C:/webmozart/puli', '../../css/style.css'],
422
423
            // already relative + already in root basepath
424
            ['../style.css', '/', 'style.css'],
425
            ['./style.css', '/', 'style.css'],
426
            ['../../style.css', '/', 'style.css'],
427
            ['..\\style.css', 'C:\\', 'style.css'],
428
            ['.\\style.css', 'C:\\', 'style.css'],
429
            ['..\\..\\style.css', 'C:\\', 'style.css'],
430
            ['../style.css', 'C:/', 'style.css'],
431
            ['./style.css', 'C:/', 'style.css'],
432
            ['../../style.css', 'C:/', 'style.css'],
433
            ['..\\style.css', '\\', 'style.css'],
434
            ['.\\style.css', '\\', 'style.css'],
435
            ['..\\..\\style.css', '\\', 'style.css'],
436
            ['../style.css', 'phar:///', 'style.css'],
437
            ['./style.css', 'phar:///', 'style.css'],
438
            ['../../style.css', 'phar:///', 'style.css'],
439
            ['..\\style.css', 'phar://C:\\', 'style.css'],
440
            ['.\\style.css', 'phar://C:\\', 'style.css'],
441
            ['..\\..\\style.css', 'phar://C:\\', 'style.css'],
442
443
            ['css/../style.css', '/', 'style.css'],
444
            ['css/./style.css', '/', 'css/style.css'],
445
            ['css\\..\\style.css', 'C:\\', 'style.css'],
446
            ['css\\.\\style.css', 'C:\\', 'css/style.css'],
447
            ['css/../style.css', 'C:/', 'style.css'],
448
            ['css/./style.css', 'C:/', 'css/style.css'],
449
            ['css\\..\\style.css', '\\', 'style.css'],
450
            ['css\\.\\style.css', '\\', 'css/style.css'],
451
            ['css/../style.css', 'phar:///', 'style.css'],
452
            ['css/./style.css', 'phar:///', 'css/style.css'],
453
            ['css\\..\\style.css', 'phar://C:\\', 'style.css'],
454
            ['css\\.\\style.css', 'phar://C:\\', 'css/style.css'],
455
456
            // already relative
457
            ['css/style.css', '/webmozart/puli', 'css/style.css'],
458
            ['css\\style.css', '\\webmozart\\puli', 'css/style.css'],
459
460
            // both relative
461
            ['css/style.css', 'webmozart/puli', '../../css/style.css'],
462
            ['css\\style.css', 'webmozart\\puli', '../../css/style.css'],
463
464
            // relative to empty
465
            ['css/style.css', '', 'css/style.css'],
466
            ['css\\style.css', '', 'css/style.css'],
467
468
            // different slashes in path and base path
469
            ['/webmozart/puli/css/style.css', '\\webmozart\\puli', 'css/style.css'],
470
            ['\\webmozart\\puli\\css\\style.css', '/webmozart/puli', 'css/style.css'],
471
        ]);
472
    }
473
474
    /**
475
     * @dataProvider provideMakeRelativeTests
476
     */
477
    public function testMakeRelative(string $absolutePath, string $basePath, string $relativePath): void
478
    {
479
        $this->assertSame($relativePath, Path::makeRelative($absolutePath, $basePath));
480
    }
481
482
    public function testMakeRelativeFailsIfAbsolutePathAndBasePathNotAbsolute(): void
483
    {
484
        $this->expectException(\InvalidArgumentException::class);
485
        $this->expectExceptionMessage('The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "webmozart/puli". You should provide an absolute base path instead.');
486
        Path::makeRelative('/webmozart/puli/css/style.css', 'webmozart/puli');
487
    }
488
489
    public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty(): void
490
    {
491
        $this->expectException(\InvalidArgumentException::class);
492
        $this->expectExceptionMessage('The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead.');
493
        Path::makeRelative('/webmozart/puli/css/style.css', '');
494
    }
495
496
    /**
497
     * @dataProvider provideAbsolutePathsWithDifferentRoots
498
     */
499
    public function testMakeRelativeFailsIfDifferentRoot(string $absolutePath, string $basePath): void
500
    {
501
        $this->expectException(\InvalidArgumentException::class);
502
        Path::makeRelative($absolutePath, $basePath);
503
    }
504
505
    /** @return array<int,array{string,bool}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string,bool}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
506
    public function provideIsLocalTests(): array
507
    {
508
        return [
509
            ['/bg.png', true],
510
            ['bg.png', true],
511
            ['http://example.com/bg.png', false],
512
            ['http://example.com', false],
513
            ['', false],
514
        ];
515
    }
516
517
    /** @return array<int,array{string,string, bool}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string,string, bool}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
518
    public function provideIsBasePathTests(): array
519
    {
520
        return [
521
            // same paths
522
            ['/base/path', '/base/path', true],
523
            ['C:/base/path', 'C:/base/path', true],
524
            ['C:\\base\\path', 'C:\\base\\path', true],
525
            ['C:/base/path', 'C:\\base\\path', true],
526
            ['phar:///base/path', 'phar:///base/path', true],
527
            ['phar://C:/base/path', 'phar://C:/base/path', true],
528
529
            // trailing slash
530
            ['/base/path/', '/base/path', true],
531
            ['C:/base/path/', 'C:/base/path', true],
532
            ['C:\\base\\path\\', 'C:\\base\\path', true],
533
            ['C:/base/path/', 'C:\\base\\path', true],
534
            ['phar:///base/path/', 'phar:///base/path', true],
535
            ['phar://C:/base/path/', 'phar://C:/base/path', true],
536
537
            ['/base/path', '/base/path/', true],
538
            ['C:/base/path', 'C:/base/path/', true],
539
            ['C:\\base\\path', 'C:\\base\\path\\', true],
540
            ['C:/base/path', 'C:\\base\\path\\', true],
541
            ['phar:///base/path', 'phar:///base/path/', true],
542
            ['phar://C:/base/path', 'phar://C:/base/path/', true],
543
544
            // first in second
545
            ['/base/path/sub', '/base/path', false],
546
            ['C:/base/path/sub', 'C:/base/path', false],
547
            ['C:\\base\\path\\sub', 'C:\\base\\path', false],
548
            ['C:/base/path/sub', 'C:\\base\\path', false],
549
            ['phar:///base/path/sub', 'phar:///base/path', false],
550
            ['phar://C:/base/path/sub', 'phar://C:/base/path', false],
551
552
            // second in first
553
            ['/base/path', '/base/path/sub', true],
554
            ['C:/base/path', 'C:/base/path/sub', true],
555
            ['C:\\base\\path', 'C:\\base\\path\\sub', true],
556
            ['C:/base/path', 'C:\\base\\path\\sub', true],
557
            ['phar:///base/path', 'phar:///base/path/sub', true],
558
            ['phar://C:/base/path', 'phar://C:/base/path/sub', true],
559
560
            // first is prefix
561
            ['/base/path/di', '/base/path/dir', false],
562
            ['C:/base/path/di', 'C:/base/path/dir', false],
563
            ['C:\\base\\path\\di', 'C:\\base\\path\\dir', false],
564
            ['C:/base/path/di', 'C:\\base\\path\\dir', false],
565
            ['phar:///base/path/di', 'phar:///base/path/dir', false],
566
            ['phar://C:/base/path/di', 'phar://C:/base/path/dir', false],
567
568
            // second is prefix
569
            ['/base/path/dir', '/base/path/di', false],
570
            ['C:/base/path/dir', 'C:/base/path/di', false],
571
            ['C:\\base\\path\\dir', 'C:\\base\\path\\di', false],
572
            ['C:/base/path/dir', 'C:\\base\\path\\di', false],
573
            ['phar:///base/path/dir', 'phar:///base/path/di', false],
574
            ['phar://C:/base/path/dir', 'phar://C:/base/path/di', false],
575
576
            // root
577
            ['/', '/second', true],
578
            ['C:/', 'C:/second', true],
579
            ['C:', 'C:/second', true],
580
            ['C:\\', 'C:\\second', true],
581
            ['C:/', 'C:\\second', true],
582
            ['phar:///', 'phar:///second', true],
583
            ['phar://C:/', 'phar://C:/second', true],
584
585
            // windows vs unix
586
            ['/base/path', 'C:/base/path', false],
587
            ['C:/base/path', '/base/path', false],
588
            ['/base/path', 'C:\\base\\path', false],
589
            ['/base/path', 'phar:///base/path', false],
590
            ['phar:///base/path', 'phar://C:/base/path', false],
591
592
            // different partitions
593
            ['C:/base/path', 'D:/base/path', false],
594
            ['C:/base/path', 'D:\\base\\path', false],
595
            ['C:\\base\\path', 'D:\\base\\path', false],
596
            ['C:/base/path', 'phar://C:/base/path', false],
597
            ['phar://C:/base/path', 'phar://D:/base/path', false],
598
        ];
599
    }
600
601
    /**
602
     * @dataProvider provideIsBasePathTests
603
     */
604
    public function testIsBasePath(string $path, string $ofPath, bool $result): void
605
    {
606
        $this->assertSame($result, Path::isBasePath($path, $ofPath));
607
    }
608
609
    /** @return array<int,array{string, string, string}> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{string, string, string}> at position 6 could not be parsed: Expected ':' at position 6, but found 'string'.
Loading history...
610
    public function provideJoinTests(): array
611
    {
612
        return [
613
            ['', '', ''],
614
            ['/path/to/test', '', '/path/to/test'],
615
            ['/path/to//test', '', '/path/to/test'],
616
            ['', '/path/to/test', '/path/to/test'],
617
            ['', '/path/to//test', '/path/to/test'],
618
619
            ['/path/to/test', 'subdir', '/path/to/test/subdir'],
620
            ['/path/to/test/', 'subdir', '/path/to/test/subdir'],
621
            ['/path/to/test', '/subdir', '/path/to/test/subdir'],
622
            ['/path/to/test/', '/subdir', '/path/to/test/subdir'],
623
            ['/path/to/test', './subdir', '/path/to/test/subdir'],
624
            ['/path/to/test/', './subdir', '/path/to/test/subdir'],
625
            ['/path/to/test/', '../parentdir', '/path/to/parentdir'],
626
            ['/path/to/test', '../parentdir', '/path/to/parentdir'],
627
            ['path/to/test/', '/subdir', 'path/to/test/subdir'],
628
            ['path/to/test', '/subdir', 'path/to/test/subdir'],
629
            ['../path/to/test', '/subdir', '../path/to/test/subdir'],
630
            ['path', '../../subdir', '../subdir'],
631
            ['/path', '../../subdir', '/subdir'],
632
            ['../path', '../../subdir', '../../subdir'],
633
634
            ['base/path', 'to/test', 'base/path/to/test'],
635
636
            ['C:\\path\\to\\test', 'subdir', 'C:/path/to/test/subdir'],
637
            ['C:\\path\\to\\test\\', 'subdir', 'C:/path/to/test/subdir'],
638
            ['C:\\path\\to\\test', '/subdir', 'C:/path/to/test/subdir'],
639
            ['C:\\path\\to\\test\\', '/subdir', 'C:/path/to/test/subdir'],
640
641
            ['/', 'subdir', '/subdir'],
642
            ['/', '/subdir', '/subdir'],
643
            ['C:/', 'subdir', 'C:/subdir'],
644
            ['C:/', '/subdir', 'C:/subdir'],
645
            ['C:\\', 'subdir', 'C:/subdir'],
646
            ['C:\\', '/subdir', 'C:/subdir'],
647
            ['C:', 'subdir', 'C:/subdir'],
648
            ['C:', '/subdir', 'C:/subdir'],
649
650
            ['phar://', '/path/to/test', 'phar:///path/to/test'],
651
            ['phar:///', '/path/to/test', 'phar:///path/to/test'],
652
            ['phar:///path/to/test', 'subdir', 'phar:///path/to/test/subdir'],
653
            ['phar:///path/to/test', 'subdir/', 'phar:///path/to/test/subdir'],
654
            ['phar:///path/to/test', '/subdir', 'phar:///path/to/test/subdir'],
655
            ['phar:///path/to/test/', 'subdir', 'phar:///path/to/test/subdir'],
656
            ['phar:///path/to/test/', '/subdir', 'phar:///path/to/test/subdir'],
657
658
            ['phar://', 'C:/path/to/test', 'phar://C:/path/to/test'],
659
            ['phar://', 'C:\\path\\to\\test', 'phar://C:/path/to/test'],
660
            ['phar://C:/path/to/test', 'subdir', 'phar://C:/path/to/test/subdir'],
661
            ['phar://C:/path/to/test', 'subdir/', 'phar://C:/path/to/test/subdir'],
662
            ['phar://C:/path/to/test', '/subdir', 'phar://C:/path/to/test/subdir'],
663
            ['phar://C:/path/to/test/', 'subdir', 'phar://C:/path/to/test/subdir'],
664
            ['phar://C:/path/to/test/', '/subdir', 'phar://C:/path/to/test/subdir'],
665
            ['phar://C:', 'path/to/test', 'phar://C:/path/to/test'],
666
            ['phar://C:', '/path/to/test', 'phar://C:/path/to/test'],
667
            ['phar://C:/', 'path/to/test', 'phar://C:/path/to/test'],
668
            ['phar://C:/', '/path/to/test', 'phar://C:/path/to/test'],
669
        ];
670
    }
671
672
    /**
673
     * @dataProvider provideJoinTests
674
     */
675
    public function testJoin(string $path1, string $path2, string $result): void
676
    {
677
        $this->assertSame($result, Path::join([$path1, $path2]));
678
    }
679
680
    public function testJoinVarArgs(): void
681
    {
682
        $this->assertSame('/path', Path::join(['/path']));
683
        $this->assertSame('/path/to', Path::join(['/path', 'to']));
684
        $this->assertSame('/path/to/test', Path::join(['/path', 'to', '/test']));
685
        $this->assertSame('/path/to/test/subdir', Path::join(['/path', 'to', '/test', 'subdir/']));
686
    }
687
688
    public function testGetHomeDirectoryFailsIfNotSupportedOperationSystem(): void
689
    {
690
        putenv('HOME=');
691
692
        $this->expectException(InvalidPathException::class);
693
        $this->expectExceptionMessage('Your environment or operating system is not supported');
694
695
        Path::getHomeDirectory();
696
    }
697
698
    public function testGetHomeDirectoryForUnix(): void
699
    {
700
        $this->assertEquals('/home/webmozart', Path::getHomeDirectory());
701
    }
702
703
    public function testGetHomeDirectoryForWindows(): void
704
    {
705
        putenv('HOME=');
706
        putenv('HOMEDRIVE=C:');
707
        putenv('HOMEPATH=/users/webmozart');
708
709
        $this->assertEquals('C:/users/webmozart', Path::getHomeDirectory());
710
    }
711
712
    public function testExceedingBufferSize(): void
713
    {
714
        for ($i = 0; $i < 2000; ++$i) {
715
            $input = "/path{$i}/bar/../foo";
716
            $expected = "/path{$i}/foo";
717
            $actual = Path::canonicalize($input);
718
            $this->assertSame($expected, $actual);
719
        }
720
    }
721
}
722