diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 06364de3ef..f0d11195b3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -247,10 +247,21 @@ jobs: env: PHP_CODESNIFFER_CBF: '1' + - name: "Install bashunit" + if: ${{ matrix.custom_ini == false && matrix.os == 'ubuntu-latest' }} + run: | + curl -s https://bashunit.typeddevs.com/install.sh > install.sh + chmod +x install.sh + ./install.sh + + - name: "Run bashunit tests" + if: ${{ matrix.custom_ini == false && matrix.os == 'ubuntu-latest' }} + run: "./lib/bashunit -p tests/EndToEnd" + # Note: The code style check is run multiple times against every PHP version # as it also acts as an integration test. - name: 'PHPCS: check code style without cache, no parallel' - if: ${{ matrix.custom_ini == false }} + if: ${{ matrix.custom_ini == false && matrix.os == 'windows-latest' }} run: php "bin/phpcs" --no-cache --parallel=1 - name: Download the PHPCS phar diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 0fd2f38d0f..6285d269f1 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -11,6 +11,7 @@ */src/Standards/*/Tests/*\.(inc|css|js)$ */tests/Core/*/*\.(inc|css|js)$ */tests/Core/*/Fixtures/*\.php$ + */tests/EndToEnd/Files/*\.inc$ diff --git a/src/Runner.php b/src/Runner.php index d527ea575e..37c3c65c7a 100644 --- a/src/Runner.php +++ b/src/Runner.php @@ -764,7 +764,7 @@ public function processFile($file) * The reporting information returned by each child process is merged * into the main reporter class. * - * @param array $childProcs An array of child processes to wait for. + * @param array $childProcs An array of child processes to wait for. * * @return bool */ @@ -777,7 +777,8 @@ private function processChildProcs($childProcs) while (count($childProcs) > 0) { $pid = pcntl_waitpid(0, $status); - if ($pid <= 0) { + if ($pid <= 0 || isset($childProcs[$pid]) === false) { + // No child or a child with an unmanaged PID was returned. continue; } diff --git a/tests/EndToEnd/Files/.gitignore b/tests/EndToEnd/Files/.gitignore new file mode 100644 index 0000000000..862bc749ba --- /dev/null +++ b/tests/EndToEnd/Files/.gitignore @@ -0,0 +1 @@ +*.fixed \ No newline at end of file diff --git a/tests/EndToEnd/Files/ClassOneWithoutStyleError.inc b/tests/EndToEnd/Files/ClassOneWithoutStyleError.inc new file mode 100644 index 0000000000..5ae6ac8f94 --- /dev/null +++ b/tests/EndToEnd/Files/ClassOneWithoutStyleError.inc @@ -0,0 +1,18 @@ + + + The coding standard for end to end tests. + + + + . + + + + + + diff --git a/tests/EndToEnd/phpcbf_test.sh b/tests/EndToEnd/phpcbf_test.sh new file mode 100644 index 0000000000..74780570b9 --- /dev/null +++ b/tests/EndToEnd/phpcbf_test.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +function tear_down() { + rm -r tests/EndToEnd/Files/*.fixed +} + +function test_phpcbf_is_working() { + OUTPUT="$(bin/phpcbf --no-cache --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassOneWithoutStyleError.inc tests/EndToEnd/Files/ClassTwoWithoutStyleError.inc)" + + assert_successful_code + assert_contains "No violations were found" "$OUTPUT" +} + +function test_phpcbf_is_working_in_parallel() { + OUTPUT="$(bin/phpcbf --no-cache --parallel=2 --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassOneWithoutStyleError.inc tests/EndToEnd/Files/ClassTwoWithoutStyleError.inc)" + + assert_successful_code + assert_contains "No violations were found" "$OUTPUT" +} + +function test_phpcbf_returns_error_on_issues() { + OUTPUT="$(bin/phpcbf --no-colors --no-cache --suffix=.fixed --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassWithStyleError.inc)" + assert_exit_code 1 + + assert_contains "F 1 / 1 (100%)" "$OUTPUT" + assert_contains "A TOTAL OF 1 ERROR WERE FIXED IN 1 FILE" "$OUTPUT" +} + +function test_phpcbf_bug_1112() { + # See https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/1112 + if [[ "$(uname)" == "Darwin" ]]; then + # Perform some magic with `& fg` to prevent the processes from turning into a background job. + assert_successful_code "$(bash -ic 'bash --init-file <(echo "echo \"Subprocess\"") -c "bin/phpcbf --no-cache --parallel=2 --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassOneWithoutStyleError.inc tests/EndToEnd/Files/ClassTwoWithoutStyleError.inc" & fg')" + else + # This is not needed on Linux / GitHub Actions + assert_successful_code "$(bash -ic 'bash --init-file <(echo "echo \"Subprocess\"") -c "bin/phpcbf --no-cache --parallel=2 --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassOneWithoutStyleError.inc tests/EndToEnd/Files/ClassTwoWithoutStyleError.inc"')" + fi +} diff --git a/tests/EndToEnd/phpcs_test.sh b/tests/EndToEnd/phpcs_test.sh new file mode 100644 index 0000000000..ef4aef8e36 --- /dev/null +++ b/tests/EndToEnd/phpcs_test.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +function test_phpcs_is_working() { + assert_successful_code "$(bin/phpcs --no-cache --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassOneWithoutStyleError.inc tests/EndToEnd/Files/ClassTwoWithoutStyleError.inc)" +} + +function test_phpcs_is_working_in_parallel() { + assert_successful_code "$(bin/phpcs --no-cache --parallel=2 --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassOneWithoutStyleError.inc tests/EndToEnd/Files/ClassTwoWithoutStyleError.inc)" +} + +function test_phpcs_returns_error_on_issues() { + OUTPUT="$(bin/phpcs --no-colors --no-cache --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassWithStyleError.inc)" + assert_exit_code 2 + + assert_contains "E 1 / 1 (100%)" "$OUTPUT" + assert_contains "FOUND 1 ERROR AFFECTING 1 LINE" "$OUTPUT" +} + +function test_phpcs_bug_1112() { + # See https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/1112 + if [[ "$(uname)" == "Darwin" ]]; then + # Perform some magic with `& fg` to prevent the processes from turning into a background job. + assert_successful_code "$(bash -ic 'bash --init-file <(echo "echo \"Subprocess\"") -c "bin/phpcs --no-cache --parallel=2 --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassOneWithoutStyleError.inc tests/EndToEnd/Files/ClassTwoWithoutStyleError.inc" & fg')" + else + # This is not needed on Linux / GitHub Actions + assert_successful_code "$(bash -ic 'bash --init-file <(echo "echo \"Subprocess\"") -c "bin/phpcs --no-cache --parallel=2 --standard=tests/EndToEnd/Files/phpcs.xml.dist tests/EndToEnd/Files/ClassOneWithoutStyleError.inc tests/EndToEnd/Files/ClassTwoWithoutStyleError.inc"')" + fi +}