From 56a2f1b7339b3c257f216fe854bc62d73af13bc2 Mon Sep 17 00:00:00 2001 From: Nuno Maduro Date: Sat, 18 Feb 2023 16:09:50 +0000 Subject: [PATCH] fix: what's considered a "deffect" test --- .../Runner/ResultCache/DefaultResultCache.php | 181 ++++++++++++++++++ src/Bootstrappers/BootOverrides.php | 1 + 2 files changed, 182 insertions(+) create mode 100644 overrides/Runner/ResultCache/DefaultResultCache.php diff --git a/overrides/Runner/ResultCache/DefaultResultCache.php b/overrides/Runner/ResultCache/DefaultResultCache.php new file mode 100644 index 00000000..3fafc486 --- /dev/null +++ b/overrides/Runner/ResultCache/DefaultResultCache.php @@ -0,0 +1,181 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PHPUnit\Runner\ResultCache; + +use function array_keys; +use function assert; +use const DIRECTORY_SEPARATOR; +use function dirname; +use function file_get_contents; +use function file_put_contents; +use function is_array; +use function is_dir; +use function is_file; +use function json_decode; +use function json_encode; +use PHPUnit\Framework\TestStatus\TestStatus; +use PHPUnit\Runner\DirectoryCannotBeCreatedException; +use PHPUnit\Runner\Exception; +use PHPUnit\Util\Filesystem; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class DefaultResultCache implements ResultCache +{ + /** + * @var int + */ + private const VERSION = 1; + + /** + * @var string + */ + private const DEFAULT_RESULT_CACHE_FILENAME = '.phpunit.result.cache'; + + private readonly string $cacheFilename; + + /** + * @psalm-var array + */ + private array $defects = []; + + /** + * @psalm-var array + */ + private array $times = []; + + public function __construct(?string $filepath = null) + { + if ($filepath !== null && is_dir($filepath)) { + $filepath .= DIRECTORY_SEPARATOR.self::DEFAULT_RESULT_CACHE_FILENAME; + } + + $this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME; + } + + public function setStatus(string $id, TestStatus $status): void + { + if ($status->isFailure() || $status->isError()) { + $this->defects[$id] = $status; + } + } + + public function status(string $id): TestStatus + { + return $this->defects[$id] ?? TestStatus::unknown(); + } + + public function setTime(string $id, float $time): void + { + $this->times[$id] = $time; + } + + public function time(string $id): float + { + return $this->times[$id] ?? 0.0; + } + + public function load(): void + { + if (! is_file($this->cacheFilename)) { + return; + } + + $data = json_decode( + file_get_contents($this->cacheFilename), + true + ); + + if ($data === null) { + return; + } + + if (! isset($data['version'])) { + return; + } + + if ($data['version'] !== self::VERSION) { + return; + } + + assert(isset($data['defects']) && is_array($data['defects'])); + assert(isset($data['times']) && is_array($data['times'])); + + foreach (array_keys($data['defects']) as $test) { + $data['defects'][$test] = TestStatus::from($data['defects'][$test]); + } + + $this->defects = $data['defects']; + $this->times = $data['times']; + } + + /** + * @throws Exception + */ + public function persist(): void + { + if (! Filesystem::createDirectory(dirname($this->cacheFilename))) { + throw new DirectoryCannotBeCreatedException($this->cacheFilename); + } + + $data = [ + 'version' => self::VERSION, + 'defects' => [], + 'times' => $this->times, + ]; + + foreach ($this->defects as $test => $status) { + $data['defects'][$test] = $status->asInt(); + } + + file_put_contents( + $this->cacheFilename, + json_encode($data), + LOCK_EX + ); + } +} diff --git a/src/Bootstrappers/BootOverrides.php b/src/Bootstrappers/BootOverrides.php index 3d3e7fa8..7b3d2307 100644 --- a/src/Bootstrappers/BootOverrides.php +++ b/src/Bootstrappers/BootOverrides.php @@ -19,6 +19,7 @@ final class BootOverrides implements Bootstrapper */ private const FILES = [ 'Runner/Filter/NameFilterIterator.php', + 'Runner/ResultCache/DefaultResultCache.php', 'Runner/TestSuiteLoader.php', 'TextUI/Output/Default/ProgressPrinter/TestSkippedSubscriber.php', ];