CacheTest.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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\Cache;
  14. use PhpCsFixer\Cache\CacheInterface;
  15. use PhpCsFixer\Cache\Signature;
  16. use PhpCsFixer\Cache\SignatureInterface;
  17. use PhpCsFixer\Config;
  18. use PhpCsFixer\Tests\TestCase;
  19. use PhpCsFixer\ToolInfo;
  20. /**
  21. * @author Andreas Möller <am@localheinz.com>
  22. *
  23. * @internal
  24. *
  25. * @covers \PhpCsFixer\Cache\Cache
  26. */
  27. final class CacheTest extends TestCase
  28. {
  29. public function testIsFinal(): void
  30. {
  31. $reflection = new \ReflectionClass(Cache::class);
  32. self::assertTrue($reflection->isFinal());
  33. }
  34. public function testImplementsCacheInterface(): void
  35. {
  36. $reflection = new \ReflectionClass(Cache::class);
  37. self::assertTrue($reflection->implementsInterface(CacheInterface::class));
  38. }
  39. public function testConstructorSetsValues(): void
  40. {
  41. $signature = $this->getSignatureDouble();
  42. $cache = new Cache($signature);
  43. self::assertSame($signature, $cache->getSignature());
  44. }
  45. public function testDefaults(): void
  46. {
  47. $signature = $this->getSignatureDouble();
  48. $cache = new Cache($signature);
  49. $file = 'test.php';
  50. self::assertFalse($cache->has($file));
  51. self::assertNull($cache->get($file));
  52. }
  53. public function testCanSetAndGetValue(): void
  54. {
  55. $signature = $this->getSignatureDouble();
  56. $cache = new Cache($signature);
  57. $file = 'test.php';
  58. $hash = md5('hello');
  59. $cache->set($file, $hash);
  60. self::assertTrue($cache->has($file));
  61. self::assertSame($hash, $cache->get($file));
  62. }
  63. public function testCanClearValue(): void
  64. {
  65. $signature = $this->getSignatureDouble();
  66. $cache = new Cache($signature);
  67. $file = 'test.php';
  68. $hash = md5('hello');
  69. $cache->set($file, $hash);
  70. $cache->clear($file);
  71. self::assertNull($cache->get($file));
  72. }
  73. public function testFromJsonThrowsInvalidArgumentExceptionIfJsonIsInvalid(): void
  74. {
  75. $this->expectException(\InvalidArgumentException::class);
  76. $json = '{"foo';
  77. Cache::fromJson($json);
  78. }
  79. /**
  80. * @param array<string, mixed> $data
  81. *
  82. * @dataProvider provideFromJsonThrowsInvalidArgumentExceptionIfJsonIsMissingKeyCases
  83. */
  84. public function testFromJsonThrowsInvalidArgumentExceptionIfJsonIsMissingKey(array $data): void
  85. {
  86. $this->expectException(\InvalidArgumentException::class);
  87. $json = json_encode($data, JSON_THROW_ON_ERROR);
  88. Cache::fromJson($json);
  89. }
  90. public static function provideFromJsonThrowsInvalidArgumentExceptionIfJsonIsMissingKeyCases(): iterable
  91. {
  92. $data = [
  93. 'php' => '7.1.2',
  94. 'version' => '2.0',
  95. 'rules' => [
  96. 'foo' => true,
  97. 'bar' => false,
  98. ],
  99. 'hashes' => [],
  100. ];
  101. return array_map(static function (string $missingKey) use ($data): array {
  102. unset($data[$missingKey]);
  103. return [
  104. $data,
  105. ];
  106. }, array_keys($data));
  107. }
  108. /**
  109. * @dataProvider provideCanConvertToAndFromJsonCases
  110. */
  111. public function testCanConvertToAndFromJson(SignatureInterface $signature): void
  112. {
  113. $cache = new Cache($signature);
  114. $file = 'test.php';
  115. $hash = md5('hello');
  116. $cache->set($file, $hash);
  117. $cached = Cache::fromJson($cache->toJson());
  118. self::assertTrue($cached->getSignature()->equals($signature));
  119. self::assertTrue($cached->has($file));
  120. self::assertSame($hash, $cached->get($file));
  121. }
  122. public static function provideCanConvertToAndFromJsonCases(): iterable
  123. {
  124. $toolInfo = new ToolInfo();
  125. $config = new Config();
  126. yield [new Signature(
  127. PHP_VERSION,
  128. '2.0',
  129. ' ',
  130. "\r\n",
  131. [
  132. 'foo' => true,
  133. 'bar' => true,
  134. ]
  135. )];
  136. yield [new Signature(
  137. PHP_VERSION,
  138. $toolInfo->getVersion(),
  139. $config->getIndent(),
  140. $config->getLineEnding(),
  141. [
  142. // value encoded in ANSI, not UTF
  143. 'header_comment' => ['header' => 'Dariusz '.base64_decode('UnVtafFza2k=', true)],
  144. ]
  145. )];
  146. }
  147. public function testToJsonThrowsExceptionOnInvalid(): void
  148. {
  149. $invalidUtf8Sequence = "\xB1\x31";
  150. $signature = $this->prophesize(SignatureInterface::class);
  151. $signature->getPhpVersion()->willReturn('7.1.0');
  152. $signature->getFixerVersion()->willReturn('2.2.0');
  153. $signature->getIndent()->willReturn(' ');
  154. $signature->getLineEnding()->willReturn(PHP_EOL);
  155. $signature->getRules()->willReturn([
  156. $invalidUtf8Sequence => true,
  157. ]);
  158. $cache = new Cache($signature->reveal());
  159. $this->expectException(
  160. \UnexpectedValueException::class
  161. );
  162. $this->expectExceptionMessage(
  163. 'Cannot encode cache signature to JSON, error: "Malformed UTF-8 characters, possibly incorrectly encoded". If you have non-UTF8 chars in your signature, like in license for `header_comment`, consider enabling `ext-mbstring` or install `symfony/polyfill-mbstring`.'
  164. );
  165. $cache->toJson();
  166. }
  167. private function getSignatureDouble(): SignatureInterface
  168. {
  169. return $this->prophesize(SignatureInterface::class)->reveal();
  170. }
  171. }