diff --git a/src/CodeCoverage/Collector.php b/src/CodeCoverage/Collector.php index 1e80412d..cbc9b047 100644 --- a/src/CodeCoverage/Collector.php +++ b/src/CodeCoverage/Collector.php @@ -30,9 +30,9 @@ class Collector public static function detectEngines(): array { return array_filter([ - extension_loaded('pcov') ? self::ENGINE_PCOV : null, - defined('PHPDBG_VERSION') ? self::ENGINE_PHPDBG : null, - extension_loaded('xdebug') ? self::ENGINE_XDEBUG : null, + extension_loaded('pcov') ? [self::ENGINE_PCOV, phpversion('pcov')] : null, + defined('PHPDBG_VERSION') ? [self::ENGINE_PHPDBG, PHPDBG_VERSION] : null, + extension_loaded('xdebug') ? [self::ENGINE_XDEBUG, phpversion('xdebug')] : null, ]); } @@ -52,7 +52,7 @@ public static function start(string $file, string $engine): void if (self::isStarted()) { throw new \LogicException('Code coverage collector has been already started.'); - } elseif (!in_array($engine, self::detectEngines(), true)) { + } elseif (!in_array($engine, array_map(function (array $engineInfo) { return $engineInfo[0]; }, self::detectEngines()), true)) { throw new \LogicException("Code coverage engine '$engine' is not supported."); } diff --git a/src/Runner/CliTester.php b/src/Runner/CliTester.php index cbf96033..f0638f1d 100644 --- a/src/Runner/CliTester.php +++ b/src/Runner/CliTester.php @@ -236,8 +236,14 @@ private function prepareCodeCoverage(Runner $runner): string file_put_contents($this->options['--coverage'], ''); $file = realpath($this->options['--coverage']); + [$engine, $version] = reset($engines); + $runner->setEnvironmentVariable(Environment::COVERAGE, $file); - $runner->setEnvironmentVariable(Environment::COVERAGE_ENGINE, $engine = reset($engines)); + $runner->setEnvironmentVariable(Environment::COVERAGE_ENGINE, $engine); + + if ($engine === CodeCoverage\Collector::ENGINE_XDEBUG && version_compare($version, '3.0.0', '>=')) { + $runner->addPhpIniOption('xdebug.mode', ltrim(ini_get('xdebug.mode') . ',coverage', ',')); + } if ($engine === CodeCoverage\Collector::ENGINE_PCOV && count($this->options['--coverage-src'])) { $runner->addPhpIniOption('pcov.directory', Helpers::findCommonDirectory($this->options['--coverage-src'])); diff --git a/src/Runner/info.php b/src/Runner/info.php index c00d4521..a2c2b012 100644 --- a/src/Runner/info.php +++ b/src/Runner/info.php @@ -36,7 +36,9 @@ 'PHP version' . ($isPhpDbg ? '; PHPDBG version' : '') => "$info->version ($info->sapi)" . ($isPhpDbg ? "; $info->phpDbgVersion" : ''), 'Loaded php.ini files' => count($info->iniFiles) ? implode(', ', $info->iniFiles) : '(none)', - 'Code coverage engines' => count($info->codeCoverageEngines) ? implode(', ', $info->codeCoverageEngines) : '(not available)', + 'Code coverage engines' => count($info->codeCoverageEngines) + ? implode(', ', array_map(function (array $engineInfo) { return sprintf('%s (%s)', ...$engineInfo); }, $info->codeCoverageEngines)) + : '(not available)', 'PHP temporary directory' => $info->tempDir == '' ? '(empty)' : $info->tempDir, 'Loaded extensions' => count($info->extensions) ? implode(', ', $info->extensions) : '(none)', ] as $title => $value) { diff --git a/tests/CodeCoverage/Collector.phpt b/tests/CodeCoverage/Collector.phpt index a6e4d3bb..29074d60 100644 --- a/tests/CodeCoverage/Collector.phpt +++ b/tests/CodeCoverage/Collector.phpt @@ -9,13 +9,21 @@ use Tester\FileMock; require __DIR__ . '/../bootstrap.php'; -$engines = array_filter(CodeCoverage\Collector::detectEngines(), function (string $engine) { +$engines = array_filter(CodeCoverage\Collector::detectEngines(), function (array $engineInfo) { + [$engine] = $engineInfo; return $engine !== CodeCoverage\Collector::ENGINE_PCOV; // PCOV needs system pcov.directory INI to be set }); if (count($engines) < 1) { Tester\Environment::skip('Requires Xdebug or PHPDB SAPI.'); } -$engine = reset($engines); +[$engine, $version] = reset($engines); + +if ($engine === CodeCoverage\Collector::ENGINE_XDEBUG + && version_compare($version, '3.0.0', '>=') + && strpos(ini_get('xdebug.mode'), 'coverage') === false +) { + Tester\Environment::skip('Requires xdebug.mode=coverage with Xdebug 3.'); +} if (CodeCoverage\Collector::isStarted()) { Tester\Environment::skip('Requires running without --coverage.'); diff --git a/tests/Runner/PhpInterpreter.phpt b/tests/Runner/PhpInterpreter.phpt index 13e89b92..2516d628 100644 --- a/tests/Runner/PhpInterpreter.phpt +++ b/tests/Runner/PhpInterpreter.phpt @@ -18,15 +18,15 @@ Assert::same(strpos(PHP_SAPI, 'cgi') !== false, $interpreter->isCgi()); $count = 0; $engines = $interpreter->getCodeCoverageEngines(); if (defined('PHPDBG_VERSION')) { - Assert::contains(Tester\CodeCoverage\Collector::ENGINE_PHPDBG, $engines); + Assert::contains([Tester\CodeCoverage\Collector::ENGINE_PHPDBG, PHPDBG_VERSION], $engines); $count++; } if (extension_loaded('xdebug')) { - Assert::contains(Tester\CodeCoverage\Collector::ENGINE_XDEBUG, $engines); + Assert::contains([Tester\CodeCoverage\Collector::ENGINE_XDEBUG, phpversion('xdebug')], $engines); $count++; } if (extension_loaded('pcov')) { - Assert::contains(Tester\CodeCoverage\Collector::ENGINE_PCOV, $engines); + Assert::contains([Tester\CodeCoverage\Collector::ENGINE_PCOV, phpversion('pcov')], $engines); $count++; } Assert::count($count, $engines);