Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
if: ${{ matrix.php-version != env.HIGHEST_PHP_VERSION }}

- name: Run PHPUnit with coverage
run: vendor/bin/phpunit --coverage-clover clover.xml
run: vendor/bin/phpunit --coverage-php coverage.php
env:
DRIVER: mysql_pdo
MYSQL_HOST: 127.0.0.1
Expand All @@ -106,6 +106,10 @@ jobs:
PDO_ERRMODE: ${{ matrix.pdo-errmode }}
if: ${{ matrix.php-version == env.HIGHEST_PHP_VERSION }}

- name: Merge worker coverage
run: php tools/merge-coverage.php coverage.php clover.xml && rm coverage.php
if: ${{ matrix.php-version == env.HIGHEST_PHP_VERSION }}

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
Expand Down Expand Up @@ -154,13 +158,16 @@ jobs:
dependency-versions: ${{ matrix.deps }}

- name: Run PHPUnit with coverage
run: vendor/bin/phpunit --coverage-clover clover.xml
run: vendor/bin/phpunit --coverage-php coverage.php
env:
DRIVER: mysql_doctrine
MYSQL_HOST: 127.0.0.1
MYSQL_USER: root
MYSQL_PASSWORD: password

- name: Merge worker coverage
run: php tools/merge-coverage.php coverage.php clover.xml && rm coverage.php

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
Expand Down Expand Up @@ -201,13 +208,16 @@ jobs:
uses: ramsey/composer-install@v3

- name: Run PHPUnit with coverage
run: vendor/bin/phpunit --coverage-clover clover.xml
run: vendor/bin/phpunit --coverage-php coverage.php
env:
DRIVER: mariadb_pdo
MARIADB_HOST: 127.0.0.1
MARIADB_USER: root
MARIADB_PASSWORD: password

- name: Merge worker coverage
run: php tools/merge-coverage.php coverage.php clover.xml && rm coverage.php

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
Expand Down Expand Up @@ -248,13 +258,16 @@ jobs:
uses: ramsey/composer-install@v3

- name: Run PHPUnit with coverage
run: vendor/bin/phpunit --coverage-clover clover.xml
run: vendor/bin/phpunit --coverage-php coverage.php
env:
DRIVER: mariadb_doctrine
MARIADB_HOST: 127.0.0.1
MARIADB_USER: root
MARIADB_PASSWORD: password

- name: Merge worker coverage
run: php tools/merge-coverage.php coverage.php clover.xml && rm coverage.php

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
Expand Down Expand Up @@ -293,13 +306,16 @@ jobs:
uses: ramsey/composer-install@v3

- name: Run PHPUnit with coverage
run: vendor/bin/phpunit --coverage-clover clover.xml
run: vendor/bin/phpunit --coverage-php coverage.php
env:
DRIVER: postgres_pdo
POSTGRES_HOST: 127.0.0.1
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres

- name: Merge worker coverage
run: php tools/merge-coverage.php coverage.php clover.xml && rm coverage.php

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
Expand Down Expand Up @@ -338,13 +354,16 @@ jobs:
uses: ramsey/composer-install@v3

- name: Run PHPUnit with coverage
run: vendor/bin/phpunit --coverage-clover clover.xml
run: vendor/bin/phpunit --coverage-php coverage.php
env:
DRIVER: postgres_doctrine
POSTGRES_HOST: 127.0.0.1
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres

- name: Merge worker coverage
run: php tools/merge-coverage.php coverage.php clover.xml && rm coverage.php

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
/tools/*
!/tools/ecs/composer.json
!/tools/ecs/ecs.php
!/tools/merge-coverage.php
16 changes: 16 additions & 0 deletions tests/Util/Command/Shutdown.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Brick\Lock\Tests\Util\Command;

use Brick\Lock\Tests\Util\CommandInterface;
use Brick\Lock\Tests\Util\LockContext;

final class Shutdown implements CommandInterface
{
public function execute(LockContext $context): void
{
exit(0);
}
}
30 changes: 29 additions & 1 deletion tests/Util/RemoteWorker.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
use PHPUnit\Framework\Assert;
use Symfony\Component\Process\InputStream;
use Symfony\Component\Process\Process;
use Throwable;

use function dirname;
use function explode;
use function extension_loaded;
use function implode;
use function json_encode;
use function microtime;
Expand All @@ -36,7 +39,18 @@ final class RemoteWorker

public function __construct()
{
$this->process = new Process(['php', 'worker.php'], __DIR__);
$command = ['php'];

if (extension_loaded('pcov')) {
// pcov.directory defaults to the process CWD (tests/Util/), which excludes src/.
// Set it explicitly so pcov tracks the library source files.
$command[] = '-d';
$command[] = 'pcov.directory=' . dirname(__DIR__, 2) . '/src';
}

$command[] = 'worker.php';

$this->process = new Process($command, __DIR__);
$this->input = new InputStream();

$this->process->setInput($this->input);
Expand Down Expand Up @@ -235,6 +249,20 @@ private function parseDuration(string $duration): float

public function __destruct()
{
if (! $this->isKilled && $this->process->isRunning()) {
try {
$this->sendCommand(new Command\Shutdown());

// Give it enough time to collect coverage.
$deadline = microtime(true) + 1.0;
while ($this->process->isRunning() && microtime(true) < $deadline) {
usleep(100_000);
}
} catch (Throwable) {
// Ignore errors.
}
}

$this->process->stop(0);
}
}
17 changes: 17 additions & 0 deletions tests/Util/worker.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,26 @@
use Brick\Lock\Tests\Util\LockDriverFactoryException;

use function Opis\Closure\unserialize;
use function pcov\collect;
use function pcov\start;
use function pcov\stop;

use const pcov\all;

require __DIR__ . '/../../vendor/autoload.php';

if (extension_loaded('pcov')) {
start();
register_shutdown_function(function (): void {
stop();
$coverage = collect(all);
file_put_contents(
sys_get_temp_dir() . '/brick-lock-worker-coverage-' . getmypid() . '.bin',
serialize($coverage),
);
});
}

try {
$lockDriverWithInfo = LockDriverFactory::getDriver();
} catch (LockDriverFactoryException $e) {
Expand Down
47 changes: 47 additions & 0 deletions tools/merge-coverage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/**
* Merges worker subprocess coverage data into the main PHPUnit coverage report.
*
* Usage: php tools/merge-coverage.php <coverage.php> <clover.xml>
*
* Worker processes (tests/Util/worker.php) save their pcov coverage to temp files
* named brick-lock-worker-coverage-<pid>.bin in sys_get_temp_dir(). This script
* loads the serialized CodeCoverage object produced by PHPUnit (--coverage-php),
* appends each worker's raw coverage data, then writes the merged clover.xml.
*/

declare(strict_types=1);

require __DIR__ . '/../vendor/autoload.php';

use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData;
use SebastianBergmann\CodeCoverage\Report\Clover;

$coveragePhpFile = $argv[1] ?? __DIR__ . '/../coverage.php';
$outputFile = $argv[2] ?? __DIR__ . '/../clover.xml';

/** @var CodeCoverage $coverage */
$coverage = require $coveragePhpFile;

$workerFiles = glob(sys_get_temp_dir() . '/brick-lock-worker-coverage-*.bin');
assert($workerFiles !== false);

foreach ($workerFiles as $file) {
$data = file_get_contents($file);
assert($data !== false);

$workerData = unserialize($data);

if (! is_array($workerData) || $workerData === []) {
continue;
}

$rawData = RawCodeCoverageData::fromXdebugWithoutPathCoverage($workerData);
$coverage->append($rawData, basename($file, '.bin'));

unlink($file);
}

(new Clover())->process($coverage, $outputFile);