CachedAdapterSpec.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <?php
  2. namespace spec\League\Flysystem\Cached;
  3. use League\Flysystem\AdapterInterface;
  4. use League\Flysystem\Cached\CacheInterface;
  5. use League\Flysystem\Config;
  6. use PhpSpec\ObjectBehavior;
  7. class CachedAdapterSpec extends ObjectBehavior
  8. {
  9. /**
  10. * @var AdapterInterface
  11. */
  12. private $adapter;
  13. /**
  14. * @var CacheInterface
  15. */
  16. private $cache;
  17. public function let(AdapterInterface $adapter, CacheInterface $cache)
  18. {
  19. $this->adapter = $adapter;
  20. $this->cache = $cache;
  21. $this->cache->load()->shouldBeCalled();
  22. $this->beConstructedWith($adapter, $cache);
  23. }
  24. public function it_is_initializable()
  25. {
  26. $this->shouldHaveType('League\Flysystem\Cached\CachedAdapter');
  27. $this->shouldHaveType('League\Flysystem\AdapterInterface');
  28. }
  29. public function it_should_forward_read_streams()
  30. {
  31. $path = 'path.txt';
  32. $response = ['path' => $path];
  33. $this->adapter->readStream($path)->willReturn($response);
  34. $this->readStream($path)->shouldbe($response);
  35. }
  36. public function it_should_cache_writes()
  37. {
  38. $type = 'file';
  39. $path = 'path.txt';
  40. $contents = 'contents';
  41. $config = new Config();
  42. $response = compact('path', 'contents', 'type');
  43. $this->adapter->write($path, $contents, $config)->willReturn($response);
  44. $this->cache->updateObject($path, $response, true)->shouldBeCalled();
  45. $this->write($path, $contents, $config)->shouldBe($response);
  46. }
  47. public function it_should_cache_streamed_writes()
  48. {
  49. $type = 'file';
  50. $path = 'path.txt';
  51. $stream = tmpfile();
  52. $config = new Config();
  53. $response = compact('path', 'stream', 'type');
  54. $this->adapter->writeStream($path, $stream, $config)->willReturn($response);
  55. $this->cache->updateObject($path, ['contents' => false] + $response, true)->shouldBeCalled();
  56. $this->writeStream($path, $stream, $config)->shouldBe($response);
  57. fclose($stream);
  58. }
  59. public function it_should_cache_streamed_updates()
  60. {
  61. $type = 'file';
  62. $path = 'path.txt';
  63. $stream = tmpfile();
  64. $config = new Config();
  65. $response = compact('path', 'stream', 'type');
  66. $this->adapter->updateStream($path, $stream, $config)->willReturn($response);
  67. $this->cache->updateObject($path, ['contents' => false] + $response, true)->shouldBeCalled();
  68. $this->updateStream($path, $stream, $config)->shouldBe($response);
  69. fclose($stream);
  70. }
  71. public function it_should_ignore_failed_writes()
  72. {
  73. $path = 'path.txt';
  74. $contents = 'contents';
  75. $config = new Config();
  76. $this->adapter->write($path, $contents, $config)->willReturn(false);
  77. $this->write($path, $contents, $config)->shouldBe(false);
  78. }
  79. public function it_should_ignore_failed_streamed_writes()
  80. {
  81. $path = 'path.txt';
  82. $contents = tmpfile();
  83. $config = new Config();
  84. $this->adapter->writeStream($path, $contents, $config)->willReturn(false);
  85. $this->writeStream($path, $contents, $config)->shouldBe(false);
  86. fclose($contents);
  87. }
  88. public function it_should_cache_updated()
  89. {
  90. $type = 'file';
  91. $path = 'path.txt';
  92. $contents = 'contents';
  93. $config = new Config();
  94. $response = compact('path', 'contents', 'type');
  95. $this->adapter->update($path, $contents, $config)->willReturn($response);
  96. $this->cache->updateObject($path, $response, true)->shouldBeCalled();
  97. $this->update($path, $contents, $config)->shouldBe($response);
  98. }
  99. public function it_should_ignore_failed_updates()
  100. {
  101. $path = 'path.txt';
  102. $contents = 'contents';
  103. $config = new Config();
  104. $this->adapter->update($path, $contents, $config)->willReturn(false);
  105. $this->update($path, $contents, $config)->shouldBe(false);
  106. }
  107. public function it_should_ignore_failed_streamed_updates()
  108. {
  109. $path = 'path.txt';
  110. $contents = tmpfile();
  111. $config = new Config();
  112. $this->adapter->updateStream($path, $contents, $config)->willReturn(false);
  113. $this->updateStream($path, $contents, $config)->shouldBe(false);
  114. fclose($contents);
  115. }
  116. public function it_should_cache_renames()
  117. {
  118. $old = 'old.txt';
  119. $new = 'new.txt';
  120. $this->adapter->rename($old, $new)->willReturn(true);
  121. $this->cache->rename($old, $new)->shouldBeCalled();
  122. $this->rename($old, $new)->shouldBe(true);
  123. }
  124. public function it_should_ignore_rename_fails()
  125. {
  126. $old = 'old.txt';
  127. $new = 'new.txt';
  128. $this->adapter->rename($old, $new)->willReturn(false);
  129. $this->rename($old, $new)->shouldBe(false);
  130. }
  131. public function it_should_cache_copies()
  132. {
  133. $old = 'old.txt';
  134. $new = 'new.txt';
  135. $this->adapter->copy($old, $new)->willReturn(true);
  136. $this->cache->copy($old, $new)->shouldBeCalled();
  137. $this->copy($old, $new)->shouldBe(true);
  138. }
  139. public function it_should_ignore_copy_fails()
  140. {
  141. $old = 'old.txt';
  142. $new = 'new.txt';
  143. $this->adapter->copy($old, $new)->willReturn(false);
  144. $this->copy($old, $new)->shouldBe(false);
  145. }
  146. public function it_should_cache_deletes()
  147. {
  148. $delete = 'delete.txt';
  149. $this->adapter->delete($delete)->willReturn(true);
  150. $this->cache->delete($delete)->shouldBeCalled();
  151. $this->delete($delete)->shouldBe(true);
  152. }
  153. public function it_should_ignore_delete_fails()
  154. {
  155. $delete = 'delete.txt';
  156. $this->adapter->delete($delete)->willReturn(false);
  157. $this->delete($delete)->shouldBe(false);
  158. }
  159. public function it_should_cache_dir_deletes()
  160. {
  161. $delete = 'delete';
  162. $this->adapter->deleteDir($delete)->willReturn(true);
  163. $this->cache->deleteDir($delete)->shouldBeCalled();
  164. $this->deleteDir($delete)->shouldBe(true);
  165. }
  166. public function it_should_ignore_delete_dir_fails()
  167. {
  168. $delete = 'delete';
  169. $this->adapter->deleteDir($delete)->willReturn(false);
  170. $this->deleteDir($delete)->shouldBe(false);
  171. }
  172. public function it_should_cache_dir_creates()
  173. {
  174. $dirname = 'dirname';
  175. $config = new Config();
  176. $response = ['path' => $dirname, 'type' => 'dir'];
  177. $this->adapter->createDir($dirname, $config)->willReturn($response);
  178. $this->cache->updateObject($dirname, $response, true)->shouldBeCalled();
  179. $this->createDir($dirname, $config)->shouldBe($response);
  180. }
  181. public function it_should_ignore_create_dir_fails()
  182. {
  183. $dirname = 'dirname';
  184. $config = new Config();
  185. $this->adapter->createDir($dirname, $config)->willReturn(false);
  186. $this->createDir($dirname, $config)->shouldBe(false);
  187. }
  188. public function it_should_cache_set_visibility()
  189. {
  190. $path = 'path.txt';
  191. $visibility = AdapterInterface::VISIBILITY_PUBLIC;
  192. $this->adapter->setVisibility($path, $visibility)->willReturn(true);
  193. $this->cache->updateObject($path, ['path' => $path, 'visibility' => $visibility], true)->shouldBeCalled();
  194. $this->setVisibility($path, $visibility)->shouldBe(true);
  195. }
  196. public function it_should_ignore_set_visibility_fails()
  197. {
  198. $dirname = 'delete';
  199. $visibility = AdapterInterface::VISIBILITY_PUBLIC;
  200. $this->adapter->setVisibility($dirname, $visibility)->willReturn(false);
  201. $this->setVisibility($dirname, $visibility)->shouldBe(false);
  202. }
  203. public function it_should_indicate_missing_files()
  204. {
  205. $this->cache->has($path = 'path.txt')->willReturn(false);
  206. $this->has($path)->shouldBe(false);
  207. }
  208. public function it_should_indicate_file_existance()
  209. {
  210. $this->cache->has($path = 'path.txt')->willReturn(true);
  211. $this->has($path)->shouldBe(true);
  212. }
  213. public function it_should_cache_missing_files()
  214. {
  215. $this->cache->has($path = 'path.txt')->willReturn(null);
  216. $this->adapter->has($path)->willReturn(false);
  217. $this->cache->storeMiss($path)->shouldBeCalled();
  218. $this->has($path)->shouldBe(false);
  219. }
  220. public function it_should_delete_when_metadata_is_missing()
  221. {
  222. $path = 'path.txt';
  223. $this->cache->has($path)->willReturn(true);
  224. $this->cache->getSize($path)->willReturn(['path' => $path]);
  225. $this->adapter->getSize($path)->willReturn($response = ['path' => $path, 'size' => 1024]);
  226. $this->cache->updateObject($path, $response, true)->shouldBeCalled();
  227. $this->getSize($path)->shouldBe($response);
  228. }
  229. public function it_should_cache_has()
  230. {
  231. $this->cache->has($path = 'path.txt')->willReturn(null);
  232. $this->adapter->has($path)->willReturn(true);
  233. $this->cache->updateObject($path, compact('path'), true)->shouldBeCalled();
  234. $this->has($path)->shouldBe(true);
  235. }
  236. public function it_should_list_cached_contents()
  237. {
  238. $this->cache->isComplete($dirname = 'dirname', $recursive = true)->willReturn(true);
  239. $response = [['path' => 'path.txt']];
  240. $this->cache->listContents($dirname, $recursive)->willReturn($response);
  241. $this->listContents($dirname, $recursive)->shouldBe($response);
  242. }
  243. public function it_should_ignore_failed_list_contents()
  244. {
  245. $this->cache->isComplete($dirname = 'dirname', $recursive = true)->willReturn(false);
  246. $this->adapter->listContents($dirname, $recursive)->willReturn(false);
  247. $this->listContents($dirname, $recursive)->shouldBe(false);
  248. }
  249. public function it_should_cache_contents_listings()
  250. {
  251. $this->cache->isComplete($dirname = 'dirname', $recursive = true)->willReturn(false);
  252. $response = [['path' => 'path.txt']];
  253. $this->adapter->listContents($dirname, $recursive)->willReturn($response);
  254. $this->cache->storeContents($dirname, $response, $recursive)->shouldBeCalled();
  255. $this->listContents($dirname, $recursive)->shouldBe($response);
  256. }
  257. public function it_should_use_cached_visibility()
  258. {
  259. $this->make_it_use_getter_cache('getVisibility', 'path.txt', [
  260. 'path' => 'path.txt',
  261. 'visibility' => AdapterInterface::VISIBILITY_PUBLIC,
  262. ]);
  263. }
  264. public function it_should_cache_get_visibility()
  265. {
  266. $path = 'path.txt';
  267. $response = ['visibility' => AdapterInterface::VISIBILITY_PUBLIC, 'path' => $path];
  268. $this->make_it_cache_getter('getVisibility', $path, $response);
  269. }
  270. public function it_should_ignore_failed_get_visibility()
  271. {
  272. $path = 'path.txt';
  273. $this->make_it_ignore_failed_getter('getVisibility', $path);
  274. }
  275. public function it_should_use_cached_timestamp()
  276. {
  277. $this->make_it_use_getter_cache('getTimestamp', 'path.txt', [
  278. 'path' => 'path.txt',
  279. 'timestamp' => 1234,
  280. ]);
  281. }
  282. public function it_should_cache_timestamps()
  283. {
  284. $this->make_it_cache_getter('getTimestamp', 'path.txt', [
  285. 'path' => 'path.txt',
  286. 'timestamp' => 1234,
  287. ]);
  288. }
  289. public function it_should_ignore_failed_get_timestamps()
  290. {
  291. $this->make_it_ignore_failed_getter('getTimestamp', 'path.txt');
  292. }
  293. public function it_should_cache_get_metadata()
  294. {
  295. $path = 'path.txt';
  296. $response = ['visibility' => AdapterInterface::VISIBILITY_PUBLIC, 'path' => $path];
  297. $this->make_it_cache_getter('getMetadata', $path, $response);
  298. }
  299. public function it_should_use_cached_metadata()
  300. {
  301. $this->make_it_use_getter_cache('getMetadata', 'path.txt', [
  302. 'path' => 'path.txt',
  303. 'timestamp' => 1234,
  304. ]);
  305. }
  306. public function it_should_ignore_failed_get_metadata()
  307. {
  308. $this->make_it_ignore_failed_getter('getMetadata', 'path.txt');
  309. }
  310. public function it_should_cache_get_size()
  311. {
  312. $path = 'path.txt';
  313. $response = ['size' => 1234, 'path' => $path];
  314. $this->make_it_cache_getter('getSize', $path, $response);
  315. }
  316. public function it_should_use_cached_size()
  317. {
  318. $this->make_it_use_getter_cache('getSize', 'path.txt', [
  319. 'path' => 'path.txt',
  320. 'size' => 1234,
  321. ]);
  322. }
  323. public function it_should_ignore_failed_get_size()
  324. {
  325. $this->make_it_ignore_failed_getter('getSize', 'path.txt');
  326. }
  327. public function it_should_cache_get_mimetype()
  328. {
  329. $path = 'path.txt';
  330. $response = ['mimetype' => 'text/plain', 'path' => $path];
  331. $this->make_it_cache_getter('getMimetype', $path, $response);
  332. }
  333. public function it_should_use_cached_mimetype()
  334. {
  335. $this->make_it_use_getter_cache('getMimetype', 'path.txt', [
  336. 'path' => 'path.txt',
  337. 'mimetype' => 'text/plain',
  338. ]);
  339. }
  340. public function it_should_ignore_failed_get_mimetype()
  341. {
  342. $this->make_it_ignore_failed_getter('getMimetype', 'path.txt');
  343. }
  344. public function it_should_cache_reads()
  345. {
  346. $path = 'path.txt';
  347. $response = ['path' => $path, 'contents' => 'contents'];
  348. $this->make_it_cache_getter('read', $path, $response);
  349. }
  350. public function it_should_use_cached_file_contents()
  351. {
  352. $this->make_it_use_getter_cache('read', 'path.txt', [
  353. 'path' => 'path.txt',
  354. 'contents' => 'contents'
  355. ]);
  356. }
  357. public function it_should_ignore_failed_reads()
  358. {
  359. $this->make_it_ignore_failed_getter('read', 'path.txt');
  360. }
  361. protected function make_it_use_getter_cache($method, $path, $response)
  362. {
  363. $this->cache->{$method}($path)->willReturn($response);
  364. $this->{$method}($path)->shouldBe($response);
  365. }
  366. protected function make_it_cache_getter($method, $path, $response)
  367. {
  368. $this->cache->{$method}($path)->willReturn(false);
  369. $this->adapter->{$method}($path)->willReturn($response);
  370. $this->cache->updateObject($path, $response, true)->shouldBeCalled();
  371. $this->{$method}($path)->shouldBe($response);
  372. }
  373. protected function make_it_ignore_failed_getter($method, $path)
  374. {
  375. $this->cache->{$method}($path)->willReturn(false);
  376. $this->adapter->{$method}($path)->willReturn(false);
  377. $this->{$method}($path)->shouldBe(false);
  378. }
  379. }