UtilsTest.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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;
  13. use PhpCsFixer\Fixer\FixerInterface;
  14. use PhpCsFixer\Tokenizer\Token;
  15. use PhpCsFixer\Utils;
  16. use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
  17. /**
  18. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  19. * @author Graham Campbell <hello@gjcampbell.co.uk>
  20. * @author Odín del Río <odin.drp@gmail.com>
  21. *
  22. * @internal
  23. *
  24. * @covers \PhpCsFixer\Utils
  25. */
  26. final class UtilsTest extends TestCase
  27. {
  28. use ExpectDeprecationTrait;
  29. private $originalValueOfFutureMode;
  30. protected function setUp(): void
  31. {
  32. $this->originalValueOfFutureMode = getenv('PHP_CS_FIXER_FUTURE_MODE');
  33. }
  34. protected function tearDown(): void
  35. {
  36. putenv("PHP_CS_FIXER_FUTURE_MODE={$this->originalValueOfFutureMode}");
  37. }
  38. /**
  39. * @param string $expected Camel case string
  40. *
  41. * @dataProvider provideCamelCaseToUnderscoreCases
  42. */
  43. public function testCamelCaseToUnderscore(string $expected, string $input = null): void
  44. {
  45. if (null !== $input) {
  46. static::assertSame($expected, Utils::camelCaseToUnderscore($input));
  47. }
  48. static::assertSame($expected, Utils::camelCaseToUnderscore($expected));
  49. }
  50. public function provideCamelCaseToUnderscoreCases(): array
  51. {
  52. return [
  53. [
  54. 'dollar_close_curly_braces',
  55. 'DollarCloseCurlyBraces',
  56. ],
  57. [
  58. 'utf8_encoder_fixer',
  59. 'utf8EncoderFixer',
  60. ],
  61. [
  62. 'terminated_with_number10',
  63. 'TerminatedWithNumber10',
  64. ],
  65. [
  66. 'utf8_encoder_fixer',
  67. ],
  68. [
  69. 'a',
  70. 'A',
  71. ],
  72. [
  73. 'aa',
  74. 'AA',
  75. ],
  76. [
  77. 'foo',
  78. 'FOO',
  79. ],
  80. [
  81. 'foo_bar_baz',
  82. 'FooBarBAZ',
  83. ],
  84. [
  85. 'foo_bar_baz',
  86. 'FooBARBaz',
  87. ],
  88. [
  89. 'foo_bar_baz',
  90. 'FOOBarBaz',
  91. ],
  92. [
  93. 'mr_t',
  94. 'MrT',
  95. ],
  96. [
  97. 'voyage_éclair',
  98. 'VoyageÉclair',
  99. ],
  100. ];
  101. }
  102. /**
  103. * @param array|string $input token prototype
  104. *
  105. * @dataProvider provideCalculateTrailingWhitespaceIndentCases
  106. */
  107. public function testCalculateTrailingWhitespaceIndent(string $spaces, $input): void
  108. {
  109. $token = new Token($input);
  110. static::assertSame($spaces, Utils::calculateTrailingWhitespaceIndent($token));
  111. }
  112. public function provideCalculateTrailingWhitespaceIndentCases(): array
  113. {
  114. return [
  115. [' ', [T_WHITESPACE, "\n\n "]],
  116. [' ', [T_WHITESPACE, "\r\n\r\r\r "]],
  117. ["\t", [T_WHITESPACE, "\r\n\t"]],
  118. ['', [T_WHITESPACE, "\t\n\r"]],
  119. ['', [T_WHITESPACE, "\n"]],
  120. ['', ''],
  121. ];
  122. }
  123. public function testCalculateTrailingWhitespaceIndentFail(): void
  124. {
  125. $this->expectException(\InvalidArgumentException::class);
  126. $this->expectExceptionMessage('The given token must be whitespace, got "T_STRING".');
  127. $token = new Token([T_STRING, 'foo']);
  128. Utils::calculateTrailingWhitespaceIndent($token);
  129. }
  130. /**
  131. * @dataProvider provideStableSortCases
  132. */
  133. public function testStableSort(
  134. array $expected,
  135. array $elements,
  136. callable $getComparableValueCallback,
  137. callable $compareValuesCallback
  138. ): void {
  139. static::assertSame(
  140. $expected,
  141. Utils::stableSort($elements, $getComparableValueCallback, $compareValuesCallback)
  142. );
  143. }
  144. public function provideStableSortCases(): array
  145. {
  146. return [
  147. [
  148. ['a', 'b', 'c', 'd', 'e'],
  149. ['b', 'd', 'e', 'a', 'c'],
  150. static function ($element) { return $element; },
  151. 'strcmp',
  152. ],
  153. [
  154. ['b', 'd', 'e', 'a', 'c'],
  155. ['b', 'd', 'e', 'a', 'c'],
  156. static function (): string { return 'foo'; },
  157. 'strcmp',
  158. ],
  159. [
  160. ['b', 'd', 'e', 'a', 'c'],
  161. ['b', 'd', 'e', 'a', 'c'],
  162. static function ($element) { return $element; },
  163. static function (): int { return 0; },
  164. ],
  165. [
  166. ['bar1', 'baz1', 'foo1', 'bar2', 'baz2', 'foo2'],
  167. ['foo1', 'foo2', 'bar1', 'bar2', 'baz1', 'baz2'],
  168. static function ($element) { return preg_replace('/([a-z]+)(\d+)/', '$2$1', $element); },
  169. 'strcmp',
  170. ],
  171. ];
  172. }
  173. public function testSortFixers(): void
  174. {
  175. $fixers = [
  176. $this->createFixerDouble('f1', 0),
  177. $this->createFixerDouble('f2', -10),
  178. $this->createFixerDouble('f3', 10),
  179. $this->createFixerDouble('f4', -10),
  180. ];
  181. static::assertSame(
  182. [
  183. $fixers[2],
  184. $fixers[0],
  185. $fixers[1],
  186. $fixers[3],
  187. ],
  188. Utils::sortFixers($fixers)
  189. );
  190. }
  191. public function testNaturalLanguageJoinWithBackticksThrowsInvalidArgumentExceptionForEmptyArray(): void
  192. {
  193. $this->expectException(\InvalidArgumentException::class);
  194. Utils::naturalLanguageJoinWithBackticks([]);
  195. }
  196. /**
  197. * @dataProvider provideNaturalLanguageJoinWithBackticksCases
  198. */
  199. public function testNaturalLanguageJoinWithBackticks(string $joined, array $names): void
  200. {
  201. static::assertSame($joined, Utils::naturalLanguageJoinWithBackticks($names));
  202. }
  203. public function provideNaturalLanguageJoinWithBackticksCases(): array
  204. {
  205. return [
  206. [
  207. '`a`',
  208. ['a'],
  209. ],
  210. [
  211. '`a` and `b`',
  212. ['a', 'b'],
  213. ],
  214. [
  215. '`a`, `b` and `c`',
  216. ['a', 'b', 'c'],
  217. ],
  218. ];
  219. }
  220. /**
  221. * @group legacy
  222. */
  223. public function testTriggerDeprecationWhenFutureModeIsOff(): void
  224. {
  225. putenv('PHP_CS_FIXER_FUTURE_MODE=0');
  226. $message = __METHOD__.'::The message';
  227. $this->expectDeprecation($message);
  228. Utils::triggerDeprecation(new \DomainException($message));
  229. $triggered = Utils::getTriggeredDeprecations();
  230. static::assertContains($message, $triggered);
  231. }
  232. public function testTriggerDeprecationWhenFutureModeIsOn(): void
  233. {
  234. putenv('PHP_CS_FIXER_FUTURE_MODE=1');
  235. $message = __METHOD__.'::The message';
  236. $exception = new \DomainException($message);
  237. $futureModeException = null;
  238. try {
  239. Utils::triggerDeprecation($exception);
  240. } catch (\Exception $futureModeException) {
  241. }
  242. static::assertInstanceOf(\RuntimeException::class, $futureModeException);
  243. static::assertSame($exception, $futureModeException->getPrevious());
  244. $triggered = Utils::getTriggeredDeprecations();
  245. static::assertNotContains($message, $triggered);
  246. }
  247. private function createFixerDouble(string $name, int $priority): FixerInterface
  248. {
  249. $fixer = $this->prophesize(FixerInterface::class);
  250. $fixer->getName()->willReturn($name);
  251. $fixer->getPriority()->willReturn($priority);
  252. return $fixer->reveal();
  253. }
  254. }