FileCacheManagerTest.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of PHP CS Fixer.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. namespace PhpCsFixer\Tests\Cache;
  13. use PhpCsFixer\Cache\CacheInterface;
  14. use PhpCsFixer\Cache\CacheManagerInterface;
  15. use PhpCsFixer\Cache\FileCacheManager;
  16. use PhpCsFixer\Cache\FileHandlerInterface;
  17. use PhpCsFixer\Cache\SignatureInterface;
  18. use PhpCsFixer\Tests\TestCase;
  19. use Prophecy\Argument;
  20. /**
  21. * @author Andreas Möller <am@localheinz.com>
  22. *
  23. * @internal
  24. *
  25. * @covers \PhpCsFixer\Cache\FileCacheManager
  26. */
  27. final class FileCacheManagerTest extends TestCase
  28. {
  29. public function testIsFinal(): void
  30. {
  31. $reflection = new \ReflectionClass(FileCacheManager::class);
  32. self::assertTrue($reflection->isFinal());
  33. }
  34. public function testImplementsCacheManagerInterface(): void
  35. {
  36. $reflection = new \ReflectionClass(FileCacheManager::class);
  37. self::assertTrue($reflection->implementsInterface(CacheManagerInterface::class));
  38. }
  39. public function testCreatesCacheIfHandlerReturnedNoCache(): void
  40. {
  41. $signature = $this->prophesize(SignatureInterface::class)->reveal();
  42. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  43. $handlerProphecy->read()->shouldBeCalled()->willReturn(null);
  44. $handlerProphecy->write(Argument::that(static function (CacheInterface $cache) use ($signature): bool {
  45. return $cache->getSignature() === $signature;
  46. }))->shouldBeCalled();
  47. $handler = $handlerProphecy->reveal();
  48. $manager = new FileCacheManager(
  49. $handler,
  50. $signature
  51. );
  52. unset($manager);
  53. }
  54. public function testCreatesCacheIfCachedSignatureIsDifferent(): void
  55. {
  56. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  57. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  58. $signatureProphecy->equals(Argument::is($cachedSignature))->shouldBeCalled()->willReturn(false);
  59. $signature = $signatureProphecy->reveal();
  60. $cacheProphecy = $this->prophesize(CacheInterface::class);
  61. $cacheProphecy->getSignature()->shouldBeCalled()->willReturn($cachedSignature);
  62. $cache = $cacheProphecy->reveal();
  63. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  64. $handlerProphecy->read()->shouldBeCalled()->willReturn($cache);
  65. $handlerProphecy->write(Argument::that(static function (CacheInterface $cache) use ($signature): bool {
  66. return $cache->getSignature() === $signature;
  67. }))->shouldBeCalled();
  68. $handler = $handlerProphecy->reveal();
  69. $manager = new FileCacheManager(
  70. $handler,
  71. $signature
  72. );
  73. unset($manager);
  74. }
  75. public function testUsesCacheIfCachedSignatureIsEqual(): void
  76. {
  77. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  78. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  79. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  80. $signature = $signatureProphecy->reveal();
  81. $cacheProphecy = $this->prophesize(CacheInterface::class);
  82. $cacheProphecy->getSignature()->shouldBeCalled()->willReturn($cachedSignature);
  83. $cache = $cacheProphecy->reveal();
  84. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  85. $handlerProphecy->read()->shouldBeCalled()->willReturn($cache);
  86. $handlerProphecy->write(Argument::is($cache))->shouldBeCalled();
  87. $handler = $handlerProphecy->reveal();
  88. $manager = new FileCacheManager(
  89. $handler,
  90. $signature
  91. );
  92. unset($manager);
  93. }
  94. public function testNeedFixingReturnsTrueIfCacheHasNoHash(): void
  95. {
  96. $file = 'hello.php';
  97. $fileContent = '<?php echo "Hello!"';
  98. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  99. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  100. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  101. $signature = $signatureProphecy->reveal();
  102. $cacheProphecy = $this->prophesize(CacheInterface::class);
  103. $cacheProphecy->getSignature()->willReturn($cachedSignature);
  104. $cacheProphecy->has(Argument::is($file))->willReturn(false);
  105. $cache = $cacheProphecy->reveal();
  106. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  107. $handlerProphecy->read()->willReturn($cache);
  108. $handlerProphecy->getFile()->willReturn($this->getFile());
  109. $handlerProphecy->write(Argument::is($cache));
  110. $handler = $handlerProphecy->reveal();
  111. $manager = new FileCacheManager(
  112. $handler,
  113. $signature
  114. );
  115. self::assertTrue($manager->needFixing($file, $fileContent));
  116. }
  117. public function testNeedFixingReturnsTrueIfCachedHashIsDifferent(): void
  118. {
  119. $file = 'hello.php';
  120. $fileContent = '<?php echo "Hello!"';
  121. $previousFileContent = '<?php echo "Hello, world!"';
  122. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  123. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  124. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  125. $signature = $signatureProphecy->reveal();
  126. $cacheProphecy = $this->prophesize(CacheInterface::class);
  127. $cacheProphecy->getSignature()->willReturn($cachedSignature);
  128. $cacheProphecy->has(Argument::is($file))->willReturn(true);
  129. $cacheProphecy->get(Argument::is($file))->willReturn(md5($previousFileContent));
  130. $cache = $cacheProphecy->reveal();
  131. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  132. $handlerProphecy->read()->willReturn($cache);
  133. $handlerProphecy->getFile()->willReturn($this->getFile());
  134. $handlerProphecy->write(Argument::is($cache));
  135. $handler = $handlerProphecy->reveal();
  136. $manager = new FileCacheManager(
  137. $handler,
  138. $signature
  139. );
  140. self::assertTrue($manager->needFixing($file, $fileContent));
  141. }
  142. public function testNeedFixingReturnsFalseIfCachedHashIsIdentical(): void
  143. {
  144. $file = 'hello.php';
  145. $fileContent = '<?php echo "Hello!"';
  146. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  147. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  148. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  149. $signature = $signatureProphecy->reveal();
  150. $cacheProphecy = $this->prophesize(CacheInterface::class);
  151. $cacheProphecy->getSignature()->willReturn($cachedSignature);
  152. $cacheProphecy->has(Argument::is($file))->willReturn(true);
  153. $cacheProphecy->get(Argument::is($file))->willReturn(md5($fileContent));
  154. $cache = $cacheProphecy->reveal();
  155. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  156. $handlerProphecy->read()->willReturn($cache);
  157. $handlerProphecy->getFile()->willReturn($this->getFile());
  158. $handlerProphecy->write(Argument::is($cache));
  159. $handler = $handlerProphecy->reveal();
  160. $manager = new FileCacheManager(
  161. $handler,
  162. $signature
  163. );
  164. self::assertFalse($manager->needFixing($file, $fileContent));
  165. }
  166. public function testNeedFixingUsesRelativePathToFile(): void
  167. {
  168. $cacheFile = $this->getFile();
  169. $file = '/foo/bar/baz/src/hello.php';
  170. $relativePathToFile = 'src/hello.php';
  171. $fileContent = '<?php echo "Hello!"';
  172. $directoryProphecy = $this->prophesize(\PhpCsFixer\Cache\DirectoryInterface::class);
  173. $directoryProphecy->getRelativePathTo(Argument::is($file))->willReturn($relativePathToFile);
  174. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  175. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  176. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  177. $signature = $signatureProphecy->reveal();
  178. $cacheProphecy = $this->prophesize(CacheInterface::class);
  179. $cacheProphecy->getSignature()->willReturn($cachedSignature);
  180. $cacheProphecy->has(Argument::is($relativePathToFile))->willReturn(true);
  181. $cacheProphecy->has(Argument::is($relativePathToFile))->willReturn(0);
  182. $cache = $cacheProphecy->reveal();
  183. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  184. $handlerProphecy->read()->willReturn($cache);
  185. $handlerProphecy->getFile()->willReturn($cacheFile);
  186. $handlerProphecy->write(Argument::is($cache));
  187. $handler = $handlerProphecy->reveal();
  188. $manager = new FileCacheManager(
  189. $handler,
  190. $signature,
  191. false,
  192. $directoryProphecy->reveal()
  193. );
  194. self::assertTrue($manager->needFixing($file, $fileContent));
  195. }
  196. public function testSetFileSetsHashOfFileContent(): void
  197. {
  198. $cacheFile = $this->getFile();
  199. $file = 'hello.php';
  200. $fileContent = '<?php echo "Hello!"';
  201. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  202. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  203. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  204. $signature = $signatureProphecy->reveal();
  205. $cacheProphecy = $this->prophesize(CacheInterface::class);
  206. $cacheProphecy->getSignature()->willReturn($cachedSignature);
  207. $cacheProphecy->set(Argument::is($file), Argument::is(md5($fileContent)))->shouldBeCalled();
  208. $cache = $cacheProphecy->reveal();
  209. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  210. $handlerProphecy->read()->willReturn($cache);
  211. $handlerProphecy->getFile()->willReturn($cacheFile);
  212. $handlerProphecy->write(Argument::is($cache));
  213. $handler = $handlerProphecy->reveal();
  214. $manager = new FileCacheManager(
  215. $handler,
  216. $signature
  217. );
  218. $manager->setFile($file, $fileContent);
  219. }
  220. public function testSetFileSetsHashOfFileContentDuringDryRunIfCacheHasNoHash(): void
  221. {
  222. $isDryRun = true;
  223. $cacheFile = $this->getFile();
  224. $file = 'hello.php';
  225. $fileContent = '<?php echo "Hello!"';
  226. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  227. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  228. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  229. $signature = $signatureProphecy->reveal();
  230. $cacheProphecy = $this->prophesize(CacheInterface::class);
  231. $cacheProphecy->getSignature()->willReturn($cachedSignature);
  232. $cacheProphecy->has(Argument::is($file))->willReturn(false);
  233. $cacheProphecy->set(Argument::is($file), Argument::is(md5($fileContent)))->shouldBeCalled();
  234. $cache = $cacheProphecy->reveal();
  235. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  236. $handlerProphecy->read()->willReturn($cache);
  237. $handlerProphecy->getFile()->willReturn($cacheFile);
  238. $handlerProphecy->write(Argument::is($cache));
  239. $handler = $handlerProphecy->reveal();
  240. $manager = new FileCacheManager(
  241. $handler,
  242. $signature,
  243. $isDryRun
  244. );
  245. $manager->setFile($file, $fileContent);
  246. }
  247. public function testSetFileClearsHashDuringDryRunIfCachedHashIsDifferent(): void
  248. {
  249. $isDryRun = true;
  250. $cacheFile = $this->getFile();
  251. $file = 'hello.php';
  252. $fileContent = '<?php echo "Hello!"';
  253. $previousFileContent = '<?php echo "Hello, world!"';
  254. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  255. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  256. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  257. $signature = $signatureProphecy->reveal();
  258. $cacheProphecy = $this->prophesize(CacheInterface::class);
  259. $cacheProphecy->getSignature()->willReturn($cachedSignature);
  260. $cacheProphecy->has(Argument::is($file))->willReturn(true);
  261. $cacheProphecy->get(Argument::is($file))->willReturn(md5($previousFileContent));
  262. $cacheProphecy->clear(Argument::is($file))->shouldBeCalled();
  263. $cache = $cacheProphecy->reveal();
  264. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  265. $handlerProphecy->read()->willReturn($cache);
  266. $handlerProphecy->getFile()->willReturn($cacheFile);
  267. $handlerProphecy->write(Argument::is($cache));
  268. $handler = $handlerProphecy->reveal();
  269. $manager = new FileCacheManager(
  270. $handler,
  271. $signature,
  272. $isDryRun
  273. );
  274. $manager->setFile($file, $fileContent);
  275. }
  276. public function testSetFileUsesRelativePathToFile(): void
  277. {
  278. $cacheFile = $this->getFile();
  279. $file = '/foo/bar/baz/src/hello.php';
  280. $relativePathToFile = 'src/hello.php';
  281. $fileContent = '<?php echo "Hello!"';
  282. $directoryProphecy = $this->prophesize(\PhpCsFixer\Cache\DirectoryInterface::class);
  283. $directoryProphecy->getRelativePathTo(Argument::is($file))->willReturn($relativePathToFile);
  284. $cachedSignature = $this->prophesize(SignatureInterface::class)->reveal();
  285. $signatureProphecy = $this->prophesize(SignatureInterface::class);
  286. $signatureProphecy->equals(Argument::is($cachedSignature))->willReturn(true);
  287. $signature = $signatureProphecy->reveal();
  288. $cacheProphecy = $this->prophesize(CacheInterface::class);
  289. $cacheProphecy->getSignature()->willReturn($cachedSignature);
  290. $cacheProphecy->set(Argument::is($relativePathToFile), Argument::is(md5($fileContent)))->shouldBeCalled();
  291. $cache = $cacheProphecy->reveal();
  292. $handlerProphecy = $this->prophesize(FileHandlerInterface::class);
  293. $handlerProphecy->read()->willReturn($cache);
  294. $handlerProphecy->getFile()->willReturn($cacheFile);
  295. $handlerProphecy->write(Argument::is($cache));
  296. $handler = $handlerProphecy->reveal();
  297. $manager = new FileCacheManager(
  298. $handler,
  299. $signature,
  300. false,
  301. $directoryProphecy->reveal()
  302. );
  303. $manager->setFile($file, $fileContent);
  304. }
  305. private function getFile(): string
  306. {
  307. return __DIR__.'/../Fixtures/.php_cs.empty-cache';
  308. }
  309. }