diff --git a/src/Data/ProcessedBranchCoverageData.php b/src/Data/ProcessedBranchCoverageData.php new file mode 100644 index 000000000..2b6076160 --- /dev/null +++ b/src/Data/ProcessedBranchCoverageData.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Data; + +use function array_merge; +use function array_unique; +use NoDiscard; +use SebastianBergmann\CodeCoverage\Driver\XdebugDriver; + +/** + * @phpstan-import-type TestIdType from ProcessedCodeCoverageData + * @phpstan-import-type XdebugBranchCoverageType from XdebugDriver + */ +final class ProcessedBranchCoverageData +{ + /** + * @param XdebugBranchCoverageType $xdebugCoverageData + */ + public static function fromXdebugCoverage(array $xdebugCoverageData): self + { + return new self( + $xdebugCoverageData['op_start'], + $xdebugCoverageData['op_end'], + $xdebugCoverageData['line_start'], + $xdebugCoverageData['line_end'], + [], + $xdebugCoverageData['out'], + $xdebugCoverageData['out_hit'], + ); + } + + public function __construct( + public readonly int $op_start, + public readonly int $op_end, + public readonly int $line_start, + public readonly int $line_end, + /** @var list */ + public array $hit, + /** @var array */ + public readonly array $out, + /** @var array */ + public readonly array $out_hit, + ) { + } + + #[NoDiscard] + public function merge(self $data): self + { + if ($data->hit === []) { + return $this; + } + + return new self( + $this->op_start, + $this->op_end, + $this->line_start, + $this->line_end, + array_unique(array_merge($this->hit, $data->hit)), + $this->out, + $this->out_hit, + ); + } + + /** + * @param TestIdType $testCaseId + */ + public function recordHit(string $testCaseId): void + { + $this->hit[] = $testCaseId; + } +} diff --git a/src/Data/ProcessedCodeCoverageData.php b/src/Data/ProcessedCodeCoverageData.php index 49a103236..5745ccb08 100644 --- a/src/Data/ProcessedCodeCoverageData.php +++ b/src/Data/ProcessedCodeCoverageData.php @@ -25,22 +25,7 @@ * @phpstan-import-type XdebugFunctionCoverageType from XdebugDriver * * @phpstan-type TestIdType string - * @phpstan-type FunctionCoverageDataType array{ - * branches: array, - * out: array, - * out_hit: array, - * }>, - * paths: array, - * hit: list, - * }> - * } - * @phpstan-type FunctionCoverageType array> + * @phpstan-type FunctionCoverageType array> * @phpstan-type LineCoverageType array>> */ final class ProcessedCodeCoverageData @@ -99,13 +84,13 @@ public function markCodeAsExecutedByTestCase(string $testCaseId, RawCodeCoverage foreach ($functions as $functionName => $functionData) { foreach ($functionData['branches'] as $branchId => $branchData) { if ($branchData['hit'] === Driver::BRANCH_HIT) { - $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'][] = $testCaseId; + $this->functionCoverage[$file][$functionName]->recordBranchHit($branchId, $testCaseId); } } foreach ($functionData['paths'] as $pathId => $pathData) { if ($pathData['hit'] === Driver::BRANCH_HIT) { - $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'][] = $testCaseId; + $this->functionCoverage[$file][$functionName]->recordPathHit($pathId, $testCaseId); } } } @@ -213,14 +198,6 @@ public function merge(self $newData): void } else { $this->initPreviouslyUnseenFunction($file, $functionName, $functionData); } - - foreach ($functionData['branches'] as $branchId => $branchData) { - $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'], $branchData['hit'])); - } - - foreach ($functionData['paths'] as $pathId => $pathData) { - $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = array_unique(array_merge($this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'], $pathData['hit'])); - } } } } @@ -257,19 +234,15 @@ private function priorityForLine(array $data, int $line): int /** * For a function we have never seen before, copy all data over and simply init the 'hit' array. * - * @param FunctionCoverageDataType|XdebugFunctionCoverageType $functionData + * @param ProcessedFunctionCoverageData|XdebugFunctionCoverageType $functionData */ - private function initPreviouslyUnseenFunction(string $file, string $functionName, array $functionData): void + private function initPreviouslyUnseenFunction(string $file, string $functionName, array|ProcessedFunctionCoverageData $functionData): void { - $this->functionCoverage[$file][$functionName] = $functionData; - - foreach (array_keys($functionData['branches']) as $branchId) { - $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = []; + if (is_array($functionData)) { + $functionData = ProcessedFunctionCoverageData::fromXdebugCoverage($functionData); } - foreach (array_keys($functionData['paths']) as $pathId) { - $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = []; - } + $this->functionCoverage[$file][$functionName] = $functionData; } /** @@ -277,22 +250,16 @@ private function initPreviouslyUnseenFunction(string $file, string $functionName * Techniques such as mocking and where the contents of a file are different vary during tests (e.g. compiling * containers) mean that the functions inside a file cannot be relied upon to be static. * - * @param FunctionCoverageDataType|XdebugFunctionCoverageType $functionData + * @param ProcessedFunctionCoverageData|XdebugFunctionCoverageType $functionData */ - private function initPreviouslySeenFunction(string $file, string $functionName, array $functionData): void + private function initPreviouslySeenFunction(string $file, string $functionName, array|ProcessedFunctionCoverageData $functionData): void { - foreach ($functionData['branches'] as $branchId => $branchData) { - if (!isset($this->functionCoverage[$file][$functionName]['branches'][$branchId])) { - $this->functionCoverage[$file][$functionName]['branches'][$branchId] = $branchData; - $this->functionCoverage[$file][$functionName]['branches'][$branchId]['hit'] = []; - } + if (is_array($functionData)) { + $functionData = ProcessedFunctionCoverageData::fromXdebugCoverage($functionData); } - foreach ($functionData['paths'] as $pathId => $pathData) { - if (!isset($this->functionCoverage[$file][$functionName]['paths'][$pathId])) { - $this->functionCoverage[$file][$functionName]['paths'][$pathId] = $pathData; - $this->functionCoverage[$file][$functionName]['paths'][$pathId]['hit'] = []; - } - } + $this->functionCoverage[$file][$functionName] = $this->functionCoverage[$file][$functionName]->merge( + $functionData, + ); } } diff --git a/src/Data/ProcessedFunctionCoverageData.php b/src/Data/ProcessedFunctionCoverageData.php new file mode 100644 index 000000000..7a12f32d7 --- /dev/null +++ b/src/Data/ProcessedFunctionCoverageData.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Data; + +use SebastianBergmann\CodeCoverage\Driver\XdebugDriver; + +/** + * @phpstan-import-type TestIdType from ProcessedCodeCoverageData + * @phpstan-import-type XdebugFunctionCoverageType from XdebugDriver + */ +final readonly class ProcessedFunctionCoverageData +{ + /** + * @param XdebugFunctionCoverageType $xdebugCoverageData + */ + public static function fromXdebugCoverage(array $xdebugCoverageData): self + { + $branches = []; + + foreach ($xdebugCoverageData['branches'] as $branchId => $branch) { + $branches[$branchId] = ProcessedBranchCoverageData::fromXdebugCoverage($branch); + } + $paths = []; + + foreach ($xdebugCoverageData['paths'] as $pathId => $path) { + $paths[$pathId] = ProcessedPathCoverageData::fromXdebugCoverage($path); + } + + return new self( + $branches, + $paths, + ); + } + + public function __construct( + /** @var array */ + public array $branches, + /** @var array */ + public array $paths, + ) { + } + + public function merge(self $data): self + { + $branches = null; + + if ($data->branches !== $this->branches) { + $branches = $this->branches; + + foreach ($data->branches as $branchId => $branch) { + if (!isset($branches[$branchId])) { + $branches[$branchId] = $branch; + } else { + $branches[$branchId] = $branches[$branchId]->merge($branch); + } + } + } + + $paths = null; + + if ($data->paths !== $this->paths) { + $paths = $this->paths; + + foreach ($data->paths as $pathId => $path) { + if (!isset($paths[$pathId])) { + $paths[$pathId] = $path; + } else { + $paths[$pathId] = $paths[$pathId]->merge($path); + } + } + } + + if ($branches === null && $paths === null) { + return $this; + } + + return new self( + $branches ?? $this->branches, + $paths ?? $this->paths, + ); + } + + /** + * @param TestIdType $testCaseId + */ + public function recordBranchHit(int $branchId, string $testCaseId): void + { + $this->branches[$branchId]->recordHit($testCaseId); + } + + /** + * @param TestIdType $testCaseId + */ + public function recordPathHit(int $pathId, string $testCaseId): void + { + $this->paths[$pathId]->recordHit($testCaseId); + } +} diff --git a/src/Data/ProcessedPathCoverageData.php b/src/Data/ProcessedPathCoverageData.php new file mode 100644 index 000000000..ccb651931 --- /dev/null +++ b/src/Data/ProcessedPathCoverageData.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace SebastianBergmann\CodeCoverage\Data; + +use function array_merge; +use function array_unique; +use NoDiscard; +use SebastianBergmann\CodeCoverage\Driver\XdebugDriver; + +/** + * @phpstan-import-type TestIdType from ProcessedCodeCoverageData + * @phpstan-import-type XdebugPathCoverageType from XdebugDriver + */ +final class ProcessedPathCoverageData +{ + /** + * @param XdebugPathCoverageType $xdebugCoverageData + */ + public static function fromXdebugCoverage(array $xdebugCoverageData): self + { + return new self( + $xdebugCoverageData['path'], + [], + ); + } + + public function __construct( + /** @var array */ + public readonly array $path, + /** @var list */ + public array $hit, + ) { + } + + #[NoDiscard] + public function merge(self $data): self + { + if ($data->hit === []) { + return $this; + } + + return new self( + $this->path, + array_unique(array_merge($this->hit, $data->hit)), + ); + } + + /** + * @param TestIdType $testCaseId + */ + public function recordHit(string $testCaseId): void + { + $this->hit[] = $testCaseId; + } +} diff --git a/src/Node/File.php b/src/Node/File.php index 54ee70b4a..18f97f808 100644 --- a/src/Node/File.php +++ b/src/Node/File.php @@ -13,6 +13,8 @@ use function count; use function range; use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Data\ProcessedBranchCoverageData; +use SebastianBergmann\CodeCoverage\Data\ProcessedPathCoverageData; use SebastianBergmann\CodeCoverage\StaticAnalysis\AnalysisResult; use SebastianBergmann\CodeCoverage\StaticAnalysis\Class_; use SebastianBergmann\CodeCoverage\StaticAnalysis\Function_; @@ -600,33 +602,33 @@ private function processFunctions(array $functions): void $this->codeUnitsByLine[$lineNumber] = [&$this->functions[$functionName]]; } - if (isset($this->functionCoverageData[$functionName]['branches'])) { + if (isset($this->functionCoverageData[$functionName])) { $this->functions[$functionName]['executableBranches'] = count( - $this->functionCoverageData[$functionName]['branches'], + $this->functionCoverageData[$functionName]->branches, ); $this->functions[$functionName]['executedBranches'] = count( array_filter( - $this->functionCoverageData[$functionName]['branches'], - static function (array $branch) + $this->functionCoverageData[$functionName]->branches, + static function (ProcessedBranchCoverageData $branch) { - return (bool) $branch['hit']; + return (bool) $branch->hit; }, ), ); } - if (isset($this->functionCoverageData[$functionName]['paths'])) { + if (isset($this->functionCoverageData[$functionName])) { $this->functions[$functionName]['executablePaths'] = count( - $this->functionCoverageData[$functionName]['paths'], + $this->functionCoverageData[$functionName]->paths, ); $this->functions[$functionName]['executedPaths'] = count( array_filter( - $this->functionCoverageData[$functionName]['paths'], - static function (array $path) + $this->functionCoverageData[$functionName]->paths, + static function (ProcessedPathCoverageData $path) { - return (bool) $path['hit']; + return (bool) $path->hit; }, ), ); @@ -664,33 +666,33 @@ private function newMethod(string $className, Method $method, string $link): arr $key = $className . '->' . $method->name(); - if (isset($this->functionCoverageData[$key]['branches'])) { + if (isset($this->functionCoverageData[$key])) { $methodData['executableBranches'] = count( - $this->functionCoverageData[$key]['branches'], + $this->functionCoverageData[$key]->branches, ); $methodData['executedBranches'] = count( array_filter( - $this->functionCoverageData[$key]['branches'], - static function (array $branch) + $this->functionCoverageData[$key]->branches, + static function (ProcessedBranchCoverageData $branch) { - return (bool) $branch['hit']; + return (bool) $branch->hit; }, ), ); } - if (isset($this->functionCoverageData[$key]['paths'])) { + if (isset($this->functionCoverageData[$key])) { $methodData['executablePaths'] = count( - $this->functionCoverageData[$key]['paths'], + $this->functionCoverageData[$key]->paths, ); $methodData['executedPaths'] = count( array_filter( - $this->functionCoverageData[$key]['paths'], - static function (array $path) + $this->functionCoverageData[$key]->paths, + static function (ProcessedPathCoverageData $path) { - return (bool) $path['hit']; + return (bool) $path->hit; }, ), ); diff --git a/src/Report/Html/Renderer/File.php b/src/Report/Html/Renderer/File.php index 09dbe31fe..7b77bc38c 100644 --- a/src/Report/Html/Renderer/File.php +++ b/src/Report/Html/Renderer/File.php @@ -102,6 +102,9 @@ use function str_replace; use function token_get_all; use function trim; +use SebastianBergmann\CodeCoverage\Data\ProcessedBranchCoverageData; +use SebastianBergmann\CodeCoverage\Data\ProcessedFunctionCoverageData; +use SebastianBergmann\CodeCoverage\Data\ProcessedPathCoverageData; use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException; use SebastianBergmann\CodeCoverage\Node\File as FileNode; use SebastianBergmann\CodeCoverage\Util\Percentage; @@ -607,18 +610,20 @@ private function renderSourceWithBranchCoverage(FileNode $node): string ]; } + /** @var ProcessedFunctionCoverageData $method */ foreach ($functionCoverageData as $method) { - foreach ($method['branches'] as $branch) { - foreach (range($branch['line_start'], $branch['line_end']) as $line) { + /** @var ProcessedBranchCoverageData $branch */ + foreach ($method->branches as $branch) { + foreach (range($branch->line_start, $branch->line_end) as $line) { if (!isset($lineData[$line])) { // blank line at end of file is sometimes included here continue; } $lineData[$line]['includedInBranches']++; - if ($branch['hit']) { + if ($branch->hit !== []) { $lineData[$line]['includedInHitBranches']++; - $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $branch['hit'])); + $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $branch->hit)); } } } @@ -693,18 +698,20 @@ private function renderSourceWithPathCoverage(FileNode $node): string ]; } + /** @var ProcessedFunctionCoverageData $method */ foreach ($functionCoverageData as $method) { - foreach ($method['paths'] as $pathId => $path) { - foreach ($path['path'] as $branchTaken) { - foreach (range($method['branches'][$branchTaken]['line_start'], $method['branches'][$branchTaken]['line_end']) as $line) { + /** @var ProcessedPathCoverageData $path */ + foreach ($method->paths as $pathId => $path) { + foreach ($path->path as $branchTaken) { + foreach (range($method->branches[$branchTaken]->line_start, $method->branches[$branchTaken]->line_end) as $line) { if (!isset($lineData[$line])) { continue; } $lineData[$line]['includedInPaths'][] = $pathId; - if ($path['hit']) { + if ($path->hit !== []) { $lineData[$line]['includedInHitPaths'][] = $pathId; - $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $path['hit'])); + $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $path->hit)); } } } @@ -774,14 +781,12 @@ private function renderBranchStructure(FileNode $node): string ksort($coverageData); + /** @var ProcessedFunctionCoverageData $methodData */ foreach ($coverageData as $methodName => $methodData) { - if (!$methodData['branches']) { - continue; - } - $branchStructure = ''; - foreach ($methodData['branches'] as $branch) { + /** @var ProcessedBranchCoverageData $branch */ + foreach ($methodData->branches as $branch) { $branchStructure .= $this->renderBranchLines($branch, $codeLines, $testData); } @@ -799,14 +804,14 @@ private function renderBranchStructure(FileNode $node): string /** * @param list $codeLines */ - private function renderBranchLines(array $branch, array $codeLines, array $testData): string + private function renderBranchLines(ProcessedBranchCoverageData $branch, array $codeLines, array $testData): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $lines = ''; - $branchLines = range($branch['line_start'], $branch['line_end']); + $branchLines = range($branch->line_start, $branch->line_end); sort($branchLines); // sometimes end_line < start_line /** @var int $line */ @@ -818,7 +823,7 @@ private function renderBranchLines(array $branch, array $codeLines, array $testD $popoverContent = ''; $popoverTitle = ''; - $numTests = count($branch['hit']); + $numTests = count($branch->hit); if ($numTests === 0) { $trClass = 'danger'; @@ -832,7 +837,7 @@ private function renderBranchLines(array $branch, array $codeLines, array $testD $popoverTitle = '1 test covers this branch'; } - foreach ($branch['hit'] as $test) { + foreach ($branch->hit as $test) { if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { $lineCss = 'covered-by-medium-tests'; } elseif ($testData[$test]['size'] === 'small') { @@ -877,21 +882,18 @@ private function renderPathStructure(FileNode $node): string ksort($coverageData); + /** @var ProcessedFunctionCoverageData $methodData */ foreach ($coverageData as $methodName => $methodData) { - if (!$methodData['paths']) { - continue; - } - $pathStructure = ''; - if (count($methodData['paths']) > 100) { - $pathStructure .= '

' . count($methodData['paths']) . ' is too many paths to sensibly render, consider refactoring your code to bring this number down.

'; + if (count($methodData->paths) > 100) { + $pathStructure .= '

' . count($methodData->paths) . ' is too many paths to sensibly render, consider refactoring your code to bring this number down.

'; continue; } - foreach ($methodData['paths'] as $path) { - $pathStructure .= $this->renderPathLines($path, $methodData['branches'], $codeLines, $testData); + foreach ($methodData->paths as $path) { + $pathStructure .= $this->renderPathLines($path, $methodData->branches, $codeLines, $testData); } if ($pathStructure !== '') { @@ -906,9 +908,10 @@ private function renderPathStructure(FileNode $node): string } /** - * @param list $codeLines + * @param array $branches + * @param list $codeLines */ - private function renderPathLines(array $path, array $branches, array $codeLines, array $testData): string + private function renderPathLines(ProcessedPathCoverageData $path, array $branches, array $codeLines, array $testData): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); @@ -916,14 +919,14 @@ private function renderPathLines(array $path, array $branches, array $codeLines, $lines = ''; $first = true; - foreach ($path['path'] as $branchId) { + foreach ($path->path as $branchId) { if ($first) { $first = false; } else { $lines .= '  ' . "\n"; } - $branchLines = range($branches[$branchId]['line_start'], $branches[$branchId]['line_end']); + $branchLines = range($branches[$branchId]->line_start, $branches[$branchId]->line_end); sort($branchLines); // sometimes end_line < start_line /** @var int $line */ @@ -935,7 +938,7 @@ private function renderPathLines(array $path, array $branches, array $codeLines, $popoverContent = ''; $popoverTitle = ''; - $numTests = count($path['hit']); + $numTests = count($path->hit); if ($numTests === 0) { $trClass = 'danger'; @@ -949,7 +952,7 @@ private function renderPathLines(array $path, array $branches, array $codeLines, $popoverTitle = '1 test covers this path'; } - foreach ($path['hit'] as $test) { + foreach ($path->hit as $test) { if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { $lineCss = 'covered-by-medium-tests'; } elseif ($testData[$test]['size'] === 'small') { diff --git a/tests/src/TestCase.php b/tests/src/TestCase.php index ba87455db..f8273d17c 100644 --- a/tests/src/TestCase.php +++ b/tests/src/TestCase.php @@ -14,6 +14,9 @@ use BankAccount; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; +use SebastianBergmann\CodeCoverage\Data\ProcessedBranchCoverageData; +use SebastianBergmann\CodeCoverage\Data\ProcessedFunctionCoverageData; +use SebastianBergmann\CodeCoverage\Data\ProcessedPathCoverageData; use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData; use SebastianBergmann\CodeCoverage\Driver\Driver; use SebastianBergmann\CodeCoverage\Test\Target\Target; @@ -1560,201 +1563,199 @@ protected function getExpectedPathCoverageDataArrayForBankAccount(): array { return [ TEST_FILES_PATH . 'BankAccount.php' => [ - 'BankAccount->depositMoney' => [ - 'branches' => [ - 0 => [ - 'op_start' => 0, - 'op_end' => 14, - 'line_start' => 20, - 'line_end' => 25, - 'hit' => [ + 'BankAccount->depositMoney' => new ProcessedFunctionCoverageData( + [ + 0 => new ProcessedBranchCoverageData( + 0, + 14, + 20, + 25, + [ 0 => 'BankAccountTest::testBalanceCannotBecomeNegative2', 1 => 'BankAccountTest::testDepositWithdrawMoney', ], - 'out' => [ - ], - 'out_hit' => [ - ], - ], + [], + [], + ), ], - 'paths' => [ - 0 => [ - 'path' => [ + [ + 0 => new ProcessedPathCoverageData( + [ 0 => 0, ], - 'hit' => [ + [ 0 => 'BankAccountTest::testBalanceCannotBecomeNegative2', 1 => 'BankAccountTest::testDepositWithdrawMoney', ], - ], + ), ], - ], - 'BankAccount->getBalance' => [ - 'branches' => [ - 0 => [ - 'op_start' => 0, - 'op_end' => 5, - 'line_start' => 6, - 'line_end' => 9, - 'hit' => [ + ), + 'BankAccount->getBalance' => new ProcessedFunctionCoverageData( + [ + 0 => new ProcessedBranchCoverageData( + 0, + 5, + 6, + 9, + [ 0 => 'BankAccountTest::testBalanceIsInitiallyZero', 1 => 'BankAccountTest::testDepositWithdrawMoney', ], - 'out' => [ + [ ], - 'out_hit' => [ + [ ], - ], + ), ], - 'paths' => [ - 0 => [ - 'path' => [ + [ + 0 => new ProcessedPathCoverageData( + [ 0 => 0, ], - 'hit' => [ + [ 0 => 'BankAccountTest::testBalanceIsInitiallyZero', 1 => 'BankAccountTest::testDepositWithdrawMoney', ], - ], + ), ], - ], - 'BankAccount->withdrawMoney' => [ - 'branches' => [ - 0 => [ - 'op_start' => 0, - 'op_end' => 14, - 'line_start' => 27, - 'line_end' => 32, - 'hit' => [ + ), + 'BankAccount->withdrawMoney' => new ProcessedFunctionCoverageData( + [ + 0 => new ProcessedBranchCoverageData( + 0, + 14, + 27, + 32, + [ 0 => 'BankAccountTest::testBalanceCannotBecomeNegative', 1 => 'BankAccountTest::testDepositWithdrawMoney', ], - 'out' => [ + [ ], - 'out_hit' => [ + [ ], - ], + ), ], - 'paths' => [ - 0 => [ - 'path' => [ + [ + 0 => new ProcessedPathCoverageData( + [ 0 => 0, ], - 'hit' => [ + [ 0 => 'BankAccountTest::testBalanceCannotBecomeNegative', 1 => 'BankAccountTest::testDepositWithdrawMoney', ], - ], + ), ], - ], - '{main}' => [ - 'branches' => [ - 0 => [ - 'op_start' => 0, - 'op_end' => 1, - 'line_start' => 34, - 'line_end' => 34, - 'hit' => [ - ], - 'out' => [ + ), + '{main}' => new ProcessedFunctionCoverageData( + [ + 0 => new ProcessedBranchCoverageData( + 0, + 1, + 34, + 34, + [ + ], + [ 0 => 2147483645, ], - 'out_hit' => [ + [ 0 => 0, ], - ], + ), ], - 'paths' => [ - 0 => [ - 'path' => [ + [ + 0 => new ProcessedPathCoverageData( + [ 0 => 0, ], - 'hit' => [ + [ ], - ], + ), ], - ], - 'BankAccount->setBalance' => [ - 'branches' => [ - 0 => [ - 'op_start' => 0, - 'op_end' => 4, - 'line_start' => 11, - 'line_end' => 13, - 'hit' => [ - ], - 'out' => [ + ), + 'BankAccount->setBalance' => new ProcessedFunctionCoverageData( + [ + 0 => new ProcessedBranchCoverageData( + 0, + 4, + 11, + 13, + [ + ], + [ 0 => 5, 1 => 9, ], - 'out_hit' => [ + [ 0 => 0, 1 => 0, ], - ], - 5 => [ - 'op_start' => 5, - 'op_end' => 8, - 'line_start' => 14, - 'line_end' => 14, - 'hit' => [ - ], - 'out' => [ + ), + 5 => new ProcessedBranchCoverageData( + 5, + 8, + 14, + 14, + [ + ], + [ 0 => 13, ], - 'out_hit' => [ + [ 0 => 0, ], - ], - 9 => [ - 'op_start' => 9, - 'op_end' => 12, - 'line_start' => 16, - 'line_end' => 16, - 'hit' => [ - ], - 'out' => [ + ), + 9 => new ProcessedBranchCoverageData( + 9, + 12, + 16, + 16, + [ + ], + [ 0 => 2147483645, ], - 'out_hit' => [ + [ 0 => 0, ], - ], - 13 => [ - 'op_start' => 13, - 'op_end' => 14, - 'line_start' => 18, - 'line_end' => 18, - 'hit' => [ - ], - 'out' => [ + ), + 13 => new ProcessedBranchCoverageData( + 13, + 14, + 18, + 18, + [ + ], + [ 0 => 2147483645, ], - 'out_hit' => [ + [ 0 => 0, ], - ], + ), ], - 'paths' => [ - 0 => [ - 'path' => [ + [ + 0 => new ProcessedPathCoverageData( + [ 0 => 0, 1 => 5, 2 => 13, ], - 'hit' => [ + [ ], - ], - 1 => [ - 'path' => [ + ), + 1 => new ProcessedPathCoverageData( + [ 0 => 0, 1 => 9, ], - 'hit' => [ + [ ], - ], + ), ], - ], + ), ], ]; } diff --git a/tests/tests/Data/ProcessedCodeCoverageDataTest.php b/tests/tests/Data/ProcessedCodeCoverageDataTest.php index 46e144eec..e903636b8 100644 --- a/tests/tests/Data/ProcessedCodeCoverageDataTest.php +++ b/tests/tests/Data/ProcessedCodeCoverageDataTest.php @@ -75,29 +75,27 @@ public function testMergeDoesNotCrashWhenFileContentsHaveChanged(): void $coverage->setFunctionCoverage( [ '/some/path/SomeClass.php' => [ - 'SomeClass->firstFunction' => [ - 'branches' => [ - 0 => [ - 'op_start' => 0, - 'op_end' => 14, - 'line_start' => 20, - 'line_end' => 25, - 'hit' => [], - 'out' => [ - ], - 'out_hit' => [ - ], - ], + 'SomeClass->firstFunction' => new ProcessedFunctionCoverageData( + [ + 0 => new ProcessedBranchCoverageData( + 0, + 14, + 20, + 25, + [], + [], + [], + ), ], - 'paths' => [ - 0 => [ - 'path' => [ + [ + 0 => new ProcessedPathCoverageData( + [ 0 => 0, ], - 'hit' => [], - ], + [], + ), ], - ], + ), ], ], ); @@ -106,75 +104,70 @@ public function testMergeDoesNotCrashWhenFileContentsHaveChanged(): void $newCoverage->setFunctionCoverage( [ '/some/path/SomeClass.php' => [ - 'SomeClass->firstFunction' => [ - 'branches' => [ - 0 => [ - 'op_start' => 0, - 'op_end' => 14, - 'line_start' => 20, - 'line_end' => 25, - 'hit' => [], - 'out' => [ - ], - 'out_hit' => [ - ], - ], - 1 => [ - 'op_start' => 15, - 'op_end' => 16, - 'line_start' => 26, - 'line_end' => 27, - 'hit' => [], - 'out' => [ - ], - 'out_hit' => [ - ], - ], + 'SomeClass->firstFunction' => new ProcessedFunctionCoverageData( + [ + 0 => new ProcessedBranchCoverageData( + 0, + 14, + 20, + 25, + [], + [], + [], + ), + 1 => new ProcessedBranchCoverageData( + 15, + 16, + 26, + 27, + [], + [], + [], + ), ], - 'paths' => [ - 0 => [ - 'path' => [ + [ + 0 => new ProcessedPathCoverageData( + [ 0 => 0, ], - 'hit' => [], - ], - 1 => [ - 'path' => [ + [], + ), + 1 => new ProcessedPathCoverageData( + [ 0 => 1, ], - 'hit' => [], - ], + [], + ), ], - ], - 'SomeClass->secondFunction' => [ - 'branches' => [ - 0 => [ - 'op_start' => 0, - 'op_end' => 24, - 'line_start' => 30, - 'line_end' => 35, - 'hit' => [], - 'out' => [ - ], - 'out_hit' => [ - ], - ], + ), + 'SomeClass->secondFunction' => new ProcessedFunctionCoverageData( + [ + 0 => new ProcessedBranchCoverageData( + 0, + 24, + 30, + 35, + [], + [], + [], + ), ], - 'paths' => [ - 0 => [ - 'path' => [ + [ + 0 => new ProcessedPathCoverageData( + [ 0 => 0, ], - 'hit' => [], - ], + [], + ), ], - ], + ), ], ], ); $coverage->merge($newCoverage); + $this->assertIsArray($newCoverage->functionCoverage()['/some/path/SomeClass.php']); $this->assertArrayHasKey('SomeClass->secondFunction', $newCoverage->functionCoverage()['/some/path/SomeClass.php']); } }