CiIntegrationTest.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. /*
  3. * This file is part of PHP CS Fixer.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  7. *
  8. * This source file is subject to the MIT license that is bundled
  9. * with this source code in the file LICENSE.
  10. */
  11. namespace PhpCsFixer\Tests\Smoke;
  12. use Keradus\CliExecutor\CommandExecutor;
  13. use Keradus\CliExecutor\ScriptExecutor;
  14. use PhpCsFixer\Console\Application;
  15. /**
  16. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  17. *
  18. * @internal
  19. *
  20. * @requires OS Linux|Darwin
  21. * @coversNothing
  22. * @group covers-nothing
  23. * @large
  24. */
  25. final class CiIntegrationTest extends AbstractSmokeTest
  26. {
  27. public static $fixtureDir;
  28. public static function doSetUpBeforeClass()
  29. {
  30. parent::doSetUpBeforeClass();
  31. self::$fixtureDir = __DIR__.'/../Fixtures/ci-integration';
  32. try {
  33. CommandExecutor::create('composer --version', __DIR__)->getResult();
  34. } catch (\RuntimeException $e) {
  35. static::markTestSkippedOrFail('Missing `composer` env script. Details:'."\n".$e->getMessage());
  36. }
  37. try {
  38. CommandExecutor::create('composer check', __DIR__.'/../..')->getResult();
  39. } catch (\RuntimeException $e) {
  40. static::markTestSkippedOrFail('Composer check failed. Details:'."\n".$e->getMessage());
  41. }
  42. try {
  43. self::executeScript([
  44. 'rm -rf .git',
  45. 'git init -q',
  46. 'git config user.name test',
  47. 'git config user.email test',
  48. 'git add .',
  49. 'git commit -m "init" -q',
  50. ]);
  51. } catch (\RuntimeException $e) {
  52. static::markTestSkippedOrFail($e->getMessage());
  53. }
  54. }
  55. public static function doTearDownAfterClass()
  56. {
  57. parent::doTearDownAfterClass();
  58. self::executeCommand('rm -rf .git');
  59. }
  60. protected function doTearDown()
  61. {
  62. parent::doTearDown();
  63. self::executeScript([
  64. 'git reset . -q',
  65. 'git checkout . -q',
  66. 'git clean -fdq',
  67. 'git checkout master -q',
  68. ]);
  69. }
  70. /**
  71. * @param string $branchName
  72. * @param string[] $caseCommands
  73. * @param string[] $expectedResult1Lines
  74. * @param string[] $expectedResult2Lines
  75. * @param string $expectedResult3Files
  76. *
  77. * @dataProvider provideIntegrationCases
  78. */
  79. public function testIntegration(
  80. $branchName,
  81. array $caseCommands,
  82. array $expectedResult1Lines,
  83. array $expectedResult2Lines,
  84. $expectedResult3Files
  85. ) {
  86. self::executeScript(array_merge(
  87. [
  88. "git checkout -b {$branchName} -q",
  89. ],
  90. $caseCommands
  91. ));
  92. $integrationScript = explode("\n", str_replace('vendor/bin/', './../../../', file_get_contents(__DIR__.'/../../ci-integration.sh')));
  93. $steps = [
  94. "COMMIT_RANGE=\"master..{$branchName}\"",
  95. "{$integrationScript[3]}\n{$integrationScript[4]}",
  96. $integrationScript[5],
  97. $integrationScript[6],
  98. $integrationScript[7],
  99. ];
  100. $result1 = self::executeScript([
  101. $steps[0],
  102. $steps[1],
  103. $steps[2],
  104. 'echo "$CHANGED_FILES"',
  105. ]);
  106. static::assertSame(implode("\n", $expectedResult1Lines)."\n", $result1->getOutput());
  107. $result2 = self::executeScript([
  108. $steps[0],
  109. $steps[1],
  110. $steps[2],
  111. $steps[3],
  112. 'echo "${EXTRA_ARGS}"',
  113. ]);
  114. static::assertSame(implode("\n", $expectedResult2Lines), $result2->getOutput());
  115. $result3 = self::executeScript([
  116. $steps[0],
  117. $steps[1],
  118. $steps[2],
  119. $steps[3],
  120. $steps[4],
  121. ]);
  122. $optionalIncompatibilityWarning = 'PHP needs to be a minimum version of PHP 5.6.0 and maximum version of PHP 7.4.*.
  123. Current PHP version: '.PHP_VERSION.'.
  124. Ignoring environment requirements because `PHP_CS_FIXER_IGNORE_ENV` is set. Execution may be unstable.
  125. ';
  126. $optionalXdebugWarning = 'You are running PHP CS Fixer with xdebug enabled. This has a major impact on runtime performance.
  127. If you need help while solving warnings, ask at https://gitter.im/PHP-CS-Fixer, we will help you!
  128. ';
  129. $pattern = sprintf(
  130. '/^(?:%s)?(?:%s)?%s\n%s\n%s\n([\.S]{%d})\n%s$/',
  131. preg_quote($optionalIncompatibilityWarning, '/'),
  132. preg_quote($optionalXdebugWarning, '/'),
  133. 'PHP CS Fixer '.preg_quote(Application::VERSION, '/').' '.preg_quote(Application::VERSION_CODENAME, '/').' by Fabien Potencier and Dariusz Ruminski',
  134. preg_quote(sprintf('Runtime: PHP %s', PHP_VERSION), '/'),
  135. preg_quote('Loaded config default from ".php-cs-fixer.dist.php".', '/'),
  136. \strlen($expectedResult3Files),
  137. preg_quote('Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error', '/')
  138. );
  139. static::assertMatchesRegularExpression($pattern, $result3->getError());
  140. preg_match($pattern, $result3->getError(), $matches);
  141. static::assertArrayHasKey(1, $matches);
  142. static::assertSame(substr_count($expectedResult3Files, '.'), substr_count($matches[1], '.'));
  143. static::assertSame(substr_count($expectedResult3Files, 'S'), substr_count($matches[1], 'S'));
  144. static::assertMatchesRegularExpression(
  145. '/^\s*Checked all files in \d+\.\d+ seconds, \d+\.\d+ MB memory used\s*$/',
  146. $result3->getOutput()
  147. );
  148. }
  149. public function provideIntegrationCases()
  150. {
  151. return [
  152. 'random-changes' => [
  153. 'random-changes',
  154. [
  155. 'touch dir\ a/file.php',
  156. 'rm -r dir\ c',
  157. 'echo "" >> dir\ b/file\ b.php',
  158. 'echo "echo 1;" >> dir\ b/file\ b.php',
  159. 'git add .',
  160. 'git commit -m "Random changes" -q',
  161. ],
  162. [
  163. 'dir a/file.php',
  164. 'dir b/file b.php',
  165. ],
  166. [
  167. '--path-mode=intersection',
  168. '--',
  169. 'dir a/file.php',
  170. 'dir b/file b.php',
  171. '',
  172. ],
  173. 'S.',
  174. ],
  175. 'changes-including-dist-config-file' => [
  176. 'changes-including-dist-config-file',
  177. [
  178. 'echo "" >> dir\ b/file\ b.php',
  179. 'echo "echo 1;" >> dir\ b/file\ b.php',
  180. // `sed -i ...` is not handled the same on Linux and macOS
  181. 'sed -e \'s/@Symfony/@PSR2/\' .php-cs-fixer.dist.php > .php-cs-fixer.dist.php.new',
  182. 'mv .php-cs-fixer.dist.php.new .php-cs-fixer.dist.php',
  183. 'git add .',
  184. 'git commit -m "Random changes including config file" -q',
  185. ],
  186. [
  187. '.php-cs-fixer.dist.php',
  188. 'dir b/file b.php',
  189. ],
  190. [
  191. '',
  192. '',
  193. ],
  194. '...',
  195. ],
  196. 'changes-including-custom-config-file-creation' => [
  197. 'changes-including-custom-config-file-creation',
  198. [
  199. 'echo "" >> dir\ b/file\ b.php',
  200. 'echo "echo 1;" >> dir\ b/file\ b.php',
  201. 'sed -e \'s/@Symfony/@PSR2/\' .php-cs-fixer.dist.php > .php-cs-fixer.php',
  202. 'git add .',
  203. 'git commit -m "Random changes including custom config file creation" -q',
  204. ],
  205. [
  206. '.php-cs-fixer.php',
  207. 'dir b/file b.php',
  208. ],
  209. [
  210. '',
  211. '',
  212. ],
  213. '...',
  214. ],
  215. 'changes-including-composer-lock' => [
  216. 'changes-including-composer-lock',
  217. [
  218. 'echo "" >> dir\ b/file\ b.php',
  219. 'echo "echo 1;" >> dir\ b/file\ b.php',
  220. 'touch composer.lock',
  221. 'git add .',
  222. 'git commit -m "Random changes including composer.lock" -q',
  223. ],
  224. [
  225. 'composer.lock',
  226. 'dir b/file b.php',
  227. ],
  228. [
  229. '',
  230. '',
  231. ],
  232. '...',
  233. ],
  234. ];
  235. }
  236. private static function executeCommand($command)
  237. {
  238. return CommandExecutor::create($command, self::$fixtureDir)->getResult();
  239. }
  240. private static function executeScript(array $scriptParts)
  241. {
  242. return ScriptExecutor::create($scriptParts, self::$fixtureDir)->getResult();
  243. }
  244. }