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}> */ |
|
|
|
|
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}> */ |
|
|
|
|
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}> */ |
|
|
|
|
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}> */ |
|
|
|
|
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}> */ |
|
|
|
|
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}> */ |
|
|
|
|
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}> */ |
|
|
|
|
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}> */ |
|
|
|
|
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}> */ |
|
|
|
|
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
|
|
|
|