diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6017bab07..c0a1985cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ concurrency: jobs: tests: - name: Tests + name: Tests (${{ matrix.os }}, ${{ matrix.php.version }}, ${{ matrix.dependencies }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -27,13 +27,14 @@ jobs: - ubuntu-latest - windows-latest php: - - '7.2' - - '7.3' - - '7.4' - - '8.0' - - '8.1' - - '8.2' - - '8.3' + - { version: '7.2', phpunit: '^8.5.40' } + - { version: '7.3', phpunit: '^9.6.21' } + - { version: '7.4', phpunit: '^9.6.21' } + - { version: '8.0', phpunit: '^9.6.21' } + - { version: '8.1', phpunit: '^9.6.21' } + - { version: '8.2', phpunit: '^9.6.21' } + - { version: '8.3', phpunit: '^9.6.21' } + - { version: '8.4', phpunit: '^9.6.21' } dependencies: - lowest - highest @@ -47,7 +48,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: ${{ matrix.php }} + php-version: ${{ matrix.php.version }} coverage: xdebug - name: Setup Problem Matchers for PHPUnit @@ -62,8 +63,15 @@ jobs: uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.directory }} - key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.lock') }} - restore-keys: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.dependencies }}-composer- + key: ${{ runner.os }}-${{ matrix.php.version }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.lock') }} + restore-keys: ${{ runner.os }}-${{ matrix.php.version }}-${{ matrix.dependencies }}-composer- + + # These dependencies are not used running the tests but can cause deprecation warnings so we remove them before running the tests + - name: Remove unused dependencies + run: composer remove vimeo/psalm phpstan/phpstan friendsofphp/php-cs-fixer --dev --no-interaction --no-update + + - name: Set phpunit/phpunit version constraint + run: composer require phpunit/phpunit:'${{ matrix.php.phpunit }}' --dev --no-interaction --no-update - name: Install highest dependencies run: composer update --no-progress --no-interaction --prefer-dist @@ -84,4 +92,4 @@ jobs: - name: Check benchmarks run: vendor/bin/phpbench run --revs=1 --iterations=1 - if: ${{ matrix.dependencies == 'highest' && matrix.php == '8.2' }} + if: ${{ matrix.dependencies == 'highest' && matrix.php.version == '8.3' }} diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index d7e3c5124..69de38c90 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -21,7 +21,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: '8.3' - name: Install dependencies run: composer update --no-progress --no-interaction --prefer-dist @@ -39,7 +39,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: '8.3' - name: Install dependencies run: composer update --no-progress --no-interaction --prefer-dist @@ -59,7 +59,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: '8.3' - name: Install dependencies run: composer update --no-progress --no-interaction --prefer-dist diff --git a/composer.json b/composer.json index 798b05541..0be4a6531 100644 --- a/composer.json +++ b/composer.json @@ -33,12 +33,12 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.4", - "guzzlehttp/promises": "^1.0|^2.0", + "guzzlehttp/promises": "^2.0.3", "guzzlehttp/psr7": "^1.8.4|^2.1.1", "monolog/monolog": "^1.6|^2.0|^3.0", "phpbench/phpbench": "^1.0", "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^8.5.14|^9.4", + "phpunit/phpunit": "^8.5|^9.6", "symfony/phpunit-bridge": "^5.2|^6.0|^7.0", "vimeo/psalm": "^4.17" }, diff --git a/src/ErrorHandler.php b/src/ErrorHandler.php index 37301b407..a34ec5893 100644 --- a/src/ErrorHandler.php +++ b/src/ErrorHandler.php @@ -130,7 +130,8 @@ final class ErrorHandler \E_USER_DEPRECATED => 'User Deprecated', \E_NOTICE => 'Notice', \E_USER_NOTICE => 'User Notice', - \E_STRICT => 'Runtime Notice', + // This is \E_STRICT which has been deprecated in PHP 8.4 so we should not reference it directly to prevent deprecation notices + 2048 => 'Runtime Notice', \E_WARNING => 'Warning', \E_USER_WARNING => 'User Warning', \E_COMPILE_WARNING => 'Compile Warning', diff --git a/src/FrameBuilder.php b/src/FrameBuilder.php index 46aa3461d..1eec712d4 100644 --- a/src/FrameBuilder.php +++ b/src/FrameBuilder.php @@ -161,7 +161,7 @@ private function getFunctionArguments(array $backtraceFrame): array } else { $reflectionFunction = new \ReflectionMethod($backtraceFrame['class'], '__call'); } - } elseif (!\in_array($backtraceFrame['function'], ['{closure}', '__lambda_func'], true) && \function_exists($backtraceFrame['function'])) { + } elseif ($backtraceFrame['function'] !== '__lambda_func' && !str_starts_with($backtraceFrame['function'], '{closure') && \function_exists($backtraceFrame['function'])) { $reflectionFunction = new \ReflectionFunction($backtraceFrame['function']); } } catch (\ReflectionException $e) { diff --git a/src/HttpClient/HttpClient.php b/src/HttpClient/HttpClient.php index 879e570e0..aa5873df3 100644 --- a/src/HttpClient/HttpClient.php +++ b/src/HttpClient/HttpClient.php @@ -64,6 +64,8 @@ public function sendRequest(Request $request, Options $options): Response curl_setopt($curlHandle, \CURLOPT_URL, $dsn->getEnvelopeApiEndpointUrl()); curl_setopt($curlHandle, \CURLOPT_HTTPHEADER, $requestHeaders); curl_setopt($curlHandle, \CURLOPT_USERAGENT, $this->sdkIdentifier . '/' . $this->sdkVersion); + curl_setopt($curlHandle, \CURLOPT_TIMEOUT_MS, $options->getHttpTimeout() * 1000); + curl_setopt($curlHandle, \CURLOPT_CONNECTTIMEOUT_MS, $options->getHttpConnectTimeout() * 1000); curl_setopt($curlHandle, \CURLOPT_ENCODING, ''); curl_setopt($curlHandle, \CURLOPT_POST, true); curl_setopt($curlHandle, \CURLOPT_POSTFIELDS, $requestData); @@ -71,20 +73,6 @@ public function sendRequest(Request $request, Options $options): Response curl_setopt($curlHandle, \CURLOPT_HEADERFUNCTION, $responseHeaderCallback); curl_setopt($curlHandle, \CURLOPT_HTTP_VERSION, \CURL_HTTP_VERSION_1_1); - $httpTimeout = $options->getHttpTimeout(); - if ($httpTimeout < 1.0) { - curl_setopt($curlHandle, \CURLOPT_TIMEOUT_MS, $httpTimeout * 1000); - } else { - curl_setopt($curlHandle, \CURLOPT_TIMEOUT, $httpTimeout); - } - - $connectTimeout = $options->getHttpConnectTimeout(); - if ($connectTimeout < 1.0) { - curl_setopt($curlHandle, \CURLOPT_CONNECTTIMEOUT_MS, $connectTimeout * 1000); - } else { - curl_setopt($curlHandle, \CURLOPT_CONNECTTIMEOUT, $connectTimeout); - } - $httpSslVerifyPeer = $options->getHttpSslVerifyPeer(); if (!$httpSslVerifyPeer) { curl_setopt($curlHandle, \CURLOPT_SSL_VERIFYPEER, false); diff --git a/src/Severity.php b/src/Severity.php index d0fa899d0..89dcabc7d 100644 --- a/src/Severity.php +++ b/src/Severity.php @@ -104,7 +104,7 @@ public static function fromError(int $severity): self return self::error(); case \E_NOTICE: case \E_USER_NOTICE: - case \E_STRICT: + 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 return self::info(); default: return self::error(); diff --git a/tests/Serializer/AbstractSerializerTest.php b/tests/Serializer/AbstractSerializerTest.php index 025a3921f..8f6104fbc 100644 --- a/tests/Serializer/AbstractSerializerTest.php +++ b/tests/Serializer/AbstractSerializerTest.php @@ -442,48 +442,64 @@ public function serializableCallableProvider(): array $this->assertFileExists($filename); $callableWithoutNamespaces = require $filename; + $prettyClosureNames = \PHP_VERSION_ID >= 80400; + return [ [ 'callable' => function (array $param1) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [array param1]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [array param1]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [array param1]', ], [ 'callable' => function ($param1a) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [mixed|null param1a]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [mixed|null param1a]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [mixed|null param1a]', ], [ 'callable' => function (callable $param1c) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [callable param1c]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [callable param1c]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [callable param1c]', ], [ 'callable' => function (\stdClass $param1d) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [stdClass param1d]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [stdClass param1d]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [stdClass param1d]', ], [ 'callable' => function (?\stdClass $param1e = null) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [stdClass|null [param1e]]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [stdClass|null [param1e]]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [stdClass|null [param1e]]', ], [ 'callable' => function (array &$param1f) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [array ¶m1f]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [array ¶m1f]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [array ¶m1f]', ], [ 'callable' => function (?array &$param1g = null) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [array|null [¶m1g]]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [array|null [¶m1g]]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [array|null [¶m1g]]', ], [ 'callable' => [$this, 'serializableCallableProvider'], @@ -509,35 +525,47 @@ public function serializableCallableProvider(): array 'callable' => function (int $param1_70a) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [int param1_70a]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [int param1_70a]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [int param1_70a]', ], [ 'callable' => function (&$param): int { return (int) $param; }, - 'expected' => 'Lambda int ' . __NAMESPACE__ . '\\{closure} [mixed|null ¶m]', + 'expected' => $prettyClosureNames + ? 'Lambda int {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [mixed|null ¶m]' + : 'Lambda int ' . __NAMESPACE__ . '\\{closure} [mixed|null ¶m]', ], [ 'callable' => function (int $param): ?int { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda int ' . __NAMESPACE__ . '\\{closure} [int param]', + 'expected' => $prettyClosureNames + ? 'Lambda int {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [int param]' + : 'Lambda int ' . __NAMESPACE__ . '\\{closure} [int param]', ], [ 'callable' => function (?int $param1_70b) { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda ' . __NAMESPACE__ . '\\{closure} [int|null param1_70b]', + 'expected' => $prettyClosureNames + ? 'Lambda {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [int|null param1_70b]' + : 'Lambda ' . __NAMESPACE__ . '\\{closure} [int|null param1_70b]', ], [ 'callable' => function (?int $param1_70c): void { throw new \Exception('Don\'t even think about invoke me'); }, - 'expected' => 'Lambda void ' . __NAMESPACE__ . '\\{closure} [int|null param1_70c]', + 'expected' => $prettyClosureNames + ? 'Lambda void {closure:' . __CLASS__ . '::' . __FUNCTION__ . '():%d} [int|null param1_70c]' + : 'Lambda void ' . __NAMESPACE__ . '\\{closure} [int|null param1_70c]', ], [ 'callable' => $callableWithoutNamespaces, - 'expected' => 'Lambda void {closure} [int|null param1_70ns]', + 'expected' => $prettyClosureNames + ? 'Lambda void {closure:%s:%d} [int|null param1_70ns]' + : 'Lambda void {closure} [int|null param1_70ns]', ], [ // 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 $serializer = $this->createSerializer(); $actual = $this->invokeSerialization($serializer, $callable); - $this->assertSame($expected, $actual); + $this->assertStringMatchesFormat($expected, $actual); $actual = $this->invokeSerialization($serializer, [$callable]); - $this->assertSame([$expected], $actual); + $this->assertStringMatchesFormat($expected, $actual[0]); } /** diff --git a/tests/SeverityTest.php b/tests/SeverityTest.php index 79ade6add..63d2184f7 100644 --- a/tests/SeverityTest.php +++ b/tests/SeverityTest.php @@ -83,7 +83,8 @@ public static function levelsDataProvider(): array // Info [\E_NOTICE, 'info'], [\E_USER_NOTICE, 'info'], - [\E_STRICT, 'info'], + // This is \E_STRICT which has been deprecated in PHP 8.4 so we should not reference it directly to prevent deprecation notices + [2048, 'info'], ]; } } diff --git a/tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt b/tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt index 2ab9a423e..35deedee9 100644 --- a/tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt +++ b/tests/phpt/error_handler_respects_error_types_option_regardless_of_error_reporting.phpt @@ -62,7 +62,13 @@ trigger_error('Error thrown', E_USER_WARNING); echo 'Triggering E_USER_ERROR error (unsilenceable on PHP8)' . PHP_EOL; -trigger_error('Error thrown', E_USER_ERROR); +if (PHP_VERSION_ID >= 80400) { + // Silence a deprecation notice on PHP 8.4 + // https://wiki.php.net/rfc/deprecations_php_8_4#deprecate_passing_e_user_error_to_trigger_error + @trigger_error('Error thrown', E_USER_ERROR); +} else { + trigger_error('Error thrown', E_USER_ERROR); +} ?> --EXPECT-- Triggering E_USER_NOTICE error