FilesystemTests.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. <?php
  2. use League\Flysystem\Config;
  3. use League\Flysystem\FileNotFoundException;
  4. use League\Flysystem\Filesystem;
  5. use League\Flysystem\Util;
  6. use PHPUnit\Framework\TestCase;
  7. use Prophecy\Argument;
  8. use Prophecy\Argument\Token\TypeToken;
  9. use Prophecy\Prophecy\ObjectProphecy;
  10. class FilesystemTests extends TestCase
  11. {
  12. /**
  13. * @var ObjectProphecy
  14. */
  15. protected $prophecy;
  16. /**
  17. * @var AdapterInterface
  18. */
  19. protected $adapter;
  20. /**
  21. * @var Filesystem
  22. */
  23. protected $filesystem;
  24. /**
  25. * @var TypeToken
  26. */
  27. protected $config;
  28. /**
  29. * @var Config
  30. */
  31. private $filesystemConfig;
  32. /**
  33. * @before
  34. */
  35. public function setupAdapter()
  36. {
  37. $this->prophecy = $this->prophesize('League\\Flysystem\\AdapterInterface');
  38. $this->adapter = $this->prophecy->reveal();
  39. $this->filesystemConfig = new Config();
  40. $this->filesystem = new Filesystem($this->adapter, $this->filesystemConfig);
  41. $this->config = Argument::type('League\\Flysystem\\Config');
  42. }
  43. public function testGetAdapter()
  44. {
  45. $this->assertEquals($this->adapter, $this->filesystem->getAdapter());
  46. }
  47. public function testGetConfig()
  48. {
  49. $this->assertInstanceOf('League\\Flysystem\\Config', $this->filesystem->getConfig());
  50. }
  51. public function testHas()
  52. {
  53. $this->prophecy->has('path.txt')->willReturn(true);
  54. $this->assertTrue($this->filesystem->has('path.txt'));
  55. }
  56. public function testWrite()
  57. {
  58. $path = 'path.txt';
  59. $contents = 'contents';
  60. $this->prophecy->has($path)->willReturn(false);
  61. $this->prophecy->write($path, $contents, $this->config)->willReturn(compact('path', 'contents'));
  62. $this->assertTrue($this->filesystem->write($path, $contents));
  63. }
  64. public function testWriteWithoutAsserts()
  65. {
  66. $this->filesystemConfig->set('disable_asserts', true);
  67. $path = 'path.txt';
  68. $contents = 'contents';
  69. $this->prophecy->write($path, $contents, $this->config)->willReturn(compact('path', 'contents'));
  70. $this->assertTrue($this->filesystem->write($path, $contents));
  71. }
  72. public function testWriteStream()
  73. {
  74. $path = 'path.txt';
  75. $stream = tmpfile();
  76. $this->prophecy->has($path)->willReturn(false);
  77. $this->prophecy->writeStream($path, $stream, $this->config)->willReturn(compact('path'));
  78. $this->assertTrue($this->filesystem->writeStream($path, $stream));
  79. fclose($stream);
  80. }
  81. public function testUpdate()
  82. {
  83. $path = 'path.txt';
  84. $contents = 'contents';
  85. $this->prophecy->has($path)->willReturn(true);
  86. $this->prophecy->update($path, $contents, $this->config)->willReturn(compact('path', 'contents'));
  87. $this->assertTrue($this->filesystem->update($path, $contents));
  88. }
  89. public function testUpdateStream()
  90. {
  91. $path = 'path.txt';
  92. $stream = tmpfile();
  93. $this->prophecy->has($path)->willReturn(true);
  94. $this->prophecy->updateStream($path, $stream, $this->config)->willReturn(compact('path'));
  95. $this->assertTrue($this->filesystem->updateStream($path, $stream));
  96. fclose($stream);
  97. }
  98. public function testPutNew()
  99. {
  100. $path = 'path.txt';
  101. $contents = 'contents';
  102. $this->prophecy->has($path)->willReturn(false);
  103. $this->prophecy->write($path, $contents, $this->config)->willReturn(compact('path', 'contents'));
  104. $this->assertTrue($this->filesystem->put($path, $contents));
  105. }
  106. public function testPutNewStream()
  107. {
  108. $path = 'path.txt';
  109. $stream = tmpfile();
  110. $this->prophecy->has($path)->willReturn(false);
  111. $this->prophecy->writeStream($path, $stream, $this->config)->willReturn(compact('path'));
  112. $this->assertTrue($this->filesystem->putStream($path, $stream));
  113. fclose($stream);
  114. }
  115. public function testPutUpdate()
  116. {
  117. $path = 'path.txt';
  118. $contents = 'contents';
  119. $this->prophecy->has($path)->willReturn(true);
  120. $this->prophecy->update($path, $contents, $this->config)->willReturn(compact('path', 'contents'));
  121. $this->assertTrue($this->filesystem->put($path, $contents));
  122. }
  123. public function testPutUpdateStream()
  124. {
  125. $path = 'path.txt';
  126. $stream = tmpfile();
  127. $this->prophecy->has($path)->willReturn(true);
  128. $this->prophecy->updateStream($path, $stream, $this->config)->willReturn(compact('path'));
  129. $this->assertTrue($this->filesystem->putStream($path, $stream));
  130. fclose($stream);
  131. }
  132. public function testPutStreamInvalid()
  133. {
  134. $this->expectException('InvalidArgumentException');
  135. $this->filesystem->putStream('path.txt', '__INVALID__');
  136. }
  137. /**
  138. * @dataProvider methodsThatGuardAgainstClosedResources
  139. */
  140. public function testSupplyingClosedStreams($method)
  141. {
  142. $handle = tmpfile();
  143. fclose($handle);
  144. $this->expectException('InvalidArgumentException');
  145. $this->filesystem->{$method}('path.txt', $handle);
  146. }
  147. public function methodsThatGuardAgainstClosedResources()
  148. {
  149. return [
  150. ['putStream'],
  151. ['writeStream'],
  152. ['updateStream'],
  153. ];
  154. }
  155. public function testWriteStreamInvalid()
  156. {
  157. $this->expectException('InvalidArgumentException');
  158. $this->filesystem->writeStream('path.txt', '__INVALID__');
  159. }
  160. public function testUpdateStreamInvalid()
  161. {
  162. $this->expectException('InvalidArgumentException');
  163. $this->filesystem->updateStream('path.txt', '__INVALID__');
  164. }
  165. public function testReadAndDelete()
  166. {
  167. $path = 'path.txt';
  168. $output = '__CONTENTS__';
  169. $this->prophecy->has($path)->willReturn(true);
  170. $this->prophecy->read($path)->willReturn(['contents' => $output]);
  171. $this->prophecy->delete($path)->willReturn(true);
  172. $response = $this->filesystem->readAndDelete($path);
  173. $this->assertEquals($output, $response);
  174. }
  175. public function testReadAndDeleteFailedRead()
  176. {
  177. $path = 'path.txt';
  178. $this->prophecy->has($path)->willReturn(true);
  179. $this->prophecy->read($path)->willReturn(false);
  180. $response = $this->filesystem->readAndDelete($path);
  181. $this->assertFalse($response);
  182. }
  183. public function testRead()
  184. {
  185. $path = 'path.txt';
  186. $output = '__CONTENTS__';
  187. $this->prophecy->has($path)->willReturn(true);
  188. $this->prophecy->read($path)->willReturn(['contents' => $output]);
  189. $response = $this->filesystem->read($path);
  190. $this->assertEquals($response, $output);
  191. }
  192. public function testReadStream()
  193. {
  194. $path = 'path.txt';
  195. $output = '__CONTENTS__';
  196. $this->prophecy->has($path)->willReturn(true);
  197. $this->prophecy->readStream($path)->willReturn(['stream' => $output]);
  198. $response = $this->filesystem->readStream($path);
  199. $this->assertEquals($response, $output);
  200. }
  201. public function testReadStreamFail()
  202. {
  203. $path = 'path.txt';
  204. $this->prophecy->has($path)->willReturn(true);
  205. $this->prophecy->readStream($path)->willReturn(false);
  206. $response = $this->filesystem->readStream($path);
  207. $this->assertFalse($response);
  208. }
  209. public function testRename()
  210. {
  211. $old = 'old.txt';
  212. $new = 'new.txt';
  213. $this->prophecy->has(Argument::any())->willReturn(true, false);
  214. $this->prophecy->rename($old, $new)->willReturn(true);
  215. $response = $this->filesystem->rename($old, $new);
  216. $this->assertTrue($response);
  217. }
  218. public function testCopy()
  219. {
  220. $old = 'old.txt';
  221. $new = 'new.txt';
  222. $this->prophecy->has(Argument::any())->willReturn(true, false);
  223. $this->prophecy->copy($old, $new)->willReturn(true);
  224. $response = $this->filesystem->copy($old, $new);
  225. $this->assertTrue($response);
  226. }
  227. public function testCopyWithoutAsserts()
  228. {
  229. $old = 'old.txt';
  230. $new = 'new.txt';
  231. $this->filesystemConfig->set('disable_asserts', true);
  232. $this->prophecy->copy($old, $new)->willReturn(true);
  233. $response = $this->filesystem->copy($old, $new);
  234. $this->assertTrue($response);
  235. }
  236. public function testDeleteDirRootViolation()
  237. {
  238. $this->expectException('League\Flysystem\RootViolationException');
  239. $this->filesystem->deleteDir('');
  240. }
  241. public function testDeleteDir()
  242. {
  243. $this->prophecy->deleteDir('dirname')->willReturn(true);
  244. $response = $this->filesystem->deleteDir('dirname');
  245. $this->assertTrue($response);
  246. }
  247. public function testCreateDir()
  248. {
  249. $this->prophecy->createDir('dirname', $this->config)->willReturn(['path' => 'dirname', 'type' => 'dir']);
  250. $output = $this->filesystem->createDir('dirname');
  251. $this->assertTrue($output);
  252. }
  253. public function metaGetterProvider()
  254. {
  255. return [
  256. ['getSize', 1234],
  257. ['getVisibility', 'public'],
  258. ['getMimetype', 'text/plain'],
  259. ['getTimestamp', 2345],
  260. ['getMetadata', [
  261. 'path' => 'success.txt',
  262. 'size' => 1234,
  263. 'visibility' => 'public',
  264. 'mimetype' => 'text/plain',
  265. 'timestamp' => 2345,
  266. ]],
  267. ];
  268. }
  269. /**
  270. * @dataProvider metaGetterProvider
  271. */
  272. public function testMetaGetterSuccess($method, $value)
  273. {
  274. $path = 'success.txt';
  275. $this->prophecy->has($path)->willReturn(true);
  276. $this->prophecy->{$method}($path)->willReturn([
  277. 'path' => $path,
  278. 'size' => 1234,
  279. 'visibility' => 'public',
  280. 'mimetype' => 'text/plain',
  281. 'timestamp' => 2345,
  282. ]);
  283. $output = $this->filesystem->{$method}($path);
  284. $this->assertEquals($value, $output);
  285. }
  286. /**
  287. * @dataProvider metaGetterProvider
  288. */
  289. public function testMetaGetterFails($method)
  290. {
  291. $path = 'success.txt';
  292. $this->prophecy->has($path)->willReturn(true);
  293. $this->prophecy->{$method}($path)->willReturn(false);
  294. $output = $this->filesystem->{$method}($path);
  295. $this->assertFalse($output);
  296. }
  297. public function testGetSizeOnFileThatDoesNotExist()
  298. {
  299. $this->expectException(FileNotFoundException::class);
  300. $this->prophecy->has('path.txt')->willReturn(false);
  301. $this->filesystem->getSize('path.txt');
  302. }
  303. public function testAssertPresentThrowsException()
  304. {
  305. $this->expectException('League\Flysystem\FileExistsException');
  306. $this->prophecy->has('path.txt')->willReturn(true);
  307. $this->filesystem->write('path.txt', 'contents');
  308. }
  309. public function testAssertAbsentThrowsException()
  310. {
  311. $this->expectException('League\Flysystem\FileNotFoundException');
  312. $this->prophecy->has('path.txt')->willReturn(false);
  313. $this->filesystem->read('path.txt');
  314. }
  315. public function testSetVisibility()
  316. {
  317. $path = 'path.txt';
  318. $this->prophecy->has($path)->willReturn(true);
  319. $this->prophecy->setVisibility($path, 'public')->willReturn(['path' => $path, 'visibility' => 'public']);
  320. $output = $this->filesystem->setVisibility($path, 'public');
  321. $this->assertTrue($output);
  322. }
  323. public function testSetVisibilityOnFileThatDoesNotExist()
  324. {
  325. $this->expectException(FileNotFoundException::class);
  326. $this->prophecy->has('path.txt')->willReturn(false);
  327. $this->filesystem->setVisibility('path.txt', 'public');
  328. }
  329. public function testSetVisibilityFail()
  330. {
  331. $path = 'path.txt';
  332. $this->prophecy->has($path)->willReturn(true);
  333. $this->prophecy->setVisibility($path, 'public')->willReturn(false);
  334. $output = $this->filesystem->setVisibility($path, 'public');
  335. $this->assertFalse($output);
  336. }
  337. public function testGetFile()
  338. {
  339. $path = 'path.txt';
  340. $this->prophecy->has($path)->willReturn(true);
  341. $this->prophecy->getMetadata($path)->willReturn([
  342. 'path' => $path,
  343. 'type' => 'file',
  344. ]);
  345. $output = $this->filesystem->get($path);
  346. $this->assertInstanceOf('League\Flysystem\File', $output);
  347. }
  348. public function testGetDirectory()
  349. {
  350. $path = 'path';
  351. $this->prophecy->has($path)->willReturn(true);
  352. $this->prophecy->getMetadata($path)->willReturn([
  353. 'path' => $path,
  354. 'type' => 'dir',
  355. ]);
  356. $output = $this->filesystem->get($path);
  357. $this->assertInstanceOf('League\Flysystem\Directory', $output);
  358. }
  359. public function testListContents()
  360. {
  361. $rawListing = [
  362. ['path' => 'other_root/file.txt'],
  363. ['path' => 'valid/to_deep/file.txt'],
  364. ['path' => 'valid/file.txt'],
  365. ['path' => 'valid/a-valid-file.txt'],
  366. ];
  367. $expected = [
  368. Util::pathinfo('valid/a-valid-file.txt'),
  369. Util::pathinfo('valid/file.txt'),
  370. ];
  371. $this->prophecy->listContents('valid', false)->willReturn($rawListing);
  372. $output = $this->filesystem->listContents('valid', false);
  373. $this->assertEquals($expected, $output);
  374. }
  375. public function testListContentZeroName()
  376. {
  377. $rawListing = [
  378. // files
  379. ['path' => 0],
  380. ['path' => '0'],
  381. ['path' => ''],
  382. // directories
  383. ['path' => 0, 'type' => 'dir'],
  384. ['path' => '0', 'type' => 'dir'],
  385. ['path' => '', 'type' => 'dir']
  386. ];
  387. $this->prophecy->listContents('', false)->willReturn($rawListing);
  388. $output = $this->filesystem->listContents('', false);
  389. $this->assertCount(2, $output);
  390. }
  391. public function testListContentsRecursize()
  392. {
  393. $rawListing = [
  394. ['path' => 'other_root/file.txt'],
  395. ['path' => 'valid/to_deep/file.txt'],
  396. ['path' => 'valid/file.txt'],
  397. ['path' => 'valid/a-valid-file.txt'],
  398. ];
  399. $expected = [
  400. Util::pathinfo('valid/a-valid-file.txt'),
  401. Util::pathinfo('valid/file.txt'),
  402. Util::pathinfo('valid/to_deep/file.txt'),
  403. ];
  404. $this->prophecy->listContents('valid', true)->willReturn($rawListing);
  405. $output = $this->filesystem->listContents('valid', true);
  406. $this->assertEquals($expected, $output);
  407. $expected = [
  408. Util::pathinfo('other_root/file.txt'),
  409. Util::pathinfo('valid/a-valid-file.txt'),
  410. Util::pathinfo('valid/file.txt'),
  411. Util::pathinfo('valid/to_deep/file.txt'),
  412. ];
  413. $this->prophecy->listContents('', true)->willReturn($rawListing);
  414. $output = $this->filesystem->listContents('', true);
  415. $this->assertEquals($expected, $output);
  416. }
  417. public function testListContentsSubDirectoryMatches()
  418. {
  419. $rawListing = [['path' => 'a/dir/file.txt']];
  420. $this->prophecy->listContents('dir', true)->willReturn($rawListing);
  421. $output = $this->filesystem->listContents('dir', true);
  422. $this->assertEquals([], $output);
  423. }
  424. public function testInvalidPluginCall()
  425. {
  426. $this->expectException('BadMethodCallException');
  427. $this->filesystem->invalidCall();
  428. }
  429. }