cc88b97a39a19f17153b1d2230cb7ec5e4905e16
[yaffs-website] / vendor / webmozart / path-util / tests / PathTest.php
1 <?php
2
3 /*
4  * This file is part of the webmozart/path-util package.
5  *
6  * (c) Bernhard Schussek <bschussek@gmail.com>
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 Webmozart\PathUtil\Tests;
13
14 use Webmozart\PathUtil\Path;
15
16 /**
17  * @since  1.0
18  *
19  * @author Bernhard Schussek <bschussek@gmail.com>
20  * @author Thomas Schulz <mail@king2500.net>
21  */
22 class PathTest extends \PHPUnit_Framework_TestCase
23 {
24     protected $storedEnv = array();
25
26     public function setUp()
27     {
28         $this->storedEnv['HOME'] = getenv('HOME');
29         $this->storedEnv['HOMEDRIVE'] = getenv('HOMEDRIVE');
30         $this->storedEnv['HOMEPATH'] = getenv('HOMEPATH');
31
32         putenv('HOME=/home/webmozart');
33         putenv('HOMEDRIVE=');
34         putenv('HOMEPATH=');
35     }
36
37     public function tearDown()
38     {
39         putenv('HOME='.$this->storedEnv['HOME']);
40         putenv('HOMEDRIVE='.$this->storedEnv['HOMEDRIVE']);
41         putenv('HOMEPATH='.$this->storedEnv['HOMEPATH']);
42     }
43
44     public function provideCanonicalizationTests()
45     {
46         return array(
47             // relative paths (forward slash)
48             array('css/./style.css', 'css/style.css'),
49             array('css/../style.css', 'style.css'),
50             array('css/./../style.css', 'style.css'),
51             array('css/.././style.css', 'style.css'),
52             array('css/../../style.css', '../style.css'),
53             array('./css/style.css', 'css/style.css'),
54             array('../css/style.css', '../css/style.css'),
55             array('./../css/style.css', '../css/style.css'),
56             array('.././css/style.css', '../css/style.css'),
57             array('../../css/style.css', '../../css/style.css'),
58             array('', ''),
59             array('.', ''),
60             array('..', '..'),
61             array('./..', '..'),
62             array('../.', '..'),
63             array('../..', '../..'),
64
65             // relative paths (backslash)
66             array('css\\.\\style.css', 'css/style.css'),
67             array('css\\..\\style.css', 'style.css'),
68             array('css\\.\\..\\style.css', 'style.css'),
69             array('css\\..\\.\\style.css', 'style.css'),
70             array('css\\..\\..\\style.css', '../style.css'),
71             array('.\\css\\style.css', 'css/style.css'),
72             array('..\\css\\style.css', '../css/style.css'),
73             array('.\\..\\css\\style.css', '../css/style.css'),
74             array('..\\.\\css\\style.css', '../css/style.css'),
75             array('..\\..\\css\\style.css', '../../css/style.css'),
76
77             // absolute paths (forward slash, UNIX)
78             array('/css/style.css', '/css/style.css'),
79             array('/css/./style.css', '/css/style.css'),
80             array('/css/../style.css', '/style.css'),
81             array('/css/./../style.css', '/style.css'),
82             array('/css/.././style.css', '/style.css'),
83             array('/./css/style.css', '/css/style.css'),
84             array('/../css/style.css', '/css/style.css'),
85             array('/./../css/style.css', '/css/style.css'),
86             array('/.././css/style.css', '/css/style.css'),
87             array('/../../css/style.css', '/css/style.css'),
88
89             // absolute paths (backslash, UNIX)
90             array('\\css\\style.css', '/css/style.css'),
91             array('\\css\\.\\style.css', '/css/style.css'),
92             array('\\css\\..\\style.css', '/style.css'),
93             array('\\css\\.\\..\\style.css', '/style.css'),
94             array('\\css\\..\\.\\style.css', '/style.css'),
95             array('\\.\\css\\style.css', '/css/style.css'),
96             array('\\..\\css\\style.css', '/css/style.css'),
97             array('\\.\\..\\css\\style.css', '/css/style.css'),
98             array('\\..\\.\\css\\style.css', '/css/style.css'),
99             array('\\..\\..\\css\\style.css', '/css/style.css'),
100
101             // absolute paths (forward slash, Windows)
102             array('C:/css/style.css', 'C:/css/style.css'),
103             array('C:/css/./style.css', 'C:/css/style.css'),
104             array('C:/css/../style.css', 'C:/style.css'),
105             array('C:/css/./../style.css', 'C:/style.css'),
106             array('C:/css/.././style.css', 'C:/style.css'),
107             array('C:/./css/style.css', 'C:/css/style.css'),
108             array('C:/../css/style.css', 'C:/css/style.css'),
109             array('C:/./../css/style.css', 'C:/css/style.css'),
110             array('C:/.././css/style.css', 'C:/css/style.css'),
111             array('C:/../../css/style.css', 'C:/css/style.css'),
112
113             // absolute paths (backslash, Windows)
114             array('C:\\css\\style.css', 'C:/css/style.css'),
115             array('C:\\css\\.\\style.css', 'C:/css/style.css'),
116             array('C:\\css\\..\\style.css', 'C:/style.css'),
117             array('C:\\css\\.\\..\\style.css', 'C:/style.css'),
118             array('C:\\css\\..\\.\\style.css', 'C:/style.css'),
119             array('C:\\.\\css\\style.css', 'C:/css/style.css'),
120             array('C:\\..\\css\\style.css', 'C:/css/style.css'),
121             array('C:\\.\\..\\css\\style.css', 'C:/css/style.css'),
122             array('C:\\..\\.\\css\\style.css', 'C:/css/style.css'),
123             array('C:\\..\\..\\css\\style.css', 'C:/css/style.css'),
124
125             // Windows special case
126             array('C:', 'C:/'),
127
128             // Don't change malformed path
129             array('C:css/style.css', 'C:css/style.css'),
130
131             // absolute paths (stream, UNIX)
132             array('phar:///css/style.css', 'phar:///css/style.css'),
133             array('phar:///css/./style.css', 'phar:///css/style.css'),
134             array('phar:///css/../style.css', 'phar:///style.css'),
135             array('phar:///css/./../style.css', 'phar:///style.css'),
136             array('phar:///css/.././style.css', 'phar:///style.css'),
137             array('phar:///./css/style.css', 'phar:///css/style.css'),
138             array('phar:///../css/style.css', 'phar:///css/style.css'),
139             array('phar:///./../css/style.css', 'phar:///css/style.css'),
140             array('phar:///.././css/style.css', 'phar:///css/style.css'),
141             array('phar:///../../css/style.css', 'phar:///css/style.css'),
142
143             // absolute paths (stream, Windows)
144             array('phar://C:/css/style.css', 'phar://C:/css/style.css'),
145             array('phar://C:/css/./style.css', 'phar://C:/css/style.css'),
146             array('phar://C:/css/../style.css', 'phar://C:/style.css'),
147             array('phar://C:/css/./../style.css', 'phar://C:/style.css'),
148             array('phar://C:/css/.././style.css', 'phar://C:/style.css'),
149             array('phar://C:/./css/style.css', 'phar://C:/css/style.css'),
150             array('phar://C:/../css/style.css', 'phar://C:/css/style.css'),
151             array('phar://C:/./../css/style.css', 'phar://C:/css/style.css'),
152             array('phar://C:/.././css/style.css', 'phar://C:/css/style.css'),
153             array('phar://C:/../../css/style.css', 'phar://C:/css/style.css'),
154
155             // paths with "~" UNIX
156             array('~/css/style.css', '/home/webmozart/css/style.css'),
157             array('~/css/./style.css', '/home/webmozart/css/style.css'),
158             array('~/css/../style.css', '/home/webmozart/style.css'),
159             array('~/css/./../style.css', '/home/webmozart/style.css'),
160             array('~/css/.././style.css', '/home/webmozart/style.css'),
161             array('~/./css/style.css', '/home/webmozart/css/style.css'),
162             array('~/../css/style.css', '/home/css/style.css'),
163             array('~/./../css/style.css', '/home/css/style.css'),
164             array('~/.././css/style.css', '/home/css/style.css'),
165             array('~/../../css/style.css', '/css/style.css'),
166         );
167     }
168
169     /**
170      * @dataProvider provideCanonicalizationTests
171      */
172     public function testCanonicalize($path, $canonicalized)
173     {
174         $this->assertSame($canonicalized, Path::canonicalize($path));
175     }
176
177     /**
178      * @expectedException \InvalidArgumentException
179      * @expectedExceptionMessage The path must be a string. Got: array
180      */
181     public function testCanonicalizeFailsIfInvalidPath()
182     {
183         Path::canonicalize(array());
184     }
185
186     public function provideGetDirectoryTests()
187     {
188         return array(
189             array('/webmozart/puli/style.css', '/webmozart/puli'),
190             array('/webmozart/puli', '/webmozart'),
191             array('/webmozart', '/'),
192             array('/', '/'),
193             array('', ''),
194
195             array('\\webmozart\\puli\\style.css', '/webmozart/puli'),
196             array('\\webmozart\\puli', '/webmozart'),
197             array('\\webmozart', '/'),
198             array('\\', '/'),
199
200             array('C:/webmozart/puli/style.css', 'C:/webmozart/puli'),
201             array('C:/webmozart/puli', 'C:/webmozart'),
202             array('C:/webmozart', 'C:/'),
203             array('C:/', 'C:/'),
204             array('C:', 'C:/'),
205
206             array('C:\\webmozart\\puli\\style.css', 'C:/webmozart/puli'),
207             array('C:\\webmozart\\puli', 'C:/webmozart'),
208             array('C:\\webmozart', 'C:/'),
209             array('C:\\', 'C:/'),
210
211             array('phar:///webmozart/puli/style.css', 'phar:///webmozart/puli'),
212             array('phar:///webmozart/puli', 'phar:///webmozart'),
213             array('phar:///webmozart', 'phar:///'),
214             array('phar:///', 'phar:///'),
215
216             array('phar://C:/webmozart/puli/style.css', 'phar://C:/webmozart/puli'),
217             array('phar://C:/webmozart/puli', 'phar://C:/webmozart'),
218             array('phar://C:/webmozart', 'phar://C:/'),
219             array('phar://C:/', 'phar://C:/'),
220
221             array('webmozart/puli/style.css', 'webmozart/puli'),
222             array('webmozart/puli', 'webmozart'),
223             array('webmozart', ''),
224
225             array('webmozart\\puli\\style.css', 'webmozart/puli'),
226             array('webmozart\\puli', 'webmozart'),
227             array('webmozart', ''),
228
229             array('/webmozart/./puli/style.css', '/webmozart/puli'),
230             array('/webmozart/../puli/style.css', '/puli'),
231             array('/webmozart/./../puli/style.css', '/puli'),
232             array('/webmozart/.././puli/style.css', '/puli'),
233             array('/webmozart/../../puli/style.css', '/puli'),
234             array('/.', '/'),
235             array('/..', '/'),
236
237             array('C:webmozart', ''),
238         );
239     }
240
241     /**
242      * @dataProvider provideGetDirectoryTests
243      */
244     public function testGetDirectory($path, $directory)
245     {
246         $this->assertSame($directory, Path::getDirectory($path));
247     }
248
249     /**
250      * @expectedException \InvalidArgumentException
251      * @expectedExceptionMessage The path must be a string. Got: array
252      */
253     public function testGetDirectoryFailsIfInvalidPath()
254     {
255         Path::getDirectory(array());
256     }
257
258     public function provideGetFilenameTests()
259     {
260         return array(
261             array('/webmozart/puli/style.css', 'style.css'),
262             array('/webmozart/puli/STYLE.CSS', 'STYLE.CSS'),
263             array('/webmozart/puli/style.css/', 'style.css'),
264             array('/webmozart/puli/', 'puli'),
265             array('/webmozart/puli', 'puli'),
266             array('/', ''),
267             array('', ''),
268         );
269     }
270
271     /**
272      * @dataProvider provideGetFilenameTests
273      */
274     public function testGetFilename($path, $filename)
275     {
276         $this->assertSame($filename, Path::getFilename($path));
277     }
278
279     /**
280      * @expectedException \InvalidArgumentException
281      * @expectedExceptionMessage The path must be a string. Got: array
282      */
283     public function testGetFilenameFailsIfInvalidPath()
284     {
285         Path::getFilename(array());
286     }
287
288     public function provideGetFilenameWithoutExtensionTests()
289     {
290         return array(
291             array('/webmozart/puli/style.css.twig', null, 'style.css'),
292             array('/webmozart/puli/style.css.', null, 'style.css'),
293             array('/webmozart/puli/style.css', null, 'style'),
294             array('/webmozart/puli/.style.css', null, '.style'),
295             array('/webmozart/puli/', null, 'puli'),
296             array('/webmozart/puli', null, 'puli'),
297             array('/', null, ''),
298             array('', null, ''),
299
300             array('/webmozart/puli/style.css', 'css', 'style'),
301             array('/webmozart/puli/style.css', '.css', 'style'),
302             array('/webmozart/puli/style.css', 'twig', 'style.css'),
303             array('/webmozart/puli/style.css', '.twig', 'style.css'),
304             array('/webmozart/puli/style.css', '', 'style.css'),
305             array('/webmozart/puli/style.css.', '', 'style.css'),
306             array('/webmozart/puli/style.css.', '.', 'style.css'),
307             array('/webmozart/puli/style.css.', '.css', 'style.css'),
308             array('/webmozart/puli/.style.css', 'css', '.style'),
309             array('/webmozart/puli/.style.css', '.css', '.style'),
310         );
311     }
312
313     /**
314      * @dataProvider provideGetFilenameWithoutExtensionTests
315      */
316     public function testGetFilenameWithoutExtension($path, $extension, $filename)
317     {
318         $this->assertSame($filename, Path::getFilenameWithoutExtension($path, $extension));
319     }
320
321     /**
322      * @expectedException \InvalidArgumentException
323      * @expectedExceptionMessage The path must be a string. Got: array
324      */
325     public function testGetFilenameWithoutExtensionFailsIfInvalidPath()
326     {
327         Path::getFilenameWithoutExtension(array(), '.css');
328     }
329
330     /**
331      * @expectedException \InvalidArgumentException
332      * @expectedExceptionMessage The extension must be a string or null. Got: array
333      */
334     public function testGetFilenameWithoutExtensionFailsIfInvalidExtension()
335     {
336         Path::getFilenameWithoutExtension('/style.css', array());
337     }
338
339     public function provideGetExtensionTests()
340     {
341         $tests = array(
342             array('/webmozart/puli/style.css.twig', false, 'twig'),
343             array('/webmozart/puli/style.css', false, 'css'),
344             array('/webmozart/puli/style.css.', false, ''),
345             array('/webmozart/puli/', false, ''),
346             array('/webmozart/puli', false, ''),
347             array('/', false, ''),
348             array('', false, ''),
349
350             array('/webmozart/puli/style.CSS', false, 'CSS'),
351             array('/webmozart/puli/style.CSS', true, 'css'),
352             array('/webmozart/puli/style.ÄÖÜ', false, 'ÄÖÜ'),
353         );
354
355         if (extension_loaded('mbstring')) {
356             // This can only be tested, when mbstring is installed
357             $tests[] = array('/webmozart/puli/style.ÄÖÜ', true, 'äöü');
358         }
359
360         return $tests;
361     }
362
363     /**
364      * @dataProvider provideGetExtensionTests
365      */
366     public function testGetExtension($path, $forceLowerCase, $extension)
367     {
368         $this->assertSame($extension, Path::getExtension($path, $forceLowerCase));
369     }
370
371     /**
372      * @expectedException \InvalidArgumentException
373      * @expectedExceptionMessage The path must be a string. Got: array
374      */
375     public function testGetExtensionFailsIfInvalidPath()
376     {
377         Path::getExtension(array());
378     }
379
380     public function provideHasExtensionTests()
381     {
382         $tests = array(
383             array(true, '/webmozart/puli/style.css.twig', null, false),
384             array(true, '/webmozart/puli/style.css', null, false),
385             array(false, '/webmozart/puli/style.css.', null, false),
386             array(false, '/webmozart/puli/', null, false),
387             array(false, '/webmozart/puli', null, false),
388             array(false, '/', null, false),
389             array(false, '', null, false),
390
391             array(true, '/webmozart/puli/style.css.twig', 'twig', false),
392             array(false, '/webmozart/puli/style.css.twig', 'css', false),
393             array(true, '/webmozart/puli/style.css', 'css', false),
394             array(true, '/webmozart/puli/style.css', '.css', false),
395             array(true, '/webmozart/puli/style.css.', '', false),
396             array(false, '/webmozart/puli/', 'ext', false),
397             array(false, '/webmozart/puli', 'ext', false),
398             array(false, '/', 'ext', false),
399             array(false, '', 'ext', false),
400
401             array(false, '/webmozart/puli/style.css', 'CSS', false),
402             array(true, '/webmozart/puli/style.css', 'CSS', true),
403             array(false, '/webmozart/puli/style.CSS', 'css', false),
404             array(true, '/webmozart/puli/style.CSS', 'css', true),
405             array(true, '/webmozart/puli/style.ÄÖÜ', 'ÄÖÜ', false),
406
407             array(true, '/webmozart/puli/style.css', array('ext', 'css'), false),
408             array(true, '/webmozart/puli/style.css', array('.ext', '.css'), false),
409             array(true, '/webmozart/puli/style.css.', array('ext', ''), false),
410             array(false, '/webmozart/puli/style.css', array('foo', 'bar', ''), false),
411             array(false, '/webmozart/puli/style.css', array('.foo', '.bar', ''), false),
412         );
413
414         if (extension_loaded('mbstring')) {
415             // This can only be tested, when mbstring is installed
416             $tests[] = array(true, '/webmozart/puli/style.ÄÖÜ', 'äöü', true);
417             $tests[] = array(true, '/webmozart/puli/style.ÄÖÜ', array('äöü'), true);
418         }
419
420         return $tests;
421     }
422
423     /**
424      * @dataProvider provideHasExtensionTests
425      */
426     public function testHasExtension($hasExtension, $path, $extension, $ignoreCase)
427     {
428         $this->assertSame($hasExtension, Path::hasExtension($path, $extension, $ignoreCase));
429     }
430
431     /**
432      * @expectedException \InvalidArgumentException
433      * @expectedExceptionMessage The path must be a string. Got: array
434      */
435     public function testHasExtensionFailsIfInvalidPath()
436     {
437         Path::hasExtension(array());
438     }
439
440     /**
441      * @expectedException \InvalidArgumentException
442      * @expectedExceptionMessage The extensions must be strings. Got: stdClass
443      */
444     public function testHasExtensionFailsIfInvalidExtension()
445     {
446         Path::hasExtension('/style.css', (object) array());
447     }
448
449     public function provideChangeExtensionTests()
450     {
451         return array(
452             array('/webmozart/puli/style.css.twig', 'html', '/webmozart/puli/style.css.html'),
453             array('/webmozart/puli/style.css', 'sass', '/webmozart/puli/style.sass'),
454             array('/webmozart/puli/style.css', '.sass', '/webmozart/puli/style.sass'),
455             array('/webmozart/puli/style.css', '', '/webmozart/puli/style.'),
456             array('/webmozart/puli/style.css.', 'twig', '/webmozart/puli/style.css.twig'),
457             array('/webmozart/puli/style.css.', '', '/webmozart/puli/style.css.'),
458             array('/webmozart/puli/style.css', 'äöü', '/webmozart/puli/style.äöü'),
459             array('/webmozart/puli/style.äöü', 'css', '/webmozart/puli/style.css'),
460             array('/webmozart/puli/', 'css', '/webmozart/puli/'),
461             array('/webmozart/puli', 'css', '/webmozart/puli.css'),
462             array('/', 'css', '/'),
463             array('', 'css', ''),
464         );
465     }
466
467     /**
468      * @dataProvider provideChangeExtensionTests
469      */
470     public function testChangeExtension($path, $extension, $pathExpected)
471     {
472         static $call = 0;
473         $this->assertSame($pathExpected, Path::changeExtension($path, $extension));
474         ++$call;
475     }
476
477     /**
478      * @expectedException \InvalidArgumentException
479      * @expectedExceptionMessage The path must be a string. Got: array
480      */
481     public function testChangeExtensionFailsIfInvalidPath()
482     {
483         Path::changeExtension(array(), '.sass');
484     }
485
486     /**
487      * @expectedException \InvalidArgumentException
488      * @expectedExceptionMessage The extension must be a string. Got: array
489      */
490     public function testChangeExtensionFailsIfInvalidExtension()
491     {
492         Path::changeExtension('/style.css', array());
493     }
494
495     public function provideIsAbsolutePathTests()
496     {
497         return array(
498             array('/css/style.css', true),
499             array('/', true),
500             array('css/style.css', false),
501             array('', false),
502
503             array('\\css\\style.css', true),
504             array('\\', true),
505             array('css\\style.css', false),
506
507             array('C:/css/style.css', true),
508             array('D:/', true),
509
510             array('E:\\css\\style.css', true),
511             array('F:\\', true),
512
513             array('phar:///css/style.css', true),
514             array('phar:///', true),
515
516             // Windows special case
517             array('C:', true),
518
519             // Not considered absolute
520             array('C:css/style.css', false),
521         );
522     }
523
524     /**
525      * @dataProvider provideIsAbsolutePathTests
526      */
527     public function testIsAbsolute($path, $isAbsolute)
528     {
529         $this->assertSame($isAbsolute, Path::isAbsolute($path));
530     }
531
532     /**
533      * @expectedException \InvalidArgumentException
534      * @expectedExceptionMessage The path must be a string. Got: array
535      */
536     public function testIsAbsoluteFailsIfInvalidPath()
537     {
538         Path::isAbsolute(array());
539     }
540
541     /**
542      * @dataProvider provideIsAbsolutePathTests
543      */
544     public function testIsRelative($path, $isAbsolute)
545     {
546         $this->assertSame(!$isAbsolute, Path::isRelative($path));
547     }
548
549     /**
550      * @expectedException \InvalidArgumentException
551      * @expectedExceptionMessage The path must be a string. Got: array
552      */
553     public function testIsRelativeFailsIfInvalidPath()
554     {
555         Path::isRelative(array());
556     }
557
558     public function provideGetRootTests()
559     {
560         return array(
561             array('/css/style.css', '/'),
562             array('/', '/'),
563             array('css/style.css', ''),
564             array('', ''),
565
566             array('\\css\\style.css', '/'),
567             array('\\', '/'),
568             array('css\\style.css', ''),
569
570             array('C:/css/style.css', 'C:/'),
571             array('C:/', 'C:/'),
572             array('C:', 'C:/'),
573
574             array('D:\\css\\style.css', 'D:/'),
575             array('D:\\', 'D:/'),
576
577             array('phar:///css/style.css', 'phar:///'),
578             array('phar:///', 'phar:///'),
579
580             array('phar://C:/css/style.css', 'phar://C:/'),
581             array('phar://C:/', 'phar://C:/'),
582             array('phar://C:', 'phar://C:/'),
583         );
584     }
585
586     /**
587      * @dataProvider provideGetRootTests
588      */
589     public function testGetRoot($path, $root)
590     {
591         $this->assertSame($root, Path::getRoot($path));
592     }
593
594     /**
595      * @expectedException \InvalidArgumentException
596      * @expectedExceptionMessage The path must be a string. Got: array
597      */
598     public function testGetRootFailsIfInvalidPath()
599     {
600         Path::getRoot(array());
601     }
602
603     public function providePathTests()
604     {
605         return array(
606             // relative to absolute path
607             array('css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'),
608             array('../css/style.css', '/webmozart/puli', '/webmozart/css/style.css'),
609             array('../../css/style.css', '/webmozart/puli', '/css/style.css'),
610
611             // relative to root
612             array('css/style.css', '/', '/css/style.css'),
613             array('css/style.css', 'C:', 'C:/css/style.css'),
614             array('css/style.css', 'C:/', 'C:/css/style.css'),
615
616             // same sub directories in different base directories
617             array('../../puli/css/style.css', '/webmozart/css', '/puli/css/style.css'),
618
619             array('', '/webmozart/puli', '/webmozart/puli'),
620             array('..', '/webmozart/puli', '/webmozart'),
621         );
622     }
623
624     public function provideMakeAbsoluteTests()
625     {
626         return array_merge($this->providePathTests(), array(
627             // collapse dots
628             array('css/./style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'),
629             array('css/../style.css', '/webmozart/puli', '/webmozart/puli/style.css'),
630             array('css/./../style.css', '/webmozart/puli', '/webmozart/puli/style.css'),
631             array('css/.././style.css', '/webmozart/puli', '/webmozart/puli/style.css'),
632             array('./css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'),
633
634             array('css\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'),
635             array('css\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'),
636             array('css\\.\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'),
637             array('css\\..\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'),
638             array('.\\css\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'),
639
640             // collapse dots on root
641             array('./css/style.css', '/', '/css/style.css'),
642             array('../css/style.css', '/', '/css/style.css'),
643             array('../css/./style.css', '/', '/css/style.css'),
644             array('../css/../style.css', '/', '/style.css'),
645             array('../css/./../style.css', '/', '/style.css'),
646             array('../css/.././style.css', '/', '/style.css'),
647
648             array('.\\css\\style.css', '\\', '/css/style.css'),
649             array('..\\css\\style.css', '\\', '/css/style.css'),
650             array('..\\css\\.\\style.css', '\\', '/css/style.css'),
651             array('..\\css\\..\\style.css', '\\', '/style.css'),
652             array('..\\css\\.\\..\\style.css', '\\', '/style.css'),
653             array('..\\css\\..\\.\\style.css', '\\', '/style.css'),
654
655             array('./css/style.css', 'C:/', 'C:/css/style.css'),
656             array('../css/style.css', 'C:/', 'C:/css/style.css'),
657             array('../css/./style.css', 'C:/', 'C:/css/style.css'),
658             array('../css/../style.css', 'C:/', 'C:/style.css'),
659             array('../css/./../style.css', 'C:/', 'C:/style.css'),
660             array('../css/.././style.css', 'C:/', 'C:/style.css'),
661
662             array('.\\css\\style.css', 'C:\\', 'C:/css/style.css'),
663             array('..\\css\\style.css', 'C:\\', 'C:/css/style.css'),
664             array('..\\css\\.\\style.css', 'C:\\', 'C:/css/style.css'),
665             array('..\\css\\..\\style.css', 'C:\\', 'C:/style.css'),
666             array('..\\css\\.\\..\\style.css', 'C:\\', 'C:/style.css'),
667             array('..\\css\\..\\.\\style.css', 'C:\\', 'C:/style.css'),
668
669             array('./css/style.css', 'phar:///', 'phar:///css/style.css'),
670             array('../css/style.css', 'phar:///', 'phar:///css/style.css'),
671             array('../css/./style.css', 'phar:///', 'phar:///css/style.css'),
672             array('../css/../style.css', 'phar:///', 'phar:///style.css'),
673             array('../css/./../style.css', 'phar:///', 'phar:///style.css'),
674             array('../css/.././style.css', 'phar:///', 'phar:///style.css'),
675
676             array('./css/style.css', 'phar://C:/', 'phar://C:/css/style.css'),
677             array('../css/style.css', 'phar://C:/', 'phar://C:/css/style.css'),
678             array('../css/./style.css', 'phar://C:/', 'phar://C:/css/style.css'),
679             array('../css/../style.css', 'phar://C:/', 'phar://C:/style.css'),
680             array('../css/./../style.css', 'phar://C:/', 'phar://C:/style.css'),
681             array('../css/.././style.css', 'phar://C:/', 'phar://C:/style.css'),
682
683             // absolute paths
684             array('/css/style.css', '/webmozart/puli', '/css/style.css'),
685             array('\\css\\style.css', '/webmozart/puli', '/css/style.css'),
686             array('C:/css/style.css', 'C:/webmozart/puli', 'C:/css/style.css'),
687             array('D:\\css\\style.css', 'D:/webmozart/puli', 'D:/css/style.css'),
688         ));
689     }
690
691     /**
692      * @dataProvider provideMakeAbsoluteTests
693      */
694     public function testMakeAbsolute($relativePath, $basePath, $absolutePath)
695     {
696         $this->assertSame($absolutePath, Path::makeAbsolute($relativePath, $basePath));
697     }
698
699     /**
700      * @expectedException \InvalidArgumentException
701      * @expectedExceptionMessage The path must be a string. Got: array
702      */
703     public function testMakeAbsoluteFailsIfInvalidPath()
704     {
705         Path::makeAbsolute(array(), '/webmozart/puli');
706     }
707
708     /**
709      * @expectedException \InvalidArgumentException
710      * @expectedExceptionMessage The base path must be a non-empty string. Got: array
711      */
712     public function testMakeAbsoluteFailsIfInvalidBasePath()
713     {
714         Path::makeAbsolute('css/style.css', array());
715     }
716
717     /**
718      * @expectedException \InvalidArgumentException
719      * @expectedExceptionMessage The base path "webmozart/puli" is not an absolute path.
720      */
721     public function testMakeAbsoluteFailsIfBasePathNotAbsolute()
722     {
723         Path::makeAbsolute('css/style.css', 'webmozart/puli');
724     }
725
726     /**
727      * @expectedException \InvalidArgumentException
728      * @expectedExceptionMessage The base path must be a non-empty string. Got: ""
729      */
730     public function testMakeAbsoluteFailsIfBasePathEmpty()
731     {
732         Path::makeAbsolute('css/style.css', '');
733     }
734
735     /**
736      * @expectedException \InvalidArgumentException
737      * @expectedExceptionMessage The base path must be a non-empty string. Got: NULL
738      */
739     public function testMakeAbsoluteFailsIfBasePathNull()
740     {
741         Path::makeAbsolute('css/style.css', null);
742     }
743
744     public function provideAbsolutePathsWithDifferentRoots()
745     {
746         return array(
747             array('C:/css/style.css', '/webmozart/puli'),
748             array('C:/css/style.css', '\\webmozart\\puli'),
749             array('C:\\css\\style.css', '/webmozart/puli'),
750             array('C:\\css\\style.css', '\\webmozart\\puli'),
751
752             array('/css/style.css', 'C:/webmozart/puli'),
753             array('/css/style.css', 'C:\\webmozart\\puli'),
754             array('\\css\\style.css', 'C:/webmozart/puli'),
755             array('\\css\\style.css', 'C:\\webmozart\\puli'),
756
757             array('D:/css/style.css', 'C:/webmozart/puli'),
758             array('D:/css/style.css', 'C:\\webmozart\\puli'),
759             array('D:\\css\\style.css', 'C:/webmozart/puli'),
760             array('D:\\css\\style.css', 'C:\\webmozart\\puli'),
761
762             array('phar:///css/style.css', '/webmozart/puli'),
763             array('/css/style.css', 'phar:///webmozart/puli'),
764
765             array('phar://C:/css/style.css', 'C:/webmozart/puli'),
766             array('phar://C:/css/style.css', 'C:\\webmozart\\puli'),
767             array('phar://C:\\css\\style.css', 'C:/webmozart/puli'),
768             array('phar://C:\\css\\style.css', 'C:\\webmozart\\puli'),
769         );
770     }
771
772     /**
773      * @dataProvider provideAbsolutePathsWithDifferentRoots
774      */
775     public function testMakeAbsoluteDoesNotFailIfDifferentRoot($basePath, $absolutePath)
776     {
777         // If a path in partition D: is passed, but $basePath is in partition
778         // C:, the path should be returned unchanged
779         $this->assertSame(Path::canonicalize($absolutePath), Path::makeAbsolute($absolutePath, $basePath));
780     }
781
782     public function provideMakeRelativeTests()
783     {
784         $paths = array_map(function (array $arguments) {
785             return array($arguments[2], $arguments[1], $arguments[0]);
786         }, $this->providePathTests());
787
788         return array_merge($paths, array(
789             array('/webmozart/puli/./css/style.css', '/webmozart/puli', 'css/style.css'),
790             array('/webmozart/puli/../css/style.css', '/webmozart/puli', '../css/style.css'),
791             array('/webmozart/puli/.././css/style.css', '/webmozart/puli', '../css/style.css'),
792             array('/webmozart/puli/./../css/style.css', '/webmozart/puli', '../css/style.css'),
793             array('/webmozart/puli/../../css/style.css', '/webmozart/puli', '../../css/style.css'),
794             array('/webmozart/puli/css/style.css', '/webmozart/./puli', 'css/style.css'),
795             array('/webmozart/puli/css/style.css', '/webmozart/../puli', '../webmozart/puli/css/style.css'),
796             array('/webmozart/puli/css/style.css', '/webmozart/./../puli', '../webmozart/puli/css/style.css'),
797             array('/webmozart/puli/css/style.css', '/webmozart/.././puli', '../webmozart/puli/css/style.css'),
798             array('/webmozart/puli/css/style.css', '/webmozart/../../puli', '../webmozart/puli/css/style.css'),
799
800             // first argument shorter than second
801             array('/css', '/webmozart/puli', '../../css'),
802
803             // second argument shorter than first
804             array('/webmozart/puli', '/css', '../webmozart/puli'),
805
806             array('\\webmozart\\puli\\css\\style.css', '\\webmozart\\puli', 'css/style.css'),
807             array('\\webmozart\\css\\style.css', '\\webmozart\\puli', '../css/style.css'),
808             array('\\css\\style.css', '\\webmozart\\puli', '../../css/style.css'),
809
810             array('C:/webmozart/puli/css/style.css', 'C:/webmozart/puli', 'css/style.css'),
811             array('C:/webmozart/css/style.css', 'C:/webmozart/puli', '../css/style.css'),
812             array('C:/css/style.css', 'C:/webmozart/puli', '../../css/style.css'),
813
814             array('C:\\webmozart\\puli\\css\\style.css', 'C:\\webmozart\\puli', 'css/style.css'),
815             array('C:\\webmozart\\css\\style.css', 'C:\\webmozart\\puli', '../css/style.css'),
816             array('C:\\css\\style.css', 'C:\\webmozart\\puli', '../../css/style.css'),
817
818             array('phar:///webmozart/puli/css/style.css', 'phar:///webmozart/puli', 'css/style.css'),
819             array('phar:///webmozart/css/style.css', 'phar:///webmozart/puli', '../css/style.css'),
820             array('phar:///css/style.css', 'phar:///webmozart/puli', '../../css/style.css'),
821
822             array('phar://C:/webmozart/puli/css/style.css', 'phar://C:/webmozart/puli', 'css/style.css'),
823             array('phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/puli', '../css/style.css'),
824             array('phar://C:/css/style.css', 'phar://C:/webmozart/puli', '../../css/style.css'),
825
826             // already relative + already in root basepath
827             array('../style.css', '/', 'style.css'),
828             array('./style.css', '/', 'style.css'),
829             array('../../style.css', '/', 'style.css'),
830             array('..\\style.css', 'C:\\', 'style.css'),
831             array('.\\style.css', 'C:\\', 'style.css'),
832             array('..\\..\\style.css', 'C:\\', 'style.css'),
833             array('../style.css', 'C:/', 'style.css'),
834             array('./style.css', 'C:/', 'style.css'),
835             array('../../style.css', 'C:/', 'style.css'),
836             array('..\\style.css', '\\', 'style.css'),
837             array('.\\style.css', '\\', 'style.css'),
838             array('..\\..\\style.css', '\\', 'style.css'),
839             array('../style.css', 'phar:///', 'style.css'),
840             array('./style.css', 'phar:///', 'style.css'),
841             array('../../style.css', 'phar:///', 'style.css'),
842             array('..\\style.css', 'phar://C:\\', 'style.css'),
843             array('.\\style.css', 'phar://C:\\', 'style.css'),
844             array('..\\..\\style.css', 'phar://C:\\', 'style.css'),
845
846             array('css/../style.css', '/', 'style.css'),
847             array('css/./style.css', '/', 'css/style.css'),
848             array('css\\..\\style.css', 'C:\\', 'style.css'),
849             array('css\\.\\style.css', 'C:\\', 'css/style.css'),
850             array('css/../style.css', 'C:/', 'style.css'),
851             array('css/./style.css', 'C:/', 'css/style.css'),
852             array('css\\..\\style.css', '\\', 'style.css'),
853             array('css\\.\\style.css', '\\', 'css/style.css'),
854             array('css/../style.css', 'phar:///', 'style.css'),
855             array('css/./style.css', 'phar:///', 'css/style.css'),
856             array('css\\..\\style.css', 'phar://C:\\', 'style.css'),
857             array('css\\.\\style.css', 'phar://C:\\', 'css/style.css'),
858
859             // already relative
860             array('css/style.css', '/webmozart/puli', 'css/style.css'),
861             array('css\\style.css', '\\webmozart\\puli', 'css/style.css'),
862
863             // both relative
864             array('css/style.css', 'webmozart/puli', '../../css/style.css'),
865             array('css\\style.css', 'webmozart\\puli', '../../css/style.css'),
866
867             // relative to empty
868             array('css/style.css', '', 'css/style.css'),
869             array('css\\style.css', '', 'css/style.css'),
870
871             // different slashes in path and base path
872             array('/webmozart/puli/css/style.css', '\\webmozart\\puli', 'css/style.css'),
873             array('\\webmozart\\puli\\css\\style.css', '/webmozart/puli', 'css/style.css'),
874         ));
875     }
876
877     /**
878      * @dataProvider provideMakeRelativeTests
879      */
880     public function testMakeRelative($absolutePath, $basePath, $relativePath)
881     {
882         $this->assertSame($relativePath, Path::makeRelative($absolutePath, $basePath));
883     }
884
885     /**
886      * @expectedException \InvalidArgumentException
887      * @expectedExceptionMessage The path must be a string. Got: array
888      */
889     public function testMakeRelativeFailsIfInvalidPath()
890     {
891         Path::makeRelative(array(), '/webmozart/puli');
892     }
893
894     /**
895      * @expectedException \InvalidArgumentException
896      * @expectedExceptionMessage The base path must be a string. Got: array
897      */
898     public function testMakeRelativeFailsIfInvalidBasePath()
899     {
900         Path::makeRelative('/webmozart/puli/css/style.css', array());
901     }
902
903     /**
904      * @expectedException \InvalidArgumentException
905      * @expectedExceptionMessage 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.
906      */
907     public function testMakeRelativeFailsIfAbsolutePathAndBasePathNotAbsolute()
908     {
909         Path::makeRelative('/webmozart/puli/css/style.css', 'webmozart/puli');
910     }
911
912     /**
913      * @expectedException \InvalidArgumentException
914      * @expectedExceptionMessage The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead.
915      */
916     public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty()
917     {
918         Path::makeRelative('/webmozart/puli/css/style.css', '');
919     }
920
921     /**
922      * @expectedException \InvalidArgumentException
923      * @expectedExceptionMessage The base path must be a string. Got: NULL
924      */
925     public function testMakeRelativeFailsIfBasePathNull()
926     {
927         Path::makeRelative('/webmozart/puli/css/style.css', null);
928     }
929
930     /**
931      * @dataProvider provideAbsolutePathsWithDifferentRoots
932      * @expectedException \InvalidArgumentException
933      */
934     public function testMakeRelativeFailsIfDifferentRoot($absolutePath, $basePath)
935     {
936         Path::makeRelative($absolutePath, $basePath);
937     }
938
939     public function provideIsLocalTests()
940     {
941         return array(
942             array('/bg.png', true),
943             array('bg.png', true),
944             array('http://example.com/bg.png', false),
945             array('http://example.com', false),
946             array('', false),
947         );
948     }
949
950     /**
951      * @dataProvider provideIsLocalTests
952      */
953     public function testIsLocal($path, $isLocal)
954     {
955         $this->assertSame($isLocal, Path::isLocal($path));
956     }
957
958     /**
959      * @expectedException \InvalidArgumentException
960      * @expectedExceptionMessage The path must be a string. Got: array
961      */
962     public function testIsLocalFailsIfInvalidPath()
963     {
964         Path::isLocal(array());
965     }
966
967     public function provideGetLongestCommonBasePathTests()
968     {
969         return array(
970             // same paths
971             array(array('/base/path', '/base/path'), '/base/path'),
972             array(array('C:/base/path', 'C:/base/path'), 'C:/base/path'),
973             array(array('C:\\base\\path', 'C:\\base\\path'), 'C:/base/path'),
974             array(array('C:/base/path', 'C:\\base\\path'), 'C:/base/path'),
975             array(array('phar:///base/path', 'phar:///base/path'), 'phar:///base/path'),
976             array(array('phar://C:/base/path', 'phar://C:/base/path'), 'phar://C:/base/path'),
977
978             // trailing slash
979             array(array('/base/path/', '/base/path'), '/base/path'),
980             array(array('C:/base/path/', 'C:/base/path'), 'C:/base/path'),
981             array(array('C:\\base\\path\\', 'C:\\base\\path'), 'C:/base/path'),
982             array(array('C:/base/path/', 'C:\\base\\path'), 'C:/base/path'),
983             array(array('phar:///base/path/', 'phar:///base/path'), 'phar:///base/path'),
984             array(array('phar://C:/base/path/', 'phar://C:/base/path'), 'phar://C:/base/path'),
985
986             array(array('/base/path', '/base/path/'), '/base/path'),
987             array(array('C:/base/path', 'C:/base/path/'), 'C:/base/path'),
988             array(array('C:\\base\\path', 'C:\\base\\path\\'), 'C:/base/path'),
989             array(array('C:/base/path', 'C:\\base\\path\\'), 'C:/base/path'),
990             array(array('phar:///base/path', 'phar:///base/path/'), 'phar:///base/path'),
991             array(array('phar://C:/base/path', 'phar://C:/base/path/'), 'phar://C:/base/path'),
992
993             // first in second
994             array(array('/base/path/sub', '/base/path'), '/base/path'),
995             array(array('C:/base/path/sub', 'C:/base/path'), 'C:/base/path'),
996             array(array('C:\\base\\path\\sub', 'C:\\base\\path'), 'C:/base/path'),
997             array(array('C:/base/path/sub', 'C:\\base\\path'), 'C:/base/path'),
998             array(array('phar:///base/path/sub', 'phar:///base/path'), 'phar:///base/path'),
999             array(array('phar://C:/base/path/sub', 'phar://C:/base/path'), 'phar://C:/base/path'),
1000
1001             // second in first
1002             array(array('/base/path', '/base/path/sub'), '/base/path'),
1003             array(array('C:/base/path', 'C:/base/path/sub'), 'C:/base/path'),
1004             array(array('C:\\base\\path', 'C:\\base\\path\\sub'), 'C:/base/path'),
1005             array(array('C:/base/path', 'C:\\base\\path\\sub'), 'C:/base/path'),
1006             array(array('phar:///base/path', 'phar:///base/path/sub'), 'phar:///base/path'),
1007             array(array('phar://C:/base/path', 'phar://C:/base/path/sub'), 'phar://C:/base/path'),
1008
1009             // first is prefix
1010             array(array('/base/path/di', '/base/path/dir'), '/base/path'),
1011             array(array('C:/base/path/di', 'C:/base/path/dir'), 'C:/base/path'),
1012             array(array('C:\\base\\path\\di', 'C:\\base\\path\\dir'), 'C:/base/path'),
1013             array(array('C:/base/path/di', 'C:\\base\\path\\dir'), 'C:/base/path'),
1014             array(array('phar:///base/path/di', 'phar:///base/path/dir'), 'phar:///base/path'),
1015             array(array('phar://C:/base/path/di', 'phar://C:/base/path/dir'), 'phar://C:/base/path'),
1016
1017             // second is prefix
1018             array(array('/base/path/dir', '/base/path/di'), '/base/path'),
1019             array(array('C:/base/path/dir', 'C:/base/path/di'), 'C:/base/path'),
1020             array(array('C:\\base\\path\\dir', 'C:\\base\\path\\di'), 'C:/base/path'),
1021             array(array('C:/base/path/dir', 'C:\\base\\path\\di'), 'C:/base/path'),
1022             array(array('phar:///base/path/dir', 'phar:///base/path/di'), 'phar:///base/path'),
1023             array(array('phar://C:/base/path/dir', 'phar://C:/base/path/di'), 'phar://C:/base/path'),
1024
1025             // root is common base path
1026             array(array('/first', '/second'), '/'),
1027             array(array('C:/first', 'C:/second'), 'C:/'),
1028             array(array('C:\\first', 'C:\\second'), 'C:/'),
1029             array(array('C:/first', 'C:\\second'), 'C:/'),
1030             array(array('phar:///first', 'phar:///second'), 'phar:///'),
1031             array(array('phar://C:/first', 'phar://C:/second'), 'phar://C:/'),
1032
1033             // windows vs unix
1034             array(array('/base/path', 'C:/base/path'), null),
1035             array(array('C:/base/path', '/base/path'), null),
1036             array(array('/base/path', 'C:\\base\\path'), null),
1037             array(array('phar:///base/path', 'phar://C:/base/path'), null),
1038
1039             // different partitions
1040             array(array('C:/base/path', 'D:/base/path'), null),
1041             array(array('C:/base/path', 'D:\\base\\path'), null),
1042             array(array('C:\\base\\path', 'D:\\base\\path'), null),
1043             array(array('phar://C:/base/path', 'phar://D:/base/path'), null),
1044
1045             // three paths
1046             array(array('/base/path/foo', '/base/path', '/base/path/bar'), '/base/path'),
1047             array(array('C:/base/path/foo', 'C:/base/path', 'C:/base/path/bar'), 'C:/base/path'),
1048             array(array('C:\\base\\path\\foo', 'C:\\base\\path', 'C:\\base\\path\\bar'), 'C:/base/path'),
1049             array(array('C:/base/path//foo', 'C:/base/path', 'C:\\base\\path\\bar'), 'C:/base/path'),
1050             array(array('phar:///base/path/foo', 'phar:///base/path', 'phar:///base/path/bar'), 'phar:///base/path'),
1051             array(array('phar://C:/base/path/foo', 'phar://C:/base/path', 'phar://C:/base/path/bar'), 'phar://C:/base/path'),
1052
1053             // three paths with root
1054             array(array('/base/path/foo', '/', '/base/path/bar'), '/'),
1055             array(array('C:/base/path/foo', 'C:/', 'C:/base/path/bar'), 'C:/'),
1056             array(array('C:\\base\\path\\foo', 'C:\\', 'C:\\base\\path\\bar'), 'C:/'),
1057             array(array('C:/base/path//foo', 'C:/', 'C:\\base\\path\\bar'), 'C:/'),
1058             array(array('phar:///base/path/foo', 'phar:///', 'phar:///base/path/bar'), 'phar:///'),
1059             array(array('phar://C:/base/path/foo', 'phar://C:/', 'phar://C:/base/path/bar'), 'phar://C:/'),
1060
1061             // three paths, different roots
1062             array(array('/base/path/foo', 'C:/base/path', '/base/path/bar'), null),
1063             array(array('/base/path/foo', 'C:\\base\\path', '/base/path/bar'), null),
1064             array(array('C:/base/path/foo', 'D:/base/path', 'C:/base/path/bar'), null),
1065             array(array('C:\\base\\path\\foo', 'D:\\base\\path', 'C:\\base\\path\\bar'), null),
1066             array(array('C:/base/path//foo', 'D:/base/path', 'C:\\base\\path\\bar'), null),
1067             array(array('phar:///base/path/foo', 'phar://C:/base/path', 'phar:///base/path/bar'), null),
1068             array(array('phar://C:/base/path/foo', 'phar://D:/base/path', 'phar://C:/base/path/bar'), null),
1069
1070             // only one path
1071             array(array('/base/path'), '/base/path'),
1072             array(array('C:/base/path'), 'C:/base/path'),
1073             array(array('C:\\base\\path'), 'C:/base/path'),
1074             array(array('phar:///base/path'), 'phar:///base/path'),
1075             array(array('phar://C:/base/path'), 'phar://C:/base/path'),
1076         );
1077     }
1078
1079     /**
1080      * @dataProvider provideGetLongestCommonBasePathTests
1081      */
1082     public function testGetLongestCommonBasePath(array $paths, $basePath)
1083     {
1084         $this->assertSame($basePath, Path::getLongestCommonBasePath($paths));
1085     }
1086
1087     /**
1088      * @expectedException \InvalidArgumentException
1089      * @expectedExceptionMessage The paths must be strings. Got: array
1090      */
1091     public function testGetLongestCommonBasePathFailsIfInvalidPath()
1092     {
1093         Path::getLongestCommonBasePath(array(array()));
1094     }
1095
1096     public function provideIsBasePathTests()
1097     {
1098         return array(
1099             // same paths
1100             array('/base/path', '/base/path', true),
1101             array('C:/base/path', 'C:/base/path', true),
1102             array('C:\\base\\path', 'C:\\base\\path', true),
1103             array('C:/base/path', 'C:\\base\\path', true),
1104             array('phar:///base/path', 'phar:///base/path', true),
1105             array('phar://C:/base/path', 'phar://C:/base/path', true),
1106
1107             // trailing slash
1108             array('/base/path/', '/base/path', true),
1109             array('C:/base/path/', 'C:/base/path', true),
1110             array('C:\\base\\path\\', 'C:\\base\\path', true),
1111             array('C:/base/path/', 'C:\\base\\path', true),
1112             array('phar:///base/path/', 'phar:///base/path', true),
1113             array('phar://C:/base/path/', 'phar://C:/base/path', true),
1114
1115             array('/base/path', '/base/path/', true),
1116             array('C:/base/path', 'C:/base/path/', true),
1117             array('C:\\base\\path', 'C:\\base\\path\\', true),
1118             array('C:/base/path', 'C:\\base\\path\\', true),
1119             array('phar:///base/path', 'phar:///base/path/', true),
1120             array('phar://C:/base/path', 'phar://C:/base/path/', true),
1121
1122             // first in second
1123             array('/base/path/sub', '/base/path', false),
1124             array('C:/base/path/sub', 'C:/base/path', false),
1125             array('C:\\base\\path\\sub', 'C:\\base\\path', false),
1126             array('C:/base/path/sub', 'C:\\base\\path', false),
1127             array('phar:///base/path/sub', 'phar:///base/path', false),
1128             array('phar://C:/base/path/sub', 'phar://C:/base/path', false),
1129
1130             // second in first
1131             array('/base/path', '/base/path/sub', true),
1132             array('C:/base/path', 'C:/base/path/sub', true),
1133             array('C:\\base\\path', 'C:\\base\\path\\sub', true),
1134             array('C:/base/path', 'C:\\base\\path\\sub', true),
1135             array('phar:///base/path', 'phar:///base/path/sub', true),
1136             array('phar://C:/base/path', 'phar://C:/base/path/sub', true),
1137
1138             // first is prefix
1139             array('/base/path/di', '/base/path/dir', false),
1140             array('C:/base/path/di', 'C:/base/path/dir', false),
1141             array('C:\\base\\path\\di', 'C:\\base\\path\\dir', false),
1142             array('C:/base/path/di', 'C:\\base\\path\\dir', false),
1143             array('phar:///base/path/di', 'phar:///base/path/dir', false),
1144             array('phar://C:/base/path/di', 'phar://C:/base/path/dir', false),
1145
1146             // second is prefix
1147             array('/base/path/dir', '/base/path/di', false),
1148             array('C:/base/path/dir', 'C:/base/path/di', false),
1149             array('C:\\base\\path\\dir', 'C:\\base\\path\\di', false),
1150             array('C:/base/path/dir', 'C:\\base\\path\\di', false),
1151             array('phar:///base/path/dir', 'phar:///base/path/di', false),
1152             array('phar://C:/base/path/dir', 'phar://C:/base/path/di', false),
1153
1154             // root
1155             array('/', '/second', true),
1156             array('C:/', 'C:/second', true),
1157             array('C:', 'C:/second', true),
1158             array('C:\\', 'C:\\second', true),
1159             array('C:/', 'C:\\second', true),
1160             array('phar:///', 'phar:///second', true),
1161             array('phar://C:/', 'phar://C:/second', true),
1162
1163             // windows vs unix
1164             array('/base/path', 'C:/base/path', false),
1165             array('C:/base/path', '/base/path', false),
1166             array('/base/path', 'C:\\base\\path', false),
1167             array('/base/path', 'phar:///base/path', false),
1168             array('phar:///base/path', 'phar://C:/base/path', false),
1169
1170             // different partitions
1171             array('C:/base/path', 'D:/base/path', false),
1172             array('C:/base/path', 'D:\\base\\path', false),
1173             array('C:\\base\\path', 'D:\\base\\path', false),
1174             array('C:/base/path', 'phar://C:/base/path', false),
1175             array('phar://C:/base/path', 'phar://D:/base/path', false),
1176         );
1177     }
1178
1179     /**
1180      * @dataProvider provideIsBasePathTests
1181      */
1182     public function testIsBasePath($path, $ofPath, $result)
1183     {
1184         $this->assertSame($result, Path::isBasePath($path, $ofPath));
1185     }
1186
1187     /**
1188      * @expectedException \InvalidArgumentException
1189      * @expectedExceptionMessage The base path must be a string. Got: array
1190      */
1191     public function testIsBasePathFailsIfInvalidBasePath()
1192     {
1193         Path::isBasePath(array(), '/base/path');
1194     }
1195
1196     /**
1197      * @expectedException \InvalidArgumentException
1198      * @expectedExceptionMessage The path must be a string. Got: array
1199      */
1200     public function testIsBasePathFailsIfInvalidPath()
1201     {
1202         Path::isBasePath('/base/path', array());
1203     }
1204
1205     public function provideJoinTests()
1206     {
1207         return array(
1208             array('', '', ''),
1209             array('/path/to/test', '', '/path/to/test'),
1210             array('/path/to//test', '', '/path/to/test'),
1211             array('', '/path/to/test', '/path/to/test'),
1212             array('', '/path/to//test', '/path/to/test'),
1213
1214             array('/path/to/test', 'subdir', '/path/to/test/subdir'),
1215             array('/path/to/test/', 'subdir', '/path/to/test/subdir'),
1216             array('/path/to/test', '/subdir', '/path/to/test/subdir'),
1217             array('/path/to/test/', '/subdir', '/path/to/test/subdir'),
1218             array('/path/to/test', './subdir', '/path/to/test/subdir'),
1219             array('/path/to/test/', './subdir', '/path/to/test/subdir'),
1220             array('/path/to/test/', '../parentdir', '/path/to/parentdir'),
1221             array('/path/to/test', '../parentdir', '/path/to/parentdir'),
1222             array('path/to/test/', '/subdir', 'path/to/test/subdir'),
1223             array('path/to/test', '/subdir', 'path/to/test/subdir'),
1224             array('../path/to/test', '/subdir', '../path/to/test/subdir'),
1225             array('path', '../../subdir', '../subdir'),
1226             array('/path', '../../subdir', '/subdir'),
1227             array('../path', '../../subdir', '../../subdir'),
1228
1229             array(array('/path/to/test', 'subdir'), '', '/path/to/test/subdir'),
1230             array(array('/path/to/test', '/subdir'), '', '/path/to/test/subdir'),
1231             array(array('/path/to/test/', 'subdir'), '', '/path/to/test/subdir'),
1232             array(array('/path/to/test/', '/subdir'), '', '/path/to/test/subdir'),
1233
1234             array(array('/path'), '', '/path'),
1235             array(array('/path', 'to', '/test'), '', '/path/to/test'),
1236             array(array('/path', '', '/test'), '', '/path/test'),
1237             array(array('path', 'to', 'test'), '', 'path/to/test'),
1238             array(array(), '', ''),
1239
1240             array('base/path', 'to/test', 'base/path/to/test'),
1241
1242             array('C:\\path\\to\\test', 'subdir', 'C:/path/to/test/subdir'),
1243             array('C:\\path\\to\\test\\', 'subdir', 'C:/path/to/test/subdir'),
1244             array('C:\\path\\to\\test', '/subdir', 'C:/path/to/test/subdir'),
1245             array('C:\\path\\to\\test\\', '/subdir', 'C:/path/to/test/subdir'),
1246
1247             array('/', 'subdir', '/subdir'),
1248             array('/', '/subdir', '/subdir'),
1249             array('C:/', 'subdir', 'C:/subdir'),
1250             array('C:/', '/subdir', 'C:/subdir'),
1251             array('C:\\', 'subdir', 'C:/subdir'),
1252             array('C:\\', '/subdir', 'C:/subdir'),
1253             array('C:', 'subdir', 'C:/subdir'),
1254             array('C:', '/subdir', 'C:/subdir'),
1255
1256             array('phar://', '/path/to/test', 'phar:///path/to/test'),
1257             array('phar:///', '/path/to/test', 'phar:///path/to/test'),
1258             array('phar:///path/to/test', 'subdir', 'phar:///path/to/test/subdir'),
1259             array('phar:///path/to/test', 'subdir/', 'phar:///path/to/test/subdir'),
1260             array('phar:///path/to/test', '/subdir', 'phar:///path/to/test/subdir'),
1261             array('phar:///path/to/test/', 'subdir', 'phar:///path/to/test/subdir'),
1262             array('phar:///path/to/test/', '/subdir', 'phar:///path/to/test/subdir'),
1263
1264             array('phar://', 'C:/path/to/test', 'phar://C:/path/to/test'),
1265             array('phar://', 'C:\\path\\to\\test', 'phar://C:/path/to/test'),
1266             array('phar://C:/path/to/test', 'subdir', 'phar://C:/path/to/test/subdir'),
1267             array('phar://C:/path/to/test', 'subdir/', 'phar://C:/path/to/test/subdir'),
1268             array('phar://C:/path/to/test', '/subdir', 'phar://C:/path/to/test/subdir'),
1269             array('phar://C:/path/to/test/', 'subdir', 'phar://C:/path/to/test/subdir'),
1270             array('phar://C:/path/to/test/', '/subdir', 'phar://C:/path/to/test/subdir'),
1271             array('phar://C:', 'path/to/test', 'phar://C:/path/to/test'),
1272             array('phar://C:', '/path/to/test', 'phar://C:/path/to/test'),
1273             array('phar://C:/', 'path/to/test', 'phar://C:/path/to/test'),
1274             array('phar://C:/', '/path/to/test', 'phar://C:/path/to/test'),
1275         );
1276     }
1277
1278     /**
1279      * @dataProvider provideJoinTests
1280      */
1281     public function testJoin($path1, $path2, $result)
1282     {
1283         $this->assertSame($result, Path::join($path1, $path2));
1284     }
1285
1286     public function testJoinVarArgs()
1287     {
1288         $this->assertSame('/path', Path::join('/path'));
1289         $this->assertSame('/path/to', Path::join('/path', 'to'));
1290         $this->assertSame('/path/to/test', Path::join('/path', 'to', '/test'));
1291         $this->assertSame('/path/to/test/subdir', Path::join('/path', 'to', '/test', 'subdir/'));
1292     }
1293
1294     /**
1295      * @expectedException \InvalidArgumentException
1296      * @expectedExceptionMessage The paths must be strings. Got: array
1297      */
1298     public function testJoinFailsIfInvalidPath()
1299     {
1300         Path::join('/path', array());
1301     }
1302
1303     /**
1304      * @expectedException \RuntimeException
1305      * @expectedExceptionMessage Your environment or operation system isn't supported
1306      */
1307     public function testGetHomeDirectoryFailsIfNotSupportedOperationSystem()
1308     {
1309         putenv('HOME=');
1310
1311         Path::getHomeDirectory();
1312     }
1313
1314     public function testGetHomeDirectoryForUnix()
1315     {
1316         $this->assertEquals('/home/webmozart', Path::getHomeDirectory());
1317     }
1318
1319     public function testGetHomeDirectoryForWindows()
1320     {
1321         putenv('HOME=');
1322         putenv('HOMEDRIVE=C:');
1323         putenv('HOMEPATH=/users/webmozart');
1324
1325         $this->assertEquals('C:/users/webmozart', Path::getHomeDirectory());
1326     }
1327
1328     public function testNormalize()
1329     {
1330         $this->assertSame('C:/Foo/Bar/test', Path::normalize('C:\\Foo\\Bar/test'));
1331     }
1332
1333     /**
1334      * @expectedException \InvalidArgumentException
1335      */
1336     public function testNormalizeFailsIfNoString()
1337     {
1338         Path::normalize(true);
1339     }
1340 }