Skip to content

Commit 452fc34

Browse files
authored
Test on PHP 8.4 (#1760)
1 parent 93f0673 commit 452fc34

File tree

9 files changed

+81
-37
lines changed

9 files changed

+81
-37
lines changed

.github/workflows/ci.yml

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ concurrency:
1818

1919
jobs:
2020
tests:
21-
name: Tests
21+
name: Tests (${{ matrix.os }}, ${{ matrix.php.version }}, ${{ matrix.dependencies }})
2222
runs-on: ${{ matrix.os }}
2323
strategy:
2424
fail-fast: false
@@ -27,13 +27,14 @@ jobs:
2727
- ubuntu-latest
2828
- windows-latest
2929
php:
30-
- '7.2'
31-
- '7.3'
32-
- '7.4'
33-
- '8.0'
34-
- '8.1'
35-
- '8.2'
36-
- '8.3'
30+
- { version: '7.2', phpunit: '^8.5.40' }
31+
- { version: '7.3', phpunit: '^9.6.21' }
32+
- { version: '7.4', phpunit: '^9.6.21' }
33+
- { version: '8.0', phpunit: '^9.6.21' }
34+
- { version: '8.1', phpunit: '^9.6.21' }
35+
- { version: '8.2', phpunit: '^9.6.21' }
36+
- { version: '8.3', phpunit: '^9.6.21' }
37+
- { version: '8.4', phpunit: '^9.6.21' }
3738
dependencies:
3839
- lowest
3940
- highest
@@ -47,7 +48,7 @@ jobs:
4748
- name: Setup PHP
4849
uses: shivammathur/setup-php@v2
4950
with:
50-
php-version: ${{ matrix.php }}
51+
php-version: ${{ matrix.php.version }}
5152
coverage: xdebug
5253

5354
- name: Setup Problem Matchers for PHPUnit
@@ -62,8 +63,15 @@ jobs:
6263
uses: actions/cache@v4
6364
with:
6465
path: ${{ steps.composer-cache.outputs.directory }}
65-
key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.lock') }}
66-
restore-keys: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.dependencies }}-composer-
66+
key: ${{ runner.os }}-${{ matrix.php.version }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.lock') }}
67+
restore-keys: ${{ runner.os }}-${{ matrix.php.version }}-${{ matrix.dependencies }}-composer-
68+
69+
# These dependencies are not used running the tests but can cause deprecation warnings so we remove them before running the tests
70+
- name: Remove unused dependencies
71+
run: composer remove vimeo/psalm phpstan/phpstan friendsofphp/php-cs-fixer --dev --no-interaction --no-update
72+
73+
- name: Set phpunit/phpunit version constraint
74+
run: composer require phpunit/phpunit:'${{ matrix.php.phpunit }}' --dev --no-interaction --no-update
6775

6876
- name: Install highest dependencies
6977
run: composer update --no-progress --no-interaction --prefer-dist
@@ -84,4 +92,4 @@ jobs:
8492

8593
- name: Check benchmarks
8694
run: vendor/bin/phpbench run --revs=1 --iterations=1
87-
if: ${{ matrix.dependencies == 'highest' && matrix.php == '8.2' }}
95+
if: ${{ matrix.dependencies == 'highest' && matrix.php.version == '8.3' }}

.github/workflows/static-analysis.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- name: Setup PHP
2222
uses: shivammathur/setup-php@v2
2323
with:
24-
php-version: '8.2'
24+
php-version: '8.3'
2525

2626
- name: Install dependencies
2727
run: composer update --no-progress --no-interaction --prefer-dist
@@ -39,7 +39,7 @@ jobs:
3939
- name: Setup PHP
4040
uses: shivammathur/setup-php@v2
4141
with:
42-
php-version: '8.2'
42+
php-version: '8.3'
4343

4444
- name: Install dependencies
4545
run: composer update --no-progress --no-interaction --prefer-dist
@@ -59,7 +59,7 @@ jobs:
5959
- name: Setup PHP
6060
uses: shivammathur/setup-php@v2
6161
with:
62-
php-version: '8.2'
62+
php-version: '8.3'
6363

6464
- name: Install dependencies
6565
run: composer update --no-progress --no-interaction --prefer-dist

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@
3333
},
3434
"require-dev": {
3535
"friendsofphp/php-cs-fixer": "^3.4",
36-
"guzzlehttp/promises": "^1.0|^2.0",
36+
"guzzlehttp/promises": "^2.0.3",
3737
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
3838
"monolog/monolog": "^1.6|^2.0|^3.0",
3939
"phpbench/phpbench": "^1.0",
4040
"phpstan/phpstan": "^1.3",
41-
"phpunit/phpunit": "^8.5.14|^9.4",
41+
"phpunit/phpunit": "^8.5|^9.6",
4242
"symfony/phpunit-bridge": "^5.2|^6.0|^7.0",
4343
"vimeo/psalm": "^4.17"
4444
},

src/ErrorHandler.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ final class ErrorHandler
130130
\E_USER_DEPRECATED => 'User Deprecated',
131131
\E_NOTICE => 'Notice',
132132
\E_USER_NOTICE => 'User Notice',
133-
\E_STRICT => 'Runtime Notice',
133+
// This is \E_STRICT which has been deprecated in PHP 8.4 so we should not reference it directly to prevent deprecation notices
134+
2048 => 'Runtime Notice',
134135
\E_WARNING => 'Warning',
135136
\E_USER_WARNING => 'User Warning',
136137
\E_COMPILE_WARNING => 'Compile Warning',

src/FrameBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ private function getFunctionArguments(array $backtraceFrame): array
161161
} else {
162162
$reflectionFunction = new \ReflectionMethod($backtraceFrame['class'], '__call');
163163
}
164-
} elseif (!\in_array($backtraceFrame['function'], ['{closure}', '__lambda_func'], true) && \function_exists($backtraceFrame['function'])) {
164+
} elseif ($backtraceFrame['function'] !== '__lambda_func' && !str_starts_with($backtraceFrame['function'], '{closure') && \function_exists($backtraceFrame['function'])) {
165165
$reflectionFunction = new \ReflectionFunction($backtraceFrame['function']);
166166
}
167167
} catch (\ReflectionException $e) {

src/Severity.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public static function fromError(int $severity): self
104104
return self::error();
105105
case \E_NOTICE:
106106
case \E_USER_NOTICE:
107-
case \E_STRICT:
107+
case 2048: // This is \E_STRICT which has been deprecated in PHP 8.4 so we should not reference it directly to prevent deprecation notices
108108
return self::info();
109109
default:
110110
return self::error();

tests/Serializer/AbstractSerializerTest.php

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -442,48 +442,64 @@ public function serializableCallableProvider(): array
442442
$this->assertFileExists($filename);
443443
$callableWithoutNamespaces = require $filename;
444444

445+
$prettyClosureNames = \PHP_VERSION_ID >= 80400;
446+
445447
return [
446448
[
447449
'callable' => function (array $param1) {
448450
throw new \Exception('Don\'t even think about invoke me');
449451
},
450-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [array param1]',
452+
'expected' => $prettyClosureNames
453+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [array param1]'
454+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [array param1]',
451455
],
452456
[
453457
'callable' => function ($param1a) {
454458
throw new \Exception('Don\'t even think about invoke me');
455459
},
456-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [mixed|null param1a]',
460+
'expected' => $prettyClosureNames
461+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [mixed|null param1a]'
462+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [mixed|null param1a]',
457463
],
458464
[
459465
'callable' => function (callable $param1c) {
460466
throw new \Exception('Don\'t even think about invoke me');
461467
},
462-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [callable param1c]',
468+
'expected' => $prettyClosureNames
469+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [callable param1c]'
470+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [callable param1c]',
463471
],
464472
[
465473
'callable' => function (\stdClass $param1d) {
466474
throw new \Exception('Don\'t even think about invoke me');
467475
},
468-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [stdClass param1d]',
476+
'expected' => $prettyClosureNames
477+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [stdClass param1d]'
478+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [stdClass param1d]',
469479
],
470480
[
471481
'callable' => function (?\stdClass $param1e = null) {
472482
throw new \Exception('Don\'t even think about invoke me');
473483
},
474-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [stdClass|null [param1e]]',
484+
'expected' => $prettyClosureNames
485+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [stdClass|null [param1e]]'
486+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [stdClass|null [param1e]]',
475487
],
476488
[
477489
'callable' => function (array &$param1f) {
478490
throw new \Exception('Don\'t even think about invoke me');
479491
},
480-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [array &param1f]',
492+
'expected' => $prettyClosureNames
493+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [array &param1f]'
494+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [array &param1f]',
481495
],
482496
[
483497
'callable' => function (?array &$param1g = null) {
484498
throw new \Exception('Don\'t even think about invoke me');
485499
},
486-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [array|null [&param1g]]',
500+
'expected' => $prettyClosureNames
501+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [array|null [&param1g]]'
502+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [array|null [&param1g]]',
487503
],
488504
[
489505
'callable' => [$this, 'serializableCallableProvider'],
@@ -509,35 +525,47 @@ public function serializableCallableProvider(): array
509525
'callable' => function (int $param1_70a) {
510526
throw new \Exception('Don\'t even think about invoke me');
511527
},
512-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [int param1_70a]',
528+
'expected' => $prettyClosureNames
529+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [int param1_70a]'
530+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [int param1_70a]',
513531
],
514532
[
515533
'callable' => function (&$param): int {
516534
return (int) $param;
517535
},
518-
'expected' => 'Lambda int ' . __NAMESPACE__ . '\\{closure} [mixed|null &param]',
536+
'expected' => $prettyClosureNames
537+
? 'Lambda int {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [mixed|null &param]'
538+
: 'Lambda int ' . __NAMESPACE__ . '\\{closure} [mixed|null &param]',
519539
],
520540
[
521541
'callable' => function (int $param): ?int {
522542
throw new \Exception('Don\'t even think about invoke me');
523543
},
524-
'expected' => 'Lambda int ' . __NAMESPACE__ . '\\{closure} [int param]',
544+
'expected' => $prettyClosureNames
545+
? 'Lambda int {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [int param]'
546+
: 'Lambda int ' . __NAMESPACE__ . '\\{closure} [int param]',
525547
],
526548
[
527549
'callable' => function (?int $param1_70b) {
528550
throw new \Exception('Don\'t even think about invoke me');
529551
},
530-
'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [int|null param1_70b]',
552+
'expected' => $prettyClosureNames
553+
? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [int|null param1_70b]'
554+
: 'Lambda ' . __NAMESPACE__ . '\\{closure} [int|null param1_70b]',
531555
],
532556
[
533557
'callable' => function (?int $param1_70c): void {
534558
throw new \Exception('Don\'t even think about invoke me');
535559
},
536-
'expected' => 'Lambda void ' . __NAMESPACE__ . '\\{closure} [int|null param1_70c]',
560+
'expected' => $prettyClosureNames
561+
? 'Lambda void {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [int|null param1_70c]'
562+
: 'Lambda void ' . __NAMESPACE__ . '\\{closure} [int|null param1_70c]',
537563
],
538564
[
539565
'callable' => $callableWithoutNamespaces,
540-
'expected' => 'Lambda void {closure} [int|null param1_70ns]',
566+
'expected' => $prettyClosureNames
567+
? 'Lambda void {closure:%s:%d} [int|null param1_70ns]'
568+
: 'Lambda void {closure} [int|null param1_70ns]',
541569
],
542570
[
543571
// This is (a example of) a PHP provided function that is technically callable but we want to ignore that because it causes more false positives than it helps
@@ -559,11 +587,11 @@ public function testSerializeCallable($callable, string $expected): void
559587
$serializer = $this->createSerializer();
560588
$actual = $this->invokeSerialization($serializer, $callable);
561589

562-
$this->assertSame($expected, $actual);
590+
$this->assertStringMatchesFormat($expected, $actual);
563591

564592
$actual = $this->invokeSerialization($serializer, [$callable]);
565593

566-
$this->assertSame([$expected], $actual);
594+
$this->assertStringMatchesFormat($expected, $actual[0]);
567595
}
568596

569597
/**

tests/SeverityTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ public static function levelsDataProvider(): array
8383
// Info
8484
[\E_NOTICE, 'info'],
8585
[\E_USER_NOTICE, 'info'],
86-
[\E_STRICT, 'info'],
86+
// This is \E_STRICT which has been deprecated in PHP 8.4 so we should not reference it directly to prevent deprecation notices
87+
[2048, 'info'],
8788
];
8889
}
8990
}

tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,13 @@ trigger_error('Error thrown', E_USER_WARNING);
6262

6363
echo 'Triggering E_USER_ERROR error (unsilenceable on PHP8)' . PHP_EOL;
6464

65-
trigger_error('Error thrown', E_USER_ERROR);
65+
if (PHP_VERSION_ID >= 80400) {
66+
// Silence a deprecation notice on PHP 8.4
67+
// https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_passing_e_user_error_to_trigger_error
68+
@trigger_error('Error thrown', E_USER_ERROR);
69+
} else {
70+
trigger_error('Error thrown', E_USER_ERROR);
71+
}
6672
?>
6773
--EXPECT--
6874
Triggering E_USER_NOTICE error

0 commit comments

Comments
 (0)