UtilTests.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <?php
  2. namespace League\Flysystem;
  3. use LogicException;
  4. use PHPUnit\Framework\TestCase;
  5. class UtilTests extends TestCase
  6. {
  7. public function testEmulateDirectories()
  8. {
  9. $input = [
  10. ['dirname' => '', 'filename' => 'dummy', 'path' => 'dummy', 'type' => 'file'],
  11. ['dirname' => 'something', 'filename' => 'dummy', 'path' => 'something/dummy', 'type' => 'file'],
  12. ['dirname' => 'something', 'path' => 'something/dirname', 'type' => 'dir'],
  13. ];
  14. $output = Util::emulateDirectories($input);
  15. $this->assertCount(4, $output);
  16. }
  17. public function testEmulateDirectoriesWithNumberZeroDirectoryName()
  18. {
  19. $input = [
  20. ['dirname' => 'something/0', 'path' => 'something/0/dirname', 'type' => 'dir'],
  21. ['dirname' => '0/other', 'path' => '0/other/dir', 'type' => 'dir'],
  22. ];
  23. $output = Util::emulateDirectories($input);
  24. $this->assertCount(6, $output);
  25. }
  26. public function testContentSize()
  27. {
  28. $this->assertEquals(5, Util::contentSize('12345'));
  29. $this->assertEquals(3, Util::contentSize('135'));
  30. }
  31. /**
  32. * @dataProvider dbCorruptedPath
  33. */
  34. public function testRejectingPathWithFunkyWhitespace($path)
  35. {
  36. $this->expectException(CorruptedPathDetected::class);
  37. Util::normalizePath($path);
  38. }
  39. /**
  40. * @return array
  41. */
  42. public function dbCorruptedPath()
  43. {
  44. return [["some\0/path.txt"], ["s\x09i.php"]];
  45. }
  46. public function mapProvider()
  47. {
  48. return [
  49. [['from.this' => 'value'], ['from.this' => 'to.this', 'other' => 'other'], ['to.this' => 'value']],
  50. [['from.this' => 'value', 'no.mapping' => 'lost'], ['from.this' => 'to.this'], ['to.this' => 'value']],
  51. ];
  52. }
  53. /**
  54. * @dataProvider mapProvider
  55. */
  56. public function testMap($from, $map, $expected)
  57. {
  58. $result = Util::map($from, $map);
  59. $this->assertEquals($expected, $result);
  60. }
  61. public function dirnameProvider()
  62. {
  63. return [
  64. ['filename.txt', ''],
  65. ['dirname/filename.txt', 'dirname'],
  66. ['dirname/subdir', 'dirname'],
  67. ];
  68. }
  69. /**
  70. * @dataProvider dirnameProvider
  71. */
  72. public function testDirname($input, $expected)
  73. {
  74. $result = Util::dirname($input);
  75. $this->assertEquals($expected, $result);
  76. }
  77. public function testEnsureConfig()
  78. {
  79. $this->assertInstanceOf('League\Flysystem\Config', Util::ensureConfig([]));
  80. $this->assertInstanceOf('League\Flysystem\Config', Util::ensureConfig(null));
  81. $this->assertInstanceOf('League\Flysystem\Config', Util::ensureConfig(new Config()));
  82. }
  83. public function testInvalidValueEnsureConfig()
  84. {
  85. $this->expectException(LogicException::class);
  86. Util::ensureConfig(false);
  87. }
  88. public function invalidPathProvider()
  89. {
  90. return [
  91. ['something/../../../hehe'],
  92. ['/something/../../..'],
  93. ['..'],
  94. ['something\\..\\..'],
  95. ['\\something\\..\\..\\dirname'],
  96. ];
  97. }
  98. /**
  99. * @dataProvider invalidPathProvider
  100. */
  101. public function testOutsideRootPath($path)
  102. {
  103. $this->expectException(LogicException::class);
  104. Util::normalizePath($path);
  105. }
  106. public function pathProvider()
  107. {
  108. return [
  109. ['.', ''],
  110. ['/path/to/dir/.', 'path/to/dir'],
  111. ['/dirname/', 'dirname'],
  112. ['dirname/..', ''],
  113. ['dirname/../', ''],
  114. ['dirname./', 'dirname.'],
  115. ['dirname/./', 'dirname'],
  116. ['dirname/.', 'dirname'],
  117. ['./dir/../././', ''],
  118. ['/something/deep/../../dirname', 'dirname'],
  119. ['00004869/files/other/10-75..stl', '00004869/files/other/10-75..stl'],
  120. ['/dirname//subdir///subsubdir', 'dirname/subdir/subsubdir'],
  121. ['\dirname\\\\subdir\\\\\\subsubdir', 'dirname/subdir/subsubdir'],
  122. ['\\\\some\shared\\\\drive', 'some/shared/drive'],
  123. ['C:\dirname\\\\subdir\\\\\\subsubdir', 'C:/dirname/subdir/subsubdir'],
  124. ['C:\\\\dirname\subdir\\\\subsubdir', 'C:/dirname/subdir/subsubdir'],
  125. ['example/path/..txt', 'example/path/..txt'],
  126. ['\\example\\path.txt', 'example/path.txt'],
  127. ['\\example\\..\\path.txt', 'path.txt'],
  128. ];
  129. }
  130. /**
  131. * @dataProvider pathProvider
  132. */
  133. public function testNormalizePath($input, $expected)
  134. {
  135. $result = Util::normalizePath($input);
  136. $double = Util::normalizePath(Util::normalizePath($input));
  137. $this->assertEquals($expected, $result);
  138. $this->assertEquals($expected, $double);
  139. }
  140. public function pathAndContentProvider()
  141. {
  142. return [
  143. ['/some/file.css', '.event { background: #000; } ', 'text/css'],
  144. ['/some/file.css', 'body { background: #000; } ', 'text/css'],
  145. ['/some/file.txt', 'body { background: #000; } ', 'text/plain'],
  146. ['/1x1', base64_decode('R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='), 'image/gif'],
  147. ];
  148. }
  149. /**
  150. * @dataProvider pathAndContentProvider
  151. */
  152. public function testGuessMimeType($path, $content, $expected)
  153. {
  154. $mimeType = Util::guessMimeType($path, $content);
  155. $this->assertEquals($expected, $mimeType);
  156. }
  157. public function testStreamSize()
  158. {
  159. $stream = tmpfile();
  160. fwrite($stream, 'aaa');
  161. $size = Util::getStreamSize($stream);
  162. $this->assertEquals(3, $size);
  163. fclose($stream);
  164. }
  165. public function testStreamSizeForUrl()
  166. {
  167. $stream = \fopen('https://flysystem.thephpleague.com/img/flysystem.svg', 'r');
  168. $this->assertNull(Util::getStreamSize($stream));
  169. fclose($stream);
  170. }
  171. public function testRewindStream()
  172. {
  173. $stream = tmpfile();
  174. fwrite($stream, 'something');
  175. $this->assertNotEquals(0, ftell($stream));
  176. Util::rewindStream($stream);
  177. $this->assertEquals(0, ftell($stream));
  178. fclose($stream);
  179. }
  180. public function testNormalizePrefix()
  181. {
  182. $this->assertEquals('test/', Util::normalizePrefix('test', '/'));
  183. $this->assertEquals('test/', Util::normalizePrefix('test/', '/'));
  184. }
  185. public function pathinfoPathProvider()
  186. {
  187. return [
  188. [''],
  189. ['.'],
  190. ['..'],
  191. ['...'],
  192. ['/.'],
  193. ['//.'],
  194. ['///.'],
  195. ['foo'],
  196. ['/foo'],
  197. ['/foo/bar'],
  198. ['/foo/bar/'],
  199. ['file.txt'],
  200. ['foo/file.txt'],
  201. ['/foo/file.jpeg'],
  202. ['.txt'],
  203. ['dir/.txt'],
  204. ['/dir/.txt'],
  205. ['foo/bar.'],
  206. ['foo/bar..'],
  207. ['foo/bar/.'],
  208. ['c:'],
  209. ['c:\\'],
  210. ['c:/'],
  211. ['c:file'],
  212. ['c:f:ile'],
  213. ['c:f:'],
  214. ['c:d:e:'],
  215. ['AB:file'],
  216. ['AB:'],
  217. ['d:\foo\bar'],
  218. ['E:\foo\bar\\'],
  219. ['f:\foo\bar:baz'],
  220. ['G:\foo\bar:'],
  221. ['c:/foo/bar'],
  222. ['c:/foo/bar/'],
  223. ['Y:\foo\bar.txt'],
  224. ['z:\foo\bar.'],
  225. ['foo\bar'],
  226. ];
  227. }
  228. /**
  229. * @dataProvider pathinfoPathProvider
  230. */
  231. public function testPathinfo($path)
  232. {
  233. $expected = compact('path') + pathinfo($path) + ['dirname' => ''];
  234. if (isset($expected['dirname'])) {
  235. $expected['dirname'] = Util::normalizeDirname($expected['dirname']);
  236. }
  237. $this->assertSame($expected, Util::pathinfo($path));
  238. }
  239. public function testPathinfoHandlesUtf8()
  240. {
  241. if (setlocale(LC_ALL, 'C.UTF-8', 'C.utf8') === false) {
  242. $this->markTestSkipped('testPathinfoHandlesUtf8 requires UTF-8.');
  243. }
  244. $path = 'files/繁體中文字/test.txt';
  245. $expected = [
  246. 'path' => 'files/繁體中文字/test.txt',
  247. 'dirname' => 'files/繁體中文字',
  248. 'basename' => 'test.txt',
  249. 'extension' => 'txt',
  250. 'filename' => 'test',
  251. ];
  252. $this->assertSame($expected, Util::pathinfo($path));
  253. $path = 'files/繁體中文字.txt';
  254. $expected = [
  255. 'path' => 'files/繁體中文字.txt',
  256. 'dirname' => 'files',
  257. 'basename' => '繁體中文字.txt',
  258. 'extension' => 'txt',
  259. 'filename' => '繁體中文字',
  260. ];
  261. $this->assertSame($expected, Util::pathinfo($path));
  262. $path = '👨‍👩‍👧‍👦👨‍👩‍👦‍👦👨‍👩‍👧‍👧/繁體中文字.txt';
  263. $expected = [
  264. 'path' => '👨‍👩‍👧‍👦👨‍👩‍👦‍👦👨‍👩‍👧‍👧/繁體中文字.txt',
  265. 'dirname' => '👨‍👩‍👧‍👦👨‍👩‍👦‍👦👨‍👩‍👧‍👧',
  266. 'basename' => '繁體中文字.txt',
  267. 'extension' => 'txt',
  268. 'filename' => '繁體中文字',
  269. ];
  270. $this->assertSame($expected, Util::pathinfo($path));
  271. $path = 'foo/bar.baz.😀😬😁';
  272. $expected = [
  273. 'path' => 'foo/bar.baz.😀😬😁',
  274. 'dirname' => 'foo',
  275. 'basename' => 'bar.baz.😀😬😁',
  276. 'extension' => '😀😬😁',
  277. 'filename' => 'bar.baz',
  278. ];
  279. $this->assertSame($expected, Util::pathinfo($path));
  280. $path = '繁體中文字/👨‍👩‍👧‍👦.😺😸😹😻.😀😬😁';
  281. $expected = [
  282. 'path' => '繁體中文字/👨‍👩‍👧‍👦.😺😸😹😻.😀😬😁',
  283. 'dirname' => '繁體中文字',
  284. 'basename' => '👨‍👩‍👧‍👦.😺😸😹😻.😀😬😁',
  285. 'extension' => '😀😬😁',
  286. 'filename' => '👨‍👩‍👧‍👦.😺😸😹😻',
  287. ];
  288. $this->assertSame($expected, Util::pathinfo($path));
  289. }
  290. }