Skip to content

Commit 2795648

Browse files
committed
Merge branch 'master' into 4.x
2 parents 7fd641d + 1ed2b9e commit 2795648

File tree

11 files changed

+227
-5
lines changed

11 files changed

+227
-5
lines changed

.github/CONTRIBUTING.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ Thank you for your interest in contributing to PHP_CodeSniffer!
1818
* [Finding Something to Work on](#finding-something-to-work-on)
1919
* [Getting Started](#getting-started)
2020
* [While Working on a Patch](#while-working-on-a-patch)
21-
* [Writing Tests](#writing-tests)
21+
* [Writing Unit/Integration Tests](#writing-unitintegration-tests)
22+
* [Writing End-to-End Tests](#writing-end-to-end-tests)
2223
* [Submitting Your Pull Request](#submitting-your-pull-request)
2324
* [Licensing](#licensing)
2425

@@ -270,7 +271,7 @@ To help you with this, a number of convenience scripts are available:
270271
* `composer build` will build the phpcs.phar and phpcbf.phar files.
271272

272273

273-
### Writing Tests
274+
### Writing Unit/Integration Tests
274275

275276
Tests for the PHP_CodeSniffer engine can be found in the `tests/Core` directory.
276277
Tests for individual sniffs can be found in the `src/Standards/[StandardName]/Tests/[Category]/` directory.
@@ -378,7 +379,7 @@ To run the tests specific to the use of `PHP_CODESNIFFER_CBF === true`:
378379
vendor/bin/phpunit --group CBF --exclude-group nothing
379380
```
380381

381-
#### Other notes about writing tests
382+
#### Other notes about writing unit/integration tests
382383

383384
* When using data providers, define them immediately below the corresponding test method.
384385
* When a test method has only one data provider, it is considered best practice to closely couple the test and data provider methods via their names. I.e. the data provider's name should match the test method name, replacing the "test" prefix with "data". For example, the data provider for a method named `testSomething()` should be `dataSomething()`.
@@ -396,6 +397,24 @@ To run the tests specific to the use of `PHP_CODESNIFFER_CBF === true`:
396397
Generally speaking, it is a good idea to always add a call to `expectNoStdoutOutput()` in any test using the `assertStderrOutput*()` assertions to make sure there is no output leaking to `stdOut`.
397398

398399

400+
401+
### Writing End-to-End Tests
402+
403+
Bash-based end-to-end tests can be written using the [Bashunit](https://bashunit.typeddevs.com/) test tooling.
404+
405+
To install bashunit, follow the [installation guide](https://bashunit.typeddevs.com/installation).
406+
407+
You can then run the bashunit tests on Linux/Mac/WSL, like so:
408+
```bash
409+
./lib/bashunit -p tests/EndToEnd
410+
```
411+
412+
> Note: these tests will not run in the Windows native CMD shell. When on Windows, either use WSL or use the "git bash" shell.
413+
414+
When writing end-to-end tests, please use fixtures for the "files under scan" to make the tests stable.
415+
These fixtures can be placed in the `tests/EndToEnd/Fixtures` subdirectory.
416+
417+
399418
### Submitting Your Pull Request
400419

401420
Some guidelines for submitting pull requests (PRs) and improving the chance that your PR will be merged:
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: E2E Tests
2+
3+
on:
4+
# Run on pushes to `master`/`4.0` and on all pull requests.
5+
# Prevent the build from running when there are only irrelevant changes.
6+
push:
7+
branches:
8+
- master
9+
- 4.0
10+
tags:
11+
- '**'
12+
paths-ignore:
13+
- '**.md'
14+
pull_request:
15+
# Allow manually triggering the workflow.
16+
workflow_dispatch:
17+
18+
jobs:
19+
bash-tests:
20+
# Cancels all previous runs of this particular job for the same branch that have not yet completed.
21+
concurrency:
22+
# The concurrency group contains the workflow name, job name, job index and the branch name.
23+
group: ${{ github.workflow }}-${{ github.job }}-${{ strategy.job-index }}-${{ github.ref }}
24+
cancel-in-progress: true
25+
26+
runs-on: 'ubuntu-latest'
27+
28+
strategy:
29+
matrix:
30+
php: ['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
31+
32+
# yamllint disable-line rule:line-length
33+
name: "E2E PHP: ${{ matrix.php }}"
34+
35+
continue-on-error: ${{ matrix.php == '8.5' }}
36+
37+
steps:
38+
- name: Prepare git to leave line endings alone
39+
run: git config --global core.autocrlf input
40+
41+
- name: Checkout code
42+
uses: actions/checkout@v4
43+
44+
- name: Install PHP
45+
uses: shivammathur/setup-php@v2
46+
with:
47+
php-version: ${{ matrix.php }}
48+
ini-values: "error_reporting=-1, display_errors=On"
49+
coverage: none
50+
51+
- name: "Install bashunit"
52+
shell: bash
53+
run: |
54+
curl -s https://bashunit.typeddevs.com/install.sh > install.sh
55+
chmod +x install.sh
56+
./install.sh
57+
58+
- name: "Run bashunit tests"
59+
shell: bash
60+
run: "./lib/bashunit -p tests/EndToEnd"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ phpstan.neon
1313
/tests/Standards/sniffStnd.xml
1414
/tests/Core/Util/ExitCode/Fixtures/ExitCodeTest/*.fixed
1515
/tests/Core/Util/ExitCode/Fixtures/ExitCodeTest/phpcs.cache
16+
/tests/EndToEnd/Fixtures/*.fixed
17+
/lib/

phpcs.xml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<exclude-pattern>*/src/Standards/*/Tests/*\.inc$</exclude-pattern>
1414
<exclude-pattern>*/tests/Core/*/*\.inc$</exclude-pattern>
1515
<exclude-pattern>*/tests/Core/*/Fixtures/*\.php$</exclude-pattern>
16+
<exclude-pattern>*/tests/EndToEnd/Fixtures/*\.inc$</exclude-pattern>
1617

1718
<arg name="basepath" value="."/>
1819
<arg name="colors"/>

src/Runner.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ public function processFile($file)
682682
* The reporting information returned by each child process is merged
683683
* into the main reporter class.
684684
*
685-
* @param array $childProcs An array of child processes to wait for.
685+
* @param array<int, string> $childProcs An array of child processes to wait for.
686686
*
687687
* @return bool
688688
*/
@@ -695,7 +695,8 @@ private function processChildProcs($childProcs)
695695

696696
while (count($childProcs) > 0) {
697697
$pid = pcntl_waitpid(0, $status);
698-
if ($pid <= 0) {
698+
if ($pid <= 0 || isset($childProcs[$pid]) === false) {
699+
// No child or a child with an unmanaged PID was returned.
699700
continue;
700701
}
701702

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/**
4+
* Class containing no style errors according to the end-to-end tests phpcs.xml.dist.
5+
*
6+
* @copyright 2025 PHPCSStandards and contributors
7+
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\EndToEnd\Fixtures;
11+
12+
class ClassOneWithoutStyleError
13+
{
14+
private function foo()
15+
{
16+
return 'bar';
17+
}
18+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
/**
4+
* Class containing no style errors.
5+
*
6+
* @copyright 2025 PHPCSStandards and contributors
7+
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\EndToEnd\Fixtures;
11+
12+
class ClassTwoWithoutStyleError
13+
{
14+
/**
15+
* A property.
16+
*
17+
* @var string
18+
*/
19+
private $bar = 'baz';
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/**
4+
* Class containing a simple style error that phpcbf can fix.
5+
*
6+
* @copyright 2025 PHPCSStandards and contributors
7+
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\EndToEnd\Fixtures;
11+
12+
class ClassWithStyleError
13+
{
14+
/**
15+
* The bracket for this function is misaligned and this can be automatically fixed by phpcbf.
16+
*
17+
* @return string
18+
*/
19+
private function foo() {
20+
return 'bar';
21+
}
22+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0"?>
2+
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="EndToEndTests" xsi:noNamespaceSchemaLocation="phpcs.xsd">
3+
<description>The coding standard for end to end tests.</description>
4+
5+
<rule ref="PSR12"/>
6+
7+
<file>.</file>
8+
9+
<arg name="basepath" value="."/>
10+
<arg name="colors"/>
11+
<arg name="parallel" value="75"/>
12+
<arg value="p"/>
13+
</ruleset>

tests/EndToEnd/phpcbf_test.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env bash
2+
3+
function tear_down() {
4+
rm -r tests/EndToEnd/Fixtures/*.fixed
5+
}
6+
7+
function test_phpcbf_is_working() {
8+
OUTPUT="$(bin/phpcbf --no-cache --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc tests/EndToEnd/Fixtures/ClassTwoWithoutStyleError.inc)"
9+
10+
assert_successful_code
11+
assert_contains "No violations were found" "$OUTPUT"
12+
}
13+
14+
function test_phpcbf_is_working_in_parallel() {
15+
OUTPUT="$(bin/phpcbf --no-cache --parallel=2 --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc tests/EndToEnd/Fixtures/ClassTwoWithoutStyleError.inc)"
16+
17+
assert_successful_code
18+
assert_contains "No violations were found" "$OUTPUT"
19+
}
20+
21+
function test_phpcbf_returns_error_on_issues() {
22+
OUTPUT="$(bin/phpcbf --no-colors --no-cache --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithStyleError.inc)"
23+
assert_exit_code 1
24+
25+
assert_contains "F 1 / 1 (100%)" "$OUTPUT"
26+
assert_contains "A TOTAL OF 1 ERROR WERE FIXED IN 1 FILE" "$OUTPUT"
27+
}
28+
29+
function test_phpcbf_bug_1112() {
30+
# See https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/1112
31+
if [[ "$(uname)" == "Darwin" ]]; then
32+
# Perform some magic with `& fg` to prevent the processes from turning into a background job.
33+
assert_successful_code "$(bash -ic 'bash --init-file <(echo "echo \"Subprocess\"") -c "bin/phpcbf --no-cache --parallel=2 --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc tests/EndToEnd/Fixtures/ClassTwoWithoutStyleError.inc" & fg')"
34+
else
35+
# This is not needed on Linux / GitHub Actions
36+
assert_successful_code "$(bash -ic 'bash --init-file <(echo "echo \"Subprocess\"") -c "bin/phpcbf --no-cache --parallel=2 --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc tests/EndToEnd/Fixtures/ClassTwoWithoutStyleError.inc"')"
37+
fi
38+
}

0 commit comments

Comments
 (0)