Skip to content

Commit

Permalink
wire annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm committed Mar 29, 2024
1 parent f3fb3f2 commit a47ff12
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/Framework/Attributes/RunClassInSeparateProcess.php
Expand Up @@ -21,7 +21,7 @@
{
private ?bool $forkIfPossible;

public function __construct(bool $forkIfPossible = null)
public function __construct(?bool $forkIfPossible = null)
{
$this->forkIfPossible = $forkIfPossible;
}
Expand Down
63 changes: 61 additions & 2 deletions src/Framework/TestBuilder.php
Expand Up @@ -19,6 +19,9 @@
use PHPUnit\Metadata\ExcludeStaticPropertyFromBackup;
use PHPUnit\Metadata\Parser\Registry as MetadataRegistry;
use PHPUnit\Metadata\PreserveGlobalState;
use PHPUnit\Metadata\RunClassInSeparateProcess;
use PHPUnit\Metadata\RunInSeparateProcess;
use PHPUnit\Metadata\RunTestsInSeparateProcesses;
use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry;
use ReflectionClass;

Expand Down Expand Up @@ -50,6 +53,7 @@ public function build(ReflectionClass $theClass, string $methodName, array $grou
$this->shouldTestMethodBeRunInSeparateProcess($className, $methodName),
$this->shouldGlobalStateBePreserved($className, $methodName),
$this->shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess($className),
$this->shouldForkIfPossible($className, $methodName),
$this->backupSettings($className, $methodName),
$groups,
);
Expand All @@ -64,6 +68,7 @@ public function build(ReflectionClass $theClass, string $methodName, array $grou
$this->shouldTestMethodBeRunInSeparateProcess($className, $methodName),
$this->shouldGlobalStateBePreserved($className, $methodName),
$this->shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess($className),
$this->shouldForkIfPossible($className, $methodName),
$this->backupSettings($className, $methodName),
);

Expand All @@ -76,7 +81,7 @@ public function build(ReflectionClass $theClass, string $methodName, array $grou
* @psalm-param array{backupGlobals: ?bool, backupGlobalsExcludeList: list<string>, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array<string,list<string>>} $backupSettings
* @psalm-param list<non-empty-string> $groups
*/
private function buildDataProviderTestSuite(string $methodName, string $className, array $data, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings, array $groups): DataProviderTestSuite
private function buildDataProviderTestSuite(string $methodName, string $className, array $data, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, bool $forkIfPossible, array $backupSettings, array $groups): DataProviderTestSuite
{
$dataProviderTestSuite = DataProviderTestSuite::empty(
$className . '::' . $methodName,
Expand All @@ -99,6 +104,7 @@ private function buildDataProviderTestSuite(string $methodName, string $classNam
$runTestInSeparateProcess,
$preserveGlobalState,
$runClassInSeparateProcess,
$forkIfPossible,
$backupSettings,
);

Expand All @@ -111,7 +117,7 @@ private function buildDataProviderTestSuite(string $methodName, string $classNam
/**
* @psalm-param array{backupGlobals: ?bool, backupGlobalsExcludeList: list<string>, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array<string,list<string>>} $backupSettings
*/
private function configureTestCase(TestCase $test, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings): void
private function configureTestCase(TestCase $test, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, bool $forkIfPossible, array $backupSettings): void
{
if ($runTestInSeparateProcess) {
$test->setRunTestInSeparateProcess(true);
Expand All @@ -121,6 +127,10 @@ private function configureTestCase(TestCase $test, bool $runTestInSeparateProces
$test->setRunClassInSeparateProcess(true);
}

if ($forkIfPossible) {
$test->setForkIfPossible(true);
}

if ($preserveGlobalState !== null) {
$test->setPreserveGlobalState($preserveGlobalState);
}
Expand Down Expand Up @@ -273,4 +283,53 @@ private function shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess(str
{
return MetadataRegistry::parser()->forClass($className)->isRunClassInSeparateProcess()->isNotEmpty();
}

/**
* @psalm-param class-string $className
* @psalm-param non-empty-string $methodName
*/
private function shouldForkIfPossible(string $className, string $methodName): bool
{
$metadataForMethod = MetadataRegistry::parser()->forMethod($className, $methodName);

if ($metadataForMethod->isRunInSeparateProcess()->isNotEmpty()) {
$metadata = $metadataForMethod->isRunInSeparateProcess()->asArray()[0];

assert($metadata instanceof RunInSeparateProcess);

$forkIfPossible = $metadata->forkIfPossible();

if ($forkIfPossible !== null) {
return $forkIfPossible;
}
}

$metadataForClass = MetadataRegistry::parser()->forClass($className);

if ($metadataForClass->isRunTestsInSeparateProcesses()->isNotEmpty()) {
$metadata = $metadataForClass->isRunTestsInSeparateProcesses()->asArray()[0];

assert($metadata instanceof RunTestsInSeparateProcesses);

$forkIfPossible = $metadata->forkIfPossible();

if ($forkIfPossible !== null) {
return $forkIfPossible;

Check warning on line 317 in src/Framework/TestBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/Framework/TestBuilder.php#L317

Added line #L317 was not covered by tests
}
}

if ($metadataForClass->isRunClassInSeparateProcess()->isNotEmpty()) {
$metadata = $metadataForClass->isRunClassInSeparateProcess()->asArray()[0];

assert($metadata instanceof RunClassInSeparateProcess);

$forkIfPossible = $metadata->forkIfPossible();

if ($forkIfPossible !== null) {
return $forkIfPossible;
}
}

return false;
}
}
10 changes: 10 additions & 0 deletions src/Framework/TestCase.php
Expand Up @@ -142,6 +142,7 @@ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, T
*/
private ?array $backupGlobalExceptionHandlers = null;
private ?bool $runClassInSeparateProcess = null;
private ?bool $forkIfPossible = null;
private ?bool $runTestInSeparateProcess = null;
private bool $preserveGlobalState = false;
private bool $inIsolation = false;
Expand Down Expand Up @@ -335,6 +336,7 @@ final public function run(): void
$this,
$this->runClassInSeparateProcess && !$this->runTestInSeparateProcess,
$this->preserveGlobalState,
$this->forkIfPossible === true,
);
}
}
Expand Down Expand Up @@ -718,6 +720,14 @@ final public function setRunClassInSeparateProcess(bool $runClassInSeparateProce
$this->runClassInSeparateProcess = $runClassInSeparateProcess;
}

/**
* @internal This method is not covered by the backward compatibility promise for PHPUnit
*/
final public function setForkIfPossible(bool $forkIfPossible): void
{
$this->forkIfPossible = $forkIfPossible;
}

/**
* @internal This method is not covered by the backward compatibility promise for PHPUnit
*/
Expand Down
4 changes: 2 additions & 2 deletions src/Framework/TestRunner.php
Expand Up @@ -249,9 +249,9 @@ public function run(TestCase $test): void
* @throws ProcessIsolationException
* @throws StaticAnalysisCacheNotConfiguredException
*/
public function runInSeparateProcess(TestCase $test, bool $runEntireClass, bool $preserveGlobalState): void
public function runInSeparateProcess(TestCase $test, bool $runEntireClass, bool $preserveGlobalState, bool $forkIfPossible): void
{
if (PcntlFork::isPcntlForkAvailable()) {
if ($forkIfPossible && PcntlFork::isPcntlForkAvailable()) {
// forking the parent process is a more lightweight way to run a test in isolation.
// it requires the pcntl extension though.
$fork = new PcntlFork;
Expand Down
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\TestFixture\Metadata\Attribute;

use PHPUnit\Framework\Attributes\RunClassInSeparateProcess;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
use PHPUnit\Framework\TestCase;

#[RunClassInSeparateProcess(true)]
#[RunTestsInSeparateProcesses]
final class ProcessIsolationForkedTest extends TestCase
{
#[RunInSeparateProcess]
public function testOne(): void
{
}
}
27 changes: 27 additions & 0 deletions tests/_files/TestWithClassLevelIsolationAttributesForked.php
@@ -0,0 +1,27 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\TestFixture\TestBuilder;

use PHPUnit\Framework\Attributes\BackupGlobals;
use PHPUnit\Framework\Attributes\BackupStaticProperties;
use PHPUnit\Framework\Attributes\RunClassInSeparateProcess;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
use PHPUnit\Framework\TestCase;

#[BackupGlobals(true)]
#[BackupStaticProperties(true)]
#[RunClassInSeparateProcess]
#[RunTestsInSeparateProcesses(true)]
final class TestWithClassLevelIsolationAttributesForked extends TestCase
{
public function testOne(): void
{
}
}
25 changes: 25 additions & 0 deletions tests/_files/TestWithMethodLevelIsolationAttributesForked.php
@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\TestFixture\TestBuilder;

use PHPUnit\Framework\Attributes\BackupGlobals;
use PHPUnit\Framework\Attributes\BackupStaticProperties;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\TestCase;

final class TestWithMethodLevelIsolationAttributes extends TestCase
{
#[BackupGlobals(true)]
#[BackupStaticProperties(true)]
#[RunInSeparateProcess(true)]
public function testOne(): void
{
}
}

0 comments on commit a47ff12

Please sign in to comment.