/src/Symfony/Component/Filesystem/Tests/PathTest.php

https://github.com/stof/symfony · PHP · 1055 lines · 782 code · 154 blank · 119 comment · 0 complexity · 7e5da8bd6908624f1b4e1c34d12cd37c MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Filesystem\Tests;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Filesystem\Path;
  13. /**
  14. * @author Bernhard Schussek <bschussek@gmail.com>
  15. * @author Thomas Schulz <mail@king2500.net>
  16. * @author Théo Fidry <theo.fidry@gmail.com>
  17. */
  18. class PathTest extends TestCase
  19. {
  20. protected $storedEnv = [];
  21. protected function setUp(): void
  22. {
  23. $this->storedEnv['HOME'] = getenv('HOME');
  24. $this->storedEnv['HOMEDRIVE'] = getenv('HOMEDRIVE');
  25. $this->storedEnv['HOMEPATH'] = getenv('HOMEPATH');
  26. putenv('HOME=/home/webmozart');
  27. putenv('HOMEDRIVE=');
  28. putenv('HOMEPATH=');
  29. }
  30. protected function tearDown(): void
  31. {
  32. putenv('HOME='.$this->storedEnv['HOME']);
  33. putenv('HOMEDRIVE='.$this->storedEnv['HOMEDRIVE']);
  34. putenv('HOMEPATH='.$this->storedEnv['HOMEPATH']);
  35. }
  36. public function provideCanonicalizationTests(): \Generator
  37. {
  38. // relative paths (forward slash)
  39. yield ['css/./style.css', 'css/style.css'];
  40. yield ['css/../style.css', 'style.css'];
  41. yield ['css/./../style.css', 'style.css'];
  42. yield ['css/.././style.css', 'style.css'];
  43. yield ['css/../../style.css', '../style.css'];
  44. yield ['./css/style.css', 'css/style.css'];
  45. yield ['../css/style.css', '../css/style.css'];
  46. yield ['./../css/style.css', '../css/style.css'];
  47. yield ['.././css/style.css', '../css/style.css'];
  48. yield ['../../css/style.css', '../../css/style.css'];
  49. yield ['', ''];
  50. yield ['.', ''];
  51. yield ['..', '..'];
  52. yield ['./..', '..'];
  53. yield ['../.', '..'];
  54. yield ['../..', '../..'];
  55. // relative paths (backslash)
  56. yield ['css\\.\\style.css', 'css/style.css'];
  57. yield ['css\\..\\style.css', 'style.css'];
  58. yield ['css\\.\\..\\style.css', 'style.css'];
  59. yield ['css\\..\\.\\style.css', 'style.css'];
  60. yield ['css\\..\\..\\style.css', '../style.css'];
  61. yield ['.\\css\\style.css', 'css/style.css'];
  62. yield ['..\\css\\style.css', '../css/style.css'];
  63. yield ['.\\..\\css\\style.css', '../css/style.css'];
  64. yield ['..\\.\\css\\style.css', '../css/style.css'];
  65. yield ['..\\..\\css\\style.css', '../../css/style.css'];
  66. // absolute paths (forward slash, UNIX)
  67. yield ['/css/style.css', '/css/style.css'];
  68. yield ['/css/./style.css', '/css/style.css'];
  69. yield ['/css/../style.css', '/style.css'];
  70. yield ['/css/./../style.css', '/style.css'];
  71. yield ['/css/.././style.css', '/style.css'];
  72. yield ['/./css/style.css', '/css/style.css'];
  73. yield ['/../css/style.css', '/css/style.css'];
  74. yield ['/./../css/style.css', '/css/style.css'];
  75. yield ['/.././css/style.css', '/css/style.css'];
  76. yield ['/../../css/style.css', '/css/style.css'];
  77. // absolute paths (backslash, UNIX)
  78. yield ['\\css\\style.css', '/css/style.css'];
  79. yield ['\\css\\.\\style.css', '/css/style.css'];
  80. yield ['\\css\\..\\style.css', '/style.css'];
  81. yield ['\\css\\.\\..\\style.css', '/style.css'];
  82. yield ['\\css\\..\\.\\style.css', '/style.css'];
  83. yield ['\\.\\css\\style.css', '/css/style.css'];
  84. yield ['\\..\\css\\style.css', '/css/style.css'];
  85. yield ['\\.\\..\\css\\style.css', '/css/style.css'];
  86. yield ['\\..\\.\\css\\style.css', '/css/style.css'];
  87. yield ['\\..\\..\\css\\style.css', '/css/style.css'];
  88. // absolute paths (forward slash, Windows)
  89. yield ['C:/css/style.css', 'C:/css/style.css'];
  90. yield ['C:/css/./style.css', 'C:/css/style.css'];
  91. yield ['C:/css/../style.css', 'C:/style.css'];
  92. yield ['C:/css/./../style.css', 'C:/style.css'];
  93. yield ['C:/css/.././style.css', 'C:/style.css'];
  94. yield ['C:/./css/style.css', 'C:/css/style.css'];
  95. yield ['C:/../css/style.css', 'C:/css/style.css'];
  96. yield ['C:/./../css/style.css', 'C:/css/style.css'];
  97. yield ['C:/.././css/style.css', 'C:/css/style.css'];
  98. yield ['C:/../../css/style.css', 'C:/css/style.css'];
  99. // absolute paths (backslash, Windows)
  100. yield ['C:\\css\\style.css', 'C:/css/style.css'];
  101. yield ['C:\\css\\.\\style.css', 'C:/css/style.css'];
  102. yield ['C:\\css\\..\\style.css', 'C:/style.css'];
  103. yield ['C:\\css\\.\\..\\style.css', 'C:/style.css'];
  104. yield ['C:\\css\\..\\.\\style.css', 'C:/style.css'];
  105. yield ['C:\\.\\css\\style.css', 'C:/css/style.css'];
  106. yield ['C:\\..\\css\\style.css', 'C:/css/style.css'];
  107. yield ['C:\\.\\..\\css\\style.css', 'C:/css/style.css'];
  108. yield ['C:\\..\\.\\css\\style.css', 'C:/css/style.css'];
  109. yield ['C:\\..\\..\\css\\style.css', 'C:/css/style.css'];
  110. // Windows special case
  111. yield ['C:', 'C:/'];
  112. // Don't change malformed path
  113. yield ['C:css/style.css', 'C:css/style.css'];
  114. // absolute paths (stream, UNIX)
  115. yield ['phar:///css/style.css', 'phar:///css/style.css'];
  116. yield ['phar:///css/./style.css', 'phar:///css/style.css'];
  117. yield ['phar:///css/../style.css', 'phar:///style.css'];
  118. yield ['phar:///css/./../style.css', 'phar:///style.css'];
  119. yield ['phar:///css/.././style.css', 'phar:///style.css'];
  120. yield ['phar:///./css/style.css', 'phar:///css/style.css'];
  121. yield ['phar:///../css/style.css', 'phar:///css/style.css'];
  122. yield ['phar:///./../css/style.css', 'phar:///css/style.css'];
  123. yield ['phar:///.././css/style.css', 'phar:///css/style.css'];
  124. yield ['phar:///../../css/style.css', 'phar:///css/style.css'];
  125. // absolute paths (stream, Windows)
  126. yield ['phar://C:/css/style.css', 'phar://C:/css/style.css'];
  127. yield ['phar://C:/css/./style.css', 'phar://C:/css/style.css'];
  128. yield ['phar://C:/css/../style.css', 'phar://C:/style.css'];
  129. yield ['phar://C:/css/./../style.css', 'phar://C:/style.css'];
  130. yield ['phar://C:/css/.././style.css', 'phar://C:/style.css'];
  131. yield ['phar://C:/./css/style.css', 'phar://C:/css/style.css'];
  132. yield ['phar://C:/../css/style.css', 'phar://C:/css/style.css'];
  133. yield ['phar://C:/./../css/style.css', 'phar://C:/css/style.css'];
  134. yield ['phar://C:/.././css/style.css', 'phar://C:/css/style.css'];
  135. yield ['phar://C:/../../css/style.css', 'phar://C:/css/style.css'];
  136. // paths with "~" UNIX
  137. yield ['~/css/style.css', '/home/webmozart/css/style.css'];
  138. yield ['~/css/./style.css', '/home/webmozart/css/style.css'];
  139. yield ['~/css/../style.css', '/home/webmozart/style.css'];
  140. yield ['~/css/./../style.css', '/home/webmozart/style.css'];
  141. yield ['~/css/.././style.css', '/home/webmozart/style.css'];
  142. yield ['~/./css/style.css', '/home/webmozart/css/style.css'];
  143. yield ['~/../css/style.css', '/home/css/style.css'];
  144. yield ['~/./../css/style.css', '/home/css/style.css'];
  145. yield ['~/.././css/style.css', '/home/css/style.css'];
  146. yield ['~/../../css/style.css', '/css/style.css'];
  147. }
  148. /**
  149. * @dataProvider provideCanonicalizationTests
  150. */
  151. public function testCanonicalize(string $path, string $canonicalized)
  152. {
  153. $this->assertSame($canonicalized, Path::canonicalize($path));
  154. }
  155. public function provideGetDirectoryTests(): \Generator
  156. {
  157. yield ['/webmozart/symfony/style.css', '/webmozart/symfony'];
  158. yield ['/webmozart/symfony', '/webmozart'];
  159. yield ['/webmozart', '/'];
  160. yield ['/', '/'];
  161. yield ['', ''];
  162. yield ['\\webmozart\\symfony\\style.css', '/webmozart/symfony'];
  163. yield ['\\webmozart\\symfony', '/webmozart'];
  164. yield ['\\webmozart', '/'];
  165. yield ['\\', '/'];
  166. yield ['C:/webmozart/symfony/style.css', 'C:/webmozart/symfony'];
  167. yield ['C:/webmozart/symfony', 'C:/webmozart'];
  168. yield ['C:/webmozart', 'C:/'];
  169. yield ['C:/', 'C:/'];
  170. yield ['C:', 'C:/'];
  171. yield ['C:\\webmozart\\symfony\\style.css', 'C:/webmozart/symfony'];
  172. yield ['C:\\webmozart\\symfony', 'C:/webmozart'];
  173. yield ['C:\\webmozart', 'C:/'];
  174. yield ['C:\\', 'C:/'];
  175. yield ['phar:///webmozart/symfony/style.css', 'phar:///webmozart/symfony'];
  176. yield ['phar:///webmozart/symfony', 'phar:///webmozart'];
  177. yield ['phar:///webmozart', 'phar:///'];
  178. yield ['phar:///', 'phar:///'];
  179. yield ['phar://C:/webmozart/symfony/style.css', 'phar://C:/webmozart/symfony'];
  180. yield ['phar://C:/webmozart/symfony', 'phar://C:/webmozart'];
  181. yield ['phar://C:/webmozart', 'phar://C:/'];
  182. yield ['phar://C:/', 'phar://C:/'];
  183. yield ['webmozart/symfony/style.css', 'webmozart/symfony'];
  184. yield ['webmozart/symfony', 'webmozart'];
  185. yield ['webmozart', ''];
  186. yield ['webmozart\\symfony\\style.css', 'webmozart/symfony'];
  187. yield ['webmozart\\symfony', 'webmozart'];
  188. yield ['webmozart', ''];
  189. yield ['/webmozart/./symfony/style.css', '/webmozart/symfony'];
  190. yield ['/webmozart/../symfony/style.css', '/symfony'];
  191. yield ['/webmozart/./../symfony/style.css', '/symfony'];
  192. yield ['/webmozart/.././symfony/style.css', '/symfony'];
  193. yield ['/webmozart/../../symfony/style.css', '/symfony'];
  194. yield ['/.', '/'];
  195. yield ['/..', '/'];
  196. yield ['C:webmozart', ''];
  197. }
  198. /**
  199. * @dataProvider provideGetDirectoryTests
  200. */
  201. public function testGetDirectory(string $path, string $directory)
  202. {
  203. $this->assertSame($directory, Path::getDirectory($path));
  204. }
  205. public function provideGetFilenameWithoutExtensionTests(): \Generator
  206. {
  207. yield ['/webmozart/symfony/style.css.twig', null, 'style.css'];
  208. yield ['/webmozart/symfony/style.css.', null, 'style.css'];
  209. yield ['/webmozart/symfony/style.css', null, 'style'];
  210. yield ['/webmozart/symfony/.style.css', null, '.style'];
  211. yield ['/webmozart/symfony/', null, 'symfony'];
  212. yield ['/webmozart/symfony', null, 'symfony'];
  213. yield ['/', null, ''];
  214. yield ['', null, ''];
  215. yield ['/webmozart/symfony/style.css', 'css', 'style'];
  216. yield ['/webmozart/symfony/style.css', '.css', 'style'];
  217. yield ['/webmozart/symfony/style.css', 'twig', 'style.css'];
  218. yield ['/webmozart/symfony/style.css', '.twig', 'style.css'];
  219. yield ['/webmozart/symfony/style.css', '', 'style.css'];
  220. yield ['/webmozart/symfony/style.css.', '', 'style.css'];
  221. yield ['/webmozart/symfony/style.css.', '.', 'style.css'];
  222. yield ['/webmozart/symfony/style.css.', '.css', 'style.css'];
  223. yield ['/webmozart/symfony/.style.css', 'css', '.style'];
  224. yield ['/webmozart/symfony/.style.css', '.css', '.style'];
  225. }
  226. /**
  227. * @dataProvider provideGetFilenameWithoutExtensionTests
  228. */
  229. public function testGetFilenameWithoutExtension(string $path, ?string $extension, string $filename)
  230. {
  231. $this->assertSame($filename, Path::getFilenameWithoutExtension($path, $extension));
  232. }
  233. public function provideGetExtensionTests(): \Generator
  234. {
  235. yield ['/webmozart/symfony/style.css.twig', false, 'twig'];
  236. yield ['/webmozart/symfony/style.css', false, 'css'];
  237. yield ['/webmozart/symfony/style.css.', false, ''];
  238. yield ['/webmozart/symfony/', false, ''];
  239. yield ['/webmozart/symfony', false, ''];
  240. yield ['/', false, ''];
  241. yield ['', false, ''];
  242. yield ['/webmozart/symfony/style.CSS', false, 'CSS'];
  243. yield ['/webmozart/symfony/style.CSS', true, 'css'];
  244. yield ['/webmozart/symfony/style.ÄÖÜ', false, 'ÄÖÜ'];
  245. yield ['/webmozart/symfony/style.ÄÖÜ', true, 'äöü'];
  246. }
  247. /**
  248. * @dataProvider provideGetExtensionTests
  249. */
  250. public function testGetExtension(string $path, bool $forceLowerCase, string $extension)
  251. {
  252. $this->assertSame($extension, Path::getExtension($path, $forceLowerCase));
  253. }
  254. public function provideHasExtensionTests(): \Generator
  255. {
  256. yield [true, '/webmozart/symfony/style.css.twig', null, false];
  257. yield [true, '/webmozart/symfony/style.css', null, false];
  258. yield [false, '/webmozart/symfony/style.css.', null, false];
  259. yield [false, '/webmozart/symfony/', null, false];
  260. yield [false, '/webmozart/symfony', null, false];
  261. yield [false, '/', null, false];
  262. yield [false, '', null, false];
  263. yield [true, '/webmozart/symfony/style.css.twig', 'twig', false];
  264. yield [false, '/webmozart/symfony/style.css.twig', 'css', false];
  265. yield [true, '/webmozart/symfony/style.css', 'css', false];
  266. yield [true, '/webmozart/symfony/style.css', '.css', false];
  267. yield [true, '/webmozart/symfony/style.css.', '', false];
  268. yield [false, '/webmozart/symfony/', 'ext', false];
  269. yield [false, '/webmozart/symfony', 'ext', false];
  270. yield [false, '/', 'ext', false];
  271. yield [false, '', 'ext', false];
  272. yield [false, '/webmozart/symfony/style.css', 'CSS', false];
  273. yield [true, '/webmozart/symfony/style.css', 'CSS', true];
  274. yield [false, '/webmozart/symfony/style.CSS', 'css', false];
  275. yield [true, '/webmozart/symfony/style.CSS', 'css', true];
  276. yield [true, '/webmozart/symfony/style.ÄÖÜ', 'ÄÖÜ', false];
  277. yield [true, '/webmozart/symfony/style.css', ['ext', 'css'], false];
  278. yield [true, '/webmozart/symfony/style.css', ['.ext', '.css'], false];
  279. yield [true, '/webmozart/symfony/style.css.', ['ext', ''], false];
  280. yield [false, '/webmozart/symfony/style.css', ['foo', 'bar', ''], false];
  281. yield [false, '/webmozart/symfony/style.css', ['.foo', '.bar', ''], false];
  282. // This can only be tested, when mbstring is installed
  283. yield [true, '/webmozart/symfony/style.ÄÖÜ', 'äöü', true];
  284. yield [true, '/webmozart/symfony/style.ÄÖÜ', ['äöü'], true];
  285. }
  286. /**
  287. * @dataProvider provideHasExtensionTests
  288. *
  289. * @param string|string[]|null $extension
  290. */
  291. public function testHasExtension(bool $hasExtension, string $path, $extension, bool $ignoreCase)
  292. {
  293. $this->assertSame($hasExtension, Path::hasExtension($path, $extension, $ignoreCase));
  294. }
  295. public function provideChangeExtensionTests(): \Generator
  296. {
  297. yield ['/webmozart/symfony/style.css.twig', 'html', '/webmozart/symfony/style.css.html'];
  298. yield ['/webmozart/symfony/style.css', 'sass', '/webmozart/symfony/style.sass'];
  299. yield ['/webmozart/symfony/style.css', '.sass', '/webmozart/symfony/style.sass'];
  300. yield ['/webmozart/symfony/style.css', '', '/webmozart/symfony/style.'];
  301. yield ['/webmozart/symfony/style.css.', 'twig', '/webmozart/symfony/style.css.twig'];
  302. yield ['/webmozart/symfony/style.css.', '', '/webmozart/symfony/style.css.'];
  303. yield ['/webmozart/symfony/style.css', 'äöü', '/webmozart/symfony/style.äöü'];
  304. yield ['/webmozart/symfony/style.äöü', 'css', '/webmozart/symfony/style.css'];
  305. yield ['/webmozart/symfony/', 'css', '/webmozart/symfony/'];
  306. yield ['/webmozart/symfony', 'css', '/webmozart/symfony.css'];
  307. yield ['/', 'css', '/'];
  308. yield ['', 'css', ''];
  309. }
  310. /**
  311. * @dataProvider provideChangeExtensionTests
  312. */
  313. public function testChangeExtension(string $path, string $extension, string $pathExpected)
  314. {
  315. $this->assertSame($pathExpected, Path::changeExtension($path, $extension));
  316. }
  317. public function provideIsAbsolutePathTests(): \Generator
  318. {
  319. yield ['/css/style.css', true];
  320. yield ['/', true];
  321. yield ['css/style.css', false];
  322. yield ['', false];
  323. yield ['\\css\\style.css', true];
  324. yield ['\\', true];
  325. yield ['css\\style.css', false];
  326. yield ['C:/css/style.css', true];
  327. yield ['D:/', true];
  328. yield ['E:\\css\\style.css', true];
  329. yield ['F:\\', true];
  330. yield ['phar:///css/style.css', true];
  331. yield ['phar:///', true];
  332. // Windows special case
  333. yield ['C:', true];
  334. // Not considered absolute
  335. yield ['C:css/style.css', false];
  336. }
  337. /**
  338. * @dataProvider provideIsAbsolutePathTests
  339. */
  340. public function testIsAbsolute(string $path, bool $isAbsolute)
  341. {
  342. $this->assertSame($isAbsolute, Path::isAbsolute($path));
  343. }
  344. /**
  345. * @dataProvider provideIsAbsolutePathTests
  346. */
  347. public function testIsRelative(string $path, bool $isAbsolute)
  348. {
  349. $this->assertSame(!$isAbsolute, Path::isRelative($path));
  350. }
  351. public function provideGetRootTests(): \Generator
  352. {
  353. yield ['/css/style.css', '/'];
  354. yield ['/', '/'];
  355. yield ['css/style.css', ''];
  356. yield ['', ''];
  357. yield ['\\css\\style.css', '/'];
  358. yield ['\\', '/'];
  359. yield ['css\\style.css', ''];
  360. yield ['C:/css/style.css', 'C:/'];
  361. yield ['C:/', 'C:/'];
  362. yield ['C:', 'C:/'];
  363. yield ['D:\\css\\style.css', 'D:/'];
  364. yield ['D:\\', 'D:/'];
  365. yield ['phar:///css/style.css', 'phar:///'];
  366. yield ['phar:///', 'phar:///'];
  367. yield ['phar://C:/css/style.css', 'phar://C:/'];
  368. yield ['phar://C:/', 'phar://C:/'];
  369. yield ['phar://C:', 'phar://C:/'];
  370. }
  371. /**
  372. * @dataProvider provideGetRootTests
  373. */
  374. public function testGetRoot(string $path, string $root)
  375. {
  376. $this->assertSame($root, Path::getRoot($path));
  377. }
  378. public function providePathTests(): \Generator
  379. {
  380. // relative to absolute path
  381. yield ['css/style.css', '/webmozart/symfony', '/webmozart/symfony/css/style.css'];
  382. yield ['../css/style.css', '/webmozart/symfony', '/webmozart/css/style.css'];
  383. yield ['../../css/style.css', '/webmozart/symfony', '/css/style.css'];
  384. // relative to root
  385. yield ['css/style.css', '/', '/css/style.css'];
  386. yield ['css/style.css', 'C:', 'C:/css/style.css'];
  387. yield ['css/style.css', 'C:/', 'C:/css/style.css'];
  388. // same sub directories in different base directories
  389. yield ['../../symfony/css/style.css', '/webmozart/css', '/symfony/css/style.css'];
  390. yield ['', '/webmozart/symfony', '/webmozart/symfony'];
  391. yield ['..', '/webmozart/symfony', '/webmozart'];
  392. }
  393. public function provideMakeAbsoluteTests(): \Generator
  394. {
  395. foreach ($this->providePathTests() as $set) {
  396. yield $set;
  397. }
  398. // collapse dots
  399. yield ['css/./style.css', '/webmozart/symfony', '/webmozart/symfony/css/style.css'];
  400. yield ['css/../style.css', '/webmozart/symfony', '/webmozart/symfony/style.css'];
  401. yield ['css/./../style.css', '/webmozart/symfony', '/webmozart/symfony/style.css'];
  402. yield ['css/.././style.css', '/webmozart/symfony', '/webmozart/symfony/style.css'];
  403. yield ['./css/style.css', '/webmozart/symfony', '/webmozart/symfony/css/style.css'];
  404. yield ['css\\.\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/css/style.css'];
  405. yield ['css\\..\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/style.css'];
  406. yield ['css\\.\\..\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/style.css'];
  407. yield ['css\\..\\.\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/style.css'];
  408. yield ['.\\css\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/css/style.css'];
  409. // collapse dots on root
  410. yield ['./css/style.css', '/', '/css/style.css'];
  411. yield ['../css/style.css', '/', '/css/style.css'];
  412. yield ['../css/./style.css', '/', '/css/style.css'];
  413. yield ['../css/../style.css', '/', '/style.css'];
  414. yield ['../css/./../style.css', '/', '/style.css'];
  415. yield ['../css/.././style.css', '/', '/style.css'];
  416. yield ['.\\css\\style.css', '\\', '/css/style.css'];
  417. yield ['..\\css\\style.css', '\\', '/css/style.css'];
  418. yield ['..\\css\\.\\style.css', '\\', '/css/style.css'];
  419. yield ['..\\css\\..\\style.css', '\\', '/style.css'];
  420. yield ['..\\css\\.\\..\\style.css', '\\', '/style.css'];
  421. yield ['..\\css\\..\\.\\style.css', '\\', '/style.css'];
  422. yield ['./css/style.css', 'C:/', 'C:/css/style.css'];
  423. yield ['../css/style.css', 'C:/', 'C:/css/style.css'];
  424. yield ['../css/./style.css', 'C:/', 'C:/css/style.css'];
  425. yield ['../css/../style.css', 'C:/', 'C:/style.css'];
  426. yield ['../css/./../style.css', 'C:/', 'C:/style.css'];
  427. yield ['../css/.././style.css', 'C:/', 'C:/style.css'];
  428. yield ['.\\css\\style.css', 'C:\\', 'C:/css/style.css'];
  429. yield ['..\\css\\style.css', 'C:\\', 'C:/css/style.css'];
  430. yield ['..\\css\\.\\style.css', 'C:\\', 'C:/css/style.css'];
  431. yield ['..\\css\\..\\style.css', 'C:\\', 'C:/style.css'];
  432. yield ['..\\css\\.\\..\\style.css', 'C:\\', 'C:/style.css'];
  433. yield ['..\\css\\..\\.\\style.css', 'C:\\', 'C:/style.css'];
  434. yield ['./css/style.css', 'phar:///', 'phar:///css/style.css'];
  435. yield ['../css/style.css', 'phar:///', 'phar:///css/style.css'];
  436. yield ['../css/./style.css', 'phar:///', 'phar:///css/style.css'];
  437. yield ['../css/../style.css', 'phar:///', 'phar:///style.css'];
  438. yield ['../css/./../style.css', 'phar:///', 'phar:///style.css'];
  439. yield ['../css/.././style.css', 'phar:///', 'phar:///style.css'];
  440. yield ['./css/style.css', 'phar://C:/', 'phar://C:/css/style.css'];
  441. yield ['../css/style.css', 'phar://C:/', 'phar://C:/css/style.css'];
  442. yield ['../css/./style.css', 'phar://C:/', 'phar://C:/css/style.css'];
  443. yield ['../css/../style.css', 'phar://C:/', 'phar://C:/style.css'];
  444. yield ['../css/./../style.css', 'phar://C:/', 'phar://C:/style.css'];
  445. yield ['../css/.././style.css', 'phar://C:/', 'phar://C:/style.css'];
  446. // absolute paths
  447. yield ['/css/style.css', '/webmozart/symfony', '/css/style.css'];
  448. yield ['\\css\\style.css', '/webmozart/symfony', '/css/style.css'];
  449. yield ['C:/css/style.css', 'C:/webmozart/symfony', 'C:/css/style.css'];
  450. yield ['D:\\css\\style.css', 'D:/webmozart/symfony', 'D:/css/style.css'];
  451. }
  452. /**
  453. * @dataProvider provideMakeAbsoluteTests
  454. */
  455. public function testMakeAbsolute(string $relativePath, string $basePath, string $absolutePath)
  456. {
  457. $this->assertSame($absolutePath, Path::makeAbsolute($relativePath, $basePath));
  458. }
  459. public function testMakeAbsoluteFailsIfBasePathNotAbsolute()
  460. {
  461. $this->expectException(\InvalidArgumentException::class);
  462. $this->expectExceptionMessage('The base path "webmozart/symfony" is not an absolute path.');
  463. Path::makeAbsolute('css/style.css', 'webmozart/symfony');
  464. }
  465. public function testMakeAbsoluteFailsIfBasePathEmpty()
  466. {
  467. $this->expectException(\InvalidArgumentException::class);
  468. $this->expectExceptionMessage('The base path must be a non-empty string. Got: ""');
  469. Path::makeAbsolute('css/style.css', '');
  470. }
  471. public function provideAbsolutePathsWithDifferentRoots(): \Generator
  472. {
  473. yield ['C:/css/style.css', '/webmozart/symfony'];
  474. yield ['C:/css/style.css', '\\webmozart\\symfony'];
  475. yield ['C:\\css\\style.css', '/webmozart/symfony'];
  476. yield ['C:\\css\\style.css', '\\webmozart\\symfony'];
  477. yield ['/css/style.css', 'C:/webmozart/symfony'];
  478. yield ['/css/style.css', 'C:\\webmozart\\symfony'];
  479. yield ['\\css\\style.css', 'C:/webmozart/symfony'];
  480. yield ['\\css\\style.css', 'C:\\webmozart\\symfony'];
  481. yield ['D:/css/style.css', 'C:/webmozart/symfony'];
  482. yield ['D:/css/style.css', 'C:\\webmozart\\symfony'];
  483. yield ['D:\\css\\style.css', 'C:/webmozart/symfony'];
  484. yield ['D:\\css\\style.css', 'C:\\webmozart\\symfony'];
  485. yield ['phar:///css/style.css', '/webmozart/symfony'];
  486. yield ['/css/style.css', 'phar:///webmozart/symfony'];
  487. yield ['phar://C:/css/style.css', 'C:/webmozart/symfony'];
  488. yield ['phar://C:/css/style.css', 'C:\\webmozart\\symfony'];
  489. yield ['phar://C:\\css\\style.css', 'C:/webmozart/symfony'];
  490. yield ['phar://C:\\css\\style.css', 'C:\\webmozart\\symfony'];
  491. }
  492. /**
  493. * @dataProvider provideAbsolutePathsWithDifferentRoots
  494. */
  495. public function testMakeAbsoluteDoesNotFailIfDifferentRoot(string $basePath, string $absolutePath)
  496. {
  497. // If a path in partition D: is passed, but $basePath is in partition
  498. // C:, the path should be returned unchanged
  499. $this->assertSame(Path::canonicalize($absolutePath), Path::makeAbsolute($absolutePath, $basePath));
  500. }
  501. public function provideMakeRelativeTests(): \Generator
  502. {
  503. foreach ($this->providePathTests() as $set) {
  504. yield [$set[2], $set[1], $set[0]];
  505. }
  506. yield ['/webmozart/symfony/./css/style.css', '/webmozart/symfony', 'css/style.css'];
  507. yield ['/webmozart/symfony/../css/style.css', '/webmozart/symfony', '../css/style.css'];
  508. yield ['/webmozart/symfony/.././css/style.css', '/webmozart/symfony', '../css/style.css'];
  509. yield ['/webmozart/symfony/./../css/style.css', '/webmozart/symfony', '../css/style.css'];
  510. yield ['/webmozart/symfony/../../css/style.css', '/webmozart/symfony', '../../css/style.css'];
  511. yield ['/webmozart/symfony/css/style.css', '/webmozart/./symfony', 'css/style.css'];
  512. yield ['/webmozart/symfony/css/style.css', '/webmozart/../symfony', '../webmozart/symfony/css/style.css'];
  513. yield ['/webmozart/symfony/css/style.css', '/webmozart/./../symfony', '../webmozart/symfony/css/style.css'];
  514. yield ['/webmozart/symfony/css/style.css', '/webmozart/.././symfony', '../webmozart/symfony/css/style.css'];
  515. yield ['/webmozart/symfony/css/style.css', '/webmozart/../../symfony', '../webmozart/symfony/css/style.css'];
  516. // first argument shorter than second
  517. yield ['/css', '/webmozart/symfony', '../../css'];
  518. // second argument shorter than first
  519. yield ['/webmozart/symfony', '/css', '../webmozart/symfony'];
  520. yield ['\\webmozart\\symfony\\css\\style.css', '\\webmozart\\symfony', 'css/style.css'];
  521. yield ['\\webmozart\\css\\style.css', '\\webmozart\\symfony', '../css/style.css'];
  522. yield ['\\css\\style.css', '\\webmozart\\symfony', '../../css/style.css'];
  523. yield ['C:/webmozart/symfony/css/style.css', 'C:/webmozart/symfony', 'css/style.css'];
  524. yield ['C:/webmozart/css/style.css', 'C:/webmozart/symfony', '../css/style.css'];
  525. yield ['C:/css/style.css', 'C:/webmozart/symfony', '../../css/style.css'];
  526. yield ['C:\\webmozart\\symfony\\css\\style.css', 'C:\\webmozart\\symfony', 'css/style.css'];
  527. yield ['C:\\webmozart\\css\\style.css', 'C:\\webmozart\\symfony', '../css/style.css'];
  528. yield ['C:\\css\\style.css', 'C:\\webmozart\\symfony', '../../css/style.css'];
  529. yield ['phar:///webmozart/symfony/css/style.css', 'phar:///webmozart/symfony', 'css/style.css'];
  530. yield ['phar:///webmozart/css/style.css', 'phar:///webmozart/symfony', '../css/style.css'];
  531. yield ['phar:///css/style.css', 'phar:///webmozart/symfony', '../../css/style.css'];
  532. yield ['phar://C:/webmozart/symfony/css/style.css', 'phar://C:/webmozart/symfony', 'css/style.css'];
  533. yield ['phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/symfony', '../css/style.css'];
  534. yield ['phar://C:/css/style.css', 'phar://C:/webmozart/symfony', '../../css/style.css'];
  535. // already relative + already in root basepath
  536. yield ['../style.css', '/', 'style.css'];
  537. yield ['./style.css', '/', 'style.css'];
  538. yield ['../../style.css', '/', 'style.css'];
  539. yield ['..\\style.css', 'C:\\', 'style.css'];
  540. yield ['.\\style.css', 'C:\\', 'style.css'];
  541. yield ['..\\..\\style.css', 'C:\\', 'style.css'];
  542. yield ['../style.css', 'C:/', 'style.css'];
  543. yield ['./style.css', 'C:/', 'style.css'];
  544. yield ['../../style.css', 'C:/', 'style.css'];
  545. yield ['..\\style.css', '\\', 'style.css'];
  546. yield ['.\\style.css', '\\', 'style.css'];
  547. yield ['..\\..\\style.css', '\\', 'style.css'];
  548. yield ['../style.css', 'phar:///', 'style.css'];
  549. yield ['./style.css', 'phar:///', 'style.css'];
  550. yield ['../../style.css', 'phar:///', 'style.css'];
  551. yield ['..\\style.css', 'phar://C:\\', 'style.css'];
  552. yield ['.\\style.css', 'phar://C:\\', 'style.css'];
  553. yield ['..\\..\\style.css', 'phar://C:\\', 'style.css'];
  554. yield ['css/../style.css', '/', 'style.css'];
  555. yield ['css/./style.css', '/', 'css/style.css'];
  556. yield ['css\\..\\style.css', 'C:\\', 'style.css'];
  557. yield ['css\\.\\style.css', 'C:\\', 'css/style.css'];
  558. yield ['css/../style.css', 'C:/', 'style.css'];
  559. yield ['css/./style.css', 'C:/', 'css/style.css'];
  560. yield ['css\\..\\style.css', '\\', 'style.css'];
  561. yield ['css\\.\\style.css', '\\', 'css/style.css'];
  562. yield ['css/../style.css', 'phar:///', 'style.css'];
  563. yield ['css/./style.css', 'phar:///', 'css/style.css'];
  564. yield ['css\\..\\style.css', 'phar://C:\\', 'style.css'];
  565. yield ['css\\.\\style.css', 'phar://C:\\', 'css/style.css'];
  566. // already relative
  567. yield ['css/style.css', '/webmozart/symfony', 'css/style.css'];
  568. yield ['css\\style.css', '\\webmozart\\symfony', 'css/style.css'];
  569. // both relative
  570. yield ['css/style.css', 'webmozart/symfony', '../../css/style.css'];
  571. yield ['css\\style.css', 'webmozart\\symfony', '../../css/style.css'];
  572. // relative to empty
  573. yield ['css/style.css', '', 'css/style.css'];
  574. yield ['css\\style.css', '', 'css/style.css'];
  575. // different slashes in path and base path
  576. yield ['/webmozart/symfony/css/style.css', '\\webmozart\\symfony', 'css/style.css'];
  577. yield ['\\webmozart\\symfony\\css\\style.css', '/webmozart/symfony', 'css/style.css'];
  578. }
  579. /**
  580. * @dataProvider provideMakeRelativeTests
  581. */
  582. public function testMakeRelative(string $absolutePath, string $basePath, string $relativePath)
  583. {
  584. $this->assertSame($relativePath, Path::makeRelative($absolutePath, $basePath));
  585. }
  586. public function testMakeRelativeFailsIfAbsolutePathAndBasePathNotAbsolute()
  587. {
  588. $this->expectException(\InvalidArgumentException::class);
  589. $this->expectExceptionMessage('The absolute path "/webmozart/symfony/css/style.css" cannot be made relative to the relative path "webmozart/symfony". You should provide an absolute base path instead.');
  590. Path::makeRelative('/webmozart/symfony/css/style.css', 'webmozart/symfony');
  591. }
  592. public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty()
  593. {
  594. $this->expectExceptionMessage('The absolute path "/webmozart/symfony/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead.');
  595. Path::makeRelative('/webmozart/symfony/css/style.css', '');
  596. }
  597. /**
  598. * @dataProvider provideAbsolutePathsWithDifferentRoots
  599. */
  600. public function testMakeRelativeFailsIfDifferentRoot(string $absolutePath, string $basePath)
  601. {
  602. $this->expectException(\InvalidArgumentException::class);
  603. Path::makeRelative($absolutePath, $basePath);
  604. }
  605. public function provideIsLocalTests(): \Generator
  606. {
  607. yield ['/bg.png', true];
  608. yield ['bg.png', true];
  609. yield ['http://example.com/bg.png', false];
  610. yield ['http://example.com', false];
  611. yield ['', false];
  612. }
  613. /**
  614. * @dataProvider provideIsLocalTests
  615. */
  616. public function testIsLocal(string $path, bool $isLocal)
  617. {
  618. $this->assertSame($isLocal, Path::isLocal($path));
  619. }
  620. public function provideGetLongestCommonBasePathTests(): \Generator
  621. {
  622. // same paths
  623. yield [['/base/path', '/base/path'], '/base/path'];
  624. yield [['C:/base/path', 'C:/base/path'], 'C:/base/path'];
  625. yield [['C:\\base\\path', 'C:\\base\\path'], 'C:/base/path'];
  626. yield [['C:/base/path', 'C:\\base\\path'], 'C:/base/path'];
  627. yield [['phar:///base/path', 'phar:///base/path'], 'phar:///base/path'];
  628. yield [['phar://C:/base/path', 'phar://C:/base/path'], 'phar://C:/base/path'];
  629. // trailing slash
  630. yield [['/base/path/', '/base/path'], '/base/path'];
  631. yield [['C:/base/path/', 'C:/base/path'], 'C:/base/path'];
  632. yield [['C:\\base\\path\\', 'C:\\base\\path'], 'C:/base/path'];
  633. yield [['C:/base/path/', 'C:\\base\\path'], 'C:/base/path'];
  634. yield [['phar:///base/path/', 'phar:///base/path'], 'phar:///base/path'];
  635. yield [['phar://C:/base/path/', 'phar://C:/base/path'], 'phar://C:/base/path'];
  636. yield [['/base/path', '/base/path/'], '/base/path'];
  637. yield [['C:/base/path', 'C:/base/path/'], 'C:/base/path'];
  638. yield [['C:\\base\\path', 'C:\\base\\path\\'], 'C:/base/path'];
  639. yield [['C:/base/path', 'C:\\base\\path\\'], 'C:/base/path'];
  640. yield [['phar:///base/path', 'phar:///base/path/'], 'phar:///base/path'];
  641. yield [['phar://C:/base/path', 'phar://C:/base/path/'], 'phar://C:/base/path'];
  642. // first in second
  643. yield [['/base/path/sub', '/base/path'], '/base/path'];
  644. yield [['C:/base/path/sub', 'C:/base/path'], 'C:/base/path'];
  645. yield [['C:\\base\\path\\sub', 'C:\\base\\path'], 'C:/base/path'];
  646. yield [['C:/base/path/sub', 'C:\\base\\path'], 'C:/base/path'];
  647. yield [['phar:///base/path/sub', 'phar:///base/path'], 'phar:///base/path'];
  648. yield [['phar://C:/base/path/sub', 'phar://C:/base/path'], 'phar://C:/base/path'];
  649. // second in first
  650. yield [['/base/path', '/base/path/sub'], '/base/path'];
  651. yield [['C:/base/path', 'C:/base/path/sub'], 'C:/base/path'];
  652. yield [['C:\\base\\path', 'C:\\base\\path\\sub'], 'C:/base/path'];
  653. yield [['C:/base/path', 'C:\\base\\path\\sub'], 'C:/base/path'];
  654. yield [['phar:///base/path', 'phar:///base/path/sub'], 'phar:///base/path'];
  655. yield [['phar://C:/base/path', 'phar://C:/base/path/sub'], 'phar://C:/base/path'];
  656. // first is prefix
  657. yield [['/base/path/di', '/base/path/dir'], '/base/path'];
  658. yield [['C:/base/path/di', 'C:/base/path/dir'], 'C:/base/path'];
  659. yield [['C:\\base\\path\\di', 'C:\\base\\path\\dir'], 'C:/base/path'];
  660. yield [['C:/base/path/di', 'C:\\base\\path\\dir'], 'C:/base/path'];
  661. yield [['phar:///base/path/di', 'phar:///base/path/dir'], 'phar:///base/path'];
  662. yield [['phar://C:/base/path/di', 'phar://C:/base/path/dir'], 'phar://C:/base/path'];
  663. // second is prefix
  664. yield [['/base/path/dir', '/base/path/di'], '/base/path'];
  665. yield [['C:/base/path/dir', 'C:/base/path/di'], 'C:/base/path'];
  666. yield [['C:\\base\\path\\dir', 'C:\\base\\path\\di'], 'C:/base/path'];
  667. yield [['C:/base/path/dir', 'C:\\base\\path\\di'], 'C:/base/path'];
  668. yield [['phar:///base/path/dir', 'phar:///base/path/di'], 'phar:///base/path'];
  669. yield [['phar://C:/base/path/dir', 'phar://C:/base/path/di'], 'phar://C:/base/path'];
  670. // root is common base path
  671. yield [['/first', '/second'], '/'];
  672. yield [['C:/first', 'C:/second'], 'C:/'];
  673. yield [['C:\\first', 'C:\\second'], 'C:/'];
  674. yield [['C:/first', 'C:\\second'], 'C:/'];
  675. yield [['phar:///first', 'phar:///second'], 'phar:///'];
  676. yield [['phar://C:/first', 'phar://C:/second'], 'phar://C:/'];
  677. // windows vs unix
  678. yield [['/base/path', 'C:/base/path'], null];
  679. yield [['C:/base/path', '/base/path'], null];
  680. yield [['/base/path', 'C:\\base\\path'], null];
  681. yield [['phar:///base/path', 'phar://C:/base/path'], null];
  682. // different partitions
  683. yield [['C:/base/path', 'D:/base/path'], null];
  684. yield [['C:/base/path', 'D:\\base\\path'], null];
  685. yield [['C:\\base\\path', 'D:\\base\\path'], null];
  686. yield [['phar://C:/base/path', 'phar://D:/base/path'], null];
  687. // three paths
  688. yield [['/base/path/foo', '/base/path', '/base/path/bar'], '/base/path'];
  689. yield [['C:/base/path/foo', 'C:/base/path', 'C:/base/path/bar'], 'C:/base/path'];
  690. yield [['C:\\base\\path\\foo', 'C:\\base\\path', 'C:\\base\\path\\bar'], 'C:/base/path'];
  691. yield [['C:/base/path//foo', 'C:/base/path', 'C:\\base\\path\\bar'], 'C:/base/path'];
  692. yield [['phar:///base/path/foo', 'phar:///base/path', 'phar:///base/path/bar'], 'phar:///base/path'];
  693. yield [['phar://C:/base/path/foo', 'phar://C:/base/path', 'phar://C:/base/path/bar'], 'phar://C:/base/path'];
  694. // three paths with root
  695. yield [['/base/path/foo', '/', '/base/path/bar'], '/'];
  696. yield [['C:/base/path/foo', 'C:/', 'C:/base/path/bar'], 'C:/'];
  697. yield [['C:\\base\\path\\foo', 'C:\\', 'C:\\base\\path\\bar'], 'C:/'];
  698. yield [['C:/base/path//foo', 'C:/', 'C:\\base\\path\\bar'], 'C:/'];
  699. yield [['phar:///base/path/foo', 'phar:///', 'phar:///base/path/bar'], 'phar:///'];
  700. yield [['phar://C:/base/path/foo', 'phar://C:/', 'phar://C:/base/path/bar'], 'phar://C:/'];
  701. // three paths, different roots
  702. yield [['/base/path/foo', 'C:/base/path', '/base/path/bar'], null];
  703. yield [['/base/path/foo', 'C:\\base\\path', '/base/path/bar'], null];
  704. yield [['C:/base/path/foo', 'D:/base/path', 'C:/base/path/bar'], null];
  705. yield [['C:\\base\\path\\foo', 'D:\\base\\path', 'C:\\base\\path\\bar'], null];
  706. yield [['C:/base/path//foo', 'D:/base/path', 'C:\\base\\path\\bar'], null];
  707. yield [['phar:///base/path/foo', 'phar://C:/base/path', 'phar:///base/path/bar'], null];
  708. yield [['phar://C:/base/path/foo', 'phar://D:/base/path', 'phar://C:/base/path/bar'], null];
  709. // only one path
  710. yield [['/base/path'], '/base/path'];
  711. yield [['C:/base/path'], 'C:/base/path'];
  712. yield [['C:\\base\\path'], 'C:/base/path'];
  713. yield [['phar:///base/path'], 'phar:///base/path'];
  714. yield [['phar://C:/base/path'], 'phar://C:/base/path'];
  715. }
  716. /**
  717. * @dataProvider provideGetLongestCommonBasePathTests
  718. *
  719. * @param string[] $paths
  720. */
  721. public function testGetLongestCommonBasePath(array $paths, ?string $basePath)
  722. {
  723. $this->assertSame($basePath, Path::getLongestCommonBasePath(...$paths));
  724. }
  725. public function provideIsBasePathTests(): \Generator
  726. {
  727. // same paths
  728. yield ['/base/path', '/base/path', true];
  729. yield ['C:/base/path', 'C:/base/path', true];
  730. yield ['C:\\base\\path', 'C:\\base\\path', true];
  731. yield ['C:/base/path', 'C:\\base\\path', true];
  732. yield ['phar:///base/path', 'phar:///base/path', true];
  733. yield ['phar://C:/base/path', 'phar://C:/base/path', true];
  734. // trailing slash
  735. yield ['/base/path/', '/base/path', true];
  736. yield ['C:/base/path/', 'C:/base/path', true];
  737. yield ['C:\\base\\path\\', 'C:\\base\\path', true];
  738. yield ['C:/base/path/', 'C:\\base\\path', true];
  739. yield ['phar:///base/path/', 'phar:///base/path', true];
  740. yield ['phar://C:/base/path/', 'phar://C:/base/path', true];
  741. yield ['/base/path', '/base/path/', true];
  742. yield ['C:/base/path', 'C:/base/path/', true];
  743. yield ['C:\\base\\path', 'C:\\base\\path\\', true];
  744. yield ['C:/base/path', 'C:\\base\\path\\', true];
  745. yield ['phar:///base/path', 'phar:///base/path/', true];
  746. yield ['phar://C:/base/path', 'phar://C:/base/path/', true];
  747. // first in second
  748. yield ['/base/path/sub', '/base/path', false];
  749. yield ['C:/base/path/sub', 'C:/base/path', false];
  750. yield ['C:\\base\\path\\sub', 'C:\\base\\path', false];
  751. yield ['C:/base/path/sub', 'C:\\base\\path', false];
  752. yield ['phar:///base/path/sub', 'phar:///base/path', false];
  753. yield ['phar://C:/base/path/sub', 'phar://C:/base/path', false];
  754. // second in first
  755. yield ['/base/path', '/base/path/sub', true];
  756. yield ['C:/base/path', 'C:/base/path/sub', true];
  757. yield ['C:\\base\\path', 'C:\\base\\path\\sub', true];
  758. yield ['C:/base/path', 'C:\\base\\path\\sub', true];
  759. yield ['phar:///base/path', 'phar:///base/path/sub', true];
  760. yield ['phar://C:/base/path', 'phar://C:/base/path/sub', true];
  761. // first is prefix
  762. yield ['/base/path/di', '/base/path/dir', false];
  763. yield ['C:/base/path/di', 'C:/base/path/dir', false];
  764. yield ['C:\\base\\path\\di', 'C:\\base\\path\\dir', false];
  765. yield ['C:/base/path/di', 'C:\\base\\path\\dir', false];
  766. yield ['phar:///base/path/di', 'phar:///base/path/dir', false];
  767. yield ['phar://C:/base/path/di', 'phar://C:/base/path/dir', false];
  768. // second is prefix
  769. yield ['/base/path/dir', '/base/path/di', false];
  770. yield ['C:/base/path/dir', 'C:/base/path/di', false];
  771. yield ['C:\\base\\path\\dir', 'C:\\base\\path\\di', false];
  772. yield ['C:/base/path/dir', 'C:\\base\\path\\di', false];
  773. yield ['phar:///base/path/dir', 'phar:///base/path/di', false];
  774. yield ['phar://C:/base/path/dir', 'phar://C:/base/path/di', false];
  775. // root
  776. yield ['/', '/second', true];
  777. yield ['C:/', 'C:/second', true];
  778. yield ['C:', 'C:/second', true];
  779. yield ['C:\\', 'C:\\second', true];
  780. yield ['C:/', 'C:\\second', true];
  781. yield ['phar:///', 'phar:///second', true];
  782. yield ['phar://C:/', 'phar://C:/second', true];
  783. // windows vs unix
  784. yield ['/base/path', 'C:/base/path', false];
  785. yield ['C:/base/path', '/base/path', false];
  786. yield ['/base/path', 'C:\\base\\path', false];
  787. yield ['/base/path', 'phar:///base/path', false];
  788. yield ['phar:///base/path', 'phar://C:/base/path', false];
  789. // different partitions
  790. yield ['C:/base/path', 'D:/base/path', false];
  791. yield ['C:/base/path', 'D:\\base\\path', false];
  792. yield ['C:\\base\\path', 'D:\\base\\path', false];
  793. yield ['C:/base/path', 'phar://C:/base/path', false];
  794. yield ['phar://C:/base/path', 'phar://D:/base/path', false];
  795. }
  796. /**
  797. * @dataProvider provideIsBasePathTests
  798. */
  799. public function testIsBasePath(string $path, string $ofPath, bool $result)
  800. {
  801. $this->assertSame($result, Path::isBasePath($path, $ofPath));
  802. }
  803. public function provideJoinTests(): \Generator
  804. {
  805. yield [['', ''], ''];
  806. yield [['/path/to/test', ''], '/path/to/test'];
  807. yield [['/path/to//test', ''], '/path/to/test'];
  808. yield [['', '/path/to/test'], '/path/to/test'];
  809. yield [['', '/path/to//test'], '/path/to/test'];
  810. yield [['/path/to/test', 'subdir'], '/path/to/test/subdir'];
  811. yield [['/path/to/test/', 'subdir'], '/path/to/test/subdir'];
  812. yield [['/path/to/test', '/subdir'], '/path/to/test/subdir'];
  813. yield [['/path/to/test/', '/subdir'], '/path/to/test/subdir'];
  814. yield [['/path/to/test', './subdir'], '/path/to/test/subdir'];
  815. yield [['/path/to/test/', './subdir'], '/path/to/test/subdir'];
  816. yield [['/path/to/test/', '../parentdir'], '/path/to/parentdir'];
  817. yield [['/path/to/test', '../parentdir'], '/path/to/parentdir'];
  818. yield [['path/to/test/', '/subdir'], 'path/to/test/subdir'];
  819. yield [['path/to/test', '/subdir'], 'path/to/test/subdir'];
  820. yield [['../path/to/test', '/subdir'], '../path/to/test/subdir'];
  821. yield [['path', '../../subdir'], '../subdir'];
  822. yield [['/path', '../../subdir'], '/subdir'];
  823. yield [['../path', '../../subdir'], '../../subdir'];
  824. yield [['/path/to/test', 'subdir', ''], '/path/to/test/subdir'];
  825. yield [['/path/to/test', '/subdir', ''], '/path/to/test/subdir'];
  826. yield [['/path/to/test/', 'subdir', ''], '/path/to/test/subdir'];
  827. yield [['/path/to/test/', '/subdir', ''], '/path/to/test/subdir'];
  828. yield [['/path', ''], '/path'];
  829. yield [['/path', 'to', '/test', ''], '/path/to/test'];
  830. yield [['/path', '', '/test', ''], '/path/test'];
  831. yield [['path', 'to', 'test', ''], 'path/to/test'];
  832. yield [[], ''];
  833. yield [['base/path', 'to/test'], 'base/path/to/test'];
  834. yield [['C:\\path\\to\\test', 'subdir'], 'C:/path/to/test/subdir'];
  835. yield [['C:\\path\\to\\test\\', 'subdir'], 'C:/path/to/test/subdir'];
  836. yield [['C:\\path\\to\\test', '/subdir'], 'C:/path/to/test/subdir'];
  837. yield [['C:\\path\\to\\test\\', '/subdir'], 'C:/path/to/test/subdir'];
  838. yield [['/', 'subdir'], '/subdir'];
  839. yield [['/', '/subdir'], '/subdir'];
  840. yield [['C:/', 'subdir'], 'C:/subdir'];
  841. yield [['C:/', '/subdir'], 'C:/subdir'];
  842. yield [['C:\\', 'subdir'], 'C:/subdir'];
  843. yield [['C:\\', '/subdir'], 'C:/subdir'];
  844. yield [['C:', 'subdir'], 'C:/subdir'];
  845. yield [['C:', '/subdir'], 'C:/subdir'];
  846. yield [['phar://', '/path/to/test'], 'phar:///path/to/test'];
  847. yield [['phar:///', '/path/to/test'], 'phar:///path/to/test'];
  848. yield [['phar:///path/to/test', 'subdir'], 'phar:///path/to/test/subdir'];
  849. yield [['phar:///path/to/test', 'subdir/'], 'phar:///path/to/test/subdir'];
  850. yield [['phar:///path/to/test', '/subdir'], 'phar:///path/to/test/subdir'];
  851. yield [['phar:///path/to/test/', 'subdir'], 'phar:///path/to/test/subdir'];
  852. yield [['phar:///path/to/test/', '/subdir'], 'phar:///path/to/test/subdir'];
  853. yield [['phar://', 'C:/path/to/test'], 'phar://C:/path/to/test'];
  854. yield [['phar://', 'C:\\path\\to\\test'], 'phar://C:/path/to/test'];
  855. yield [['phar://C:/path/to/test', 'subdir'], 'phar://C:/path/to/test/subdir'];
  856. yield [['phar://C:/path/to/test', 'subdir/'], 'phar://C:/path/to/test/subdir'];
  857. yield [['phar://C:/path/to/test', '/subdir'], 'phar://C:/path/to/test/subdir'];
  858. yield [['phar://C:/path/to/test/', 'subdir'], 'phar://C:/path/to/test/subdir'];
  859. yield [['phar://C:/path/to/test/', '/subdir'], 'phar://C:/path/to/test/subdir'];
  860. yield [['phar://C:', 'path/to/test'], 'phar://C:/path/to/test'];
  861. yield [['phar://C:', '/path/to/test'], 'phar://C:/path/to/test'];
  862. yield [['phar://C:/', 'path/to/test'], 'phar://C:/path/to/test'];
  863. yield [['phar://C:/', '/path/to/test'], 'phar://C:/path/to/test'];
  864. }
  865. /**
  866. * @dataProvider provideJoinTests
  867. */
  868. public function testJoin(array $paths, $result)
  869. {
  870. $this->assertSame($result, Path::join(...$paths));
  871. }
  872. public function testJoinVarArgs()
  873. {
  874. $this->assertSame('/path', Path::join('/path'));
  875. $this->assertSame('/path/to', Path::join('/path', 'to'));
  876. $this->assertSame('/path/to/test', Path::join('/path', 'to', '/test'));
  877. $this->assertSame('/path/to/test/subdir', Path::join('/path', 'to', '/test', 'subdir/'));
  878. }
  879. public function testGetHomeDirectoryFailsIfNotSupportedOperatingSystem()
  880. {
  881. $this->expectException(\RuntimeException::class);
  882. $this->expectExceptionMessage('Your environment or operating system isn\'t supported');
  883. putenv('HOME=');
  884. Path::getHomeDirectory();
  885. }
  886. public function testGetHomeDirectoryForUnix()
  887. {
  888. $this->assertEquals('/home/webmozart', Path::getHomeDirectory());
  889. }
  890. public function testGetHomeDirectoryForWindows()
  891. {
  892. putenv('HOME=');
  893. putenv('HOMEDRIVE=C:');
  894. putenv('HOMEPATH=/users/webmozart');
  895. $this->assertEquals('C:/users/webmozart', Path::getHomeDirectory());
  896. }
  897. public function testNormalize()
  898. {
  899. $this->assertSame('C:/Foo/Bar/test', Path::normalize('C:\\Foo\\Bar/test'));
  900. }
  901. }