Skip to content

Commit 65344ad

Browse files
committed
wire annotations
1 parent 4bf5467 commit 65344ad

7 files changed

+151
-5
lines changed

src/Framework/Attributes/RunClassInSeparateProcess.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
{
2222
private ?bool $forkIfPossible;
2323

24-
public function __construct(bool $forkIfPossible = null)
24+
public function __construct(?bool $forkIfPossible = null)
2525
{
2626
$this->forkIfPossible = $forkIfPossible;
2727
}

src/Framework/TestBuilder.php

+61-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
use PHPUnit\Metadata\ExcludeStaticPropertyFromBackup;
2020
use PHPUnit\Metadata\Parser\Registry as MetadataRegistry;
2121
use PHPUnit\Metadata\PreserveGlobalState;
22+
use PHPUnit\Metadata\RunClassInSeparateProcess;
23+
use PHPUnit\Metadata\RunInSeparateProcess;
24+
use PHPUnit\Metadata\RunTestsInSeparateProcesses;
2225
use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry;
2326
use ReflectionClass;
2427

@@ -50,6 +53,7 @@ public function build(ReflectionClass $theClass, string $methodName, array $grou
5053
$this->shouldTestMethodBeRunInSeparateProcess($className, $methodName),
5154
$this->shouldGlobalStateBePreserved($className, $methodName),
5255
$this->shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess($className),
56+
$this->shouldForkIfPossible($className, $methodName),
5357
$this->backupSettings($className, $methodName),
5458
$groups,
5559
);
@@ -64,6 +68,7 @@ public function build(ReflectionClass $theClass, string $methodName, array $grou
6468
$this->shouldTestMethodBeRunInSeparateProcess($className, $methodName),
6569
$this->shouldGlobalStateBePreserved($className, $methodName),
6670
$this->shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess($className),
71+
$this->shouldForkIfPossible($className, $methodName),
6772
$this->backupSettings($className, $methodName),
6873
);
6974

@@ -76,7 +81,7 @@ public function build(ReflectionClass $theClass, string $methodName, array $grou
7681
* @psalm-param array{backupGlobals: ?bool, backupGlobalsExcludeList: list<string>, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array<string,list<string>>} $backupSettings
7782
* @psalm-param list<non-empty-string> $groups
7883
*/
79-
private function buildDataProviderTestSuite(string $methodName, string $className, array $data, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings, array $groups): DataProviderTestSuite
84+
private function buildDataProviderTestSuite(string $methodName, string $className, array $data, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, bool $forkIfPossible, array $backupSettings, array $groups): DataProviderTestSuite
8085
{
8186
$dataProviderTestSuite = DataProviderTestSuite::empty(
8287
$className . '::' . $methodName,
@@ -99,6 +104,7 @@ private function buildDataProviderTestSuite(string $methodName, string $classNam
99104
$runTestInSeparateProcess,
100105
$preserveGlobalState,
101106
$runClassInSeparateProcess,
107+
$forkIfPossible,
102108
$backupSettings,
103109
);
104110

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

130+
if ($forkIfPossible) {
131+
$test->setForkIfPossible(true);
132+
}
133+
124134
if ($preserveGlobalState !== null) {
125135
$test->setPreserveGlobalState($preserveGlobalState);
126136
}
@@ -273,4 +283,53 @@ private function shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess(str
273283
{
274284
return MetadataRegistry::parser()->forClass($className)->isRunClassInSeparateProcess()->isNotEmpty();
275285
}
286+
287+
/**
288+
* @psalm-param class-string $className
289+
* @psalm-param non-empty-string $methodName
290+
*/
291+
private function shouldForkIfPossible(string $className, string $methodName): bool
292+
{
293+
$metadataForMethod = MetadataRegistry::parser()->forMethod($className, $methodName);
294+
295+
if ($metadataForMethod->isRunInSeparateProcess()->isNotEmpty()) {
296+
$metadata = $metadataForMethod->isRunInSeparateProcess()->asArray()[0];
297+
298+
assert($metadata instanceof RunInSeparateProcess);
299+
300+
$forkIfPossible = $metadata->forkIfPossible();
301+
302+
if ($forkIfPossible !== null) {
303+
return $forkIfPossible;
304+
}
305+
}
306+
307+
$metadataForClass = MetadataRegistry::parser()->forClass($className);
308+
309+
if ($metadataForClass->isRunTestsInSeparateProcesses()->isNotEmpty()) {
310+
$metadata = $metadataForClass->isRunTestsInSeparateProcesses()->asArray()[0];
311+
312+
assert($metadata instanceof RunTestsInSeparateProcesses);
313+
314+
$forkIfPossible = $metadata->forkIfPossible();
315+
316+
if ($forkIfPossible !== null) {
317+
return $forkIfPossible;
318+
}
319+
}
320+
321+
if ($metadataForClass->isRunClassInSeparateProcess()->isNotEmpty()) {
322+
$metadata = $metadataForClass->isRunClassInSeparateProcess()->asArray()[0];
323+
324+
assert($metadata instanceof RunClassInSeparateProcess);
325+
326+
$forkIfPossible = $metadata->forkIfPossible();
327+
328+
if ($forkIfPossible !== null) {
329+
return $forkIfPossible;
330+
}
331+
}
332+
333+
return false;
334+
}
276335
}

src/Framework/TestCase.php

+10
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, T
142142
*/
143143
private ?array $backupGlobalExceptionHandlers = null;
144144
private ?bool $runClassInSeparateProcess = null;
145+
private ?bool $forkIfPossible = null;
145146
private ?bool $runTestInSeparateProcess = null;
146147
private bool $preserveGlobalState = false;
147148
private bool $inIsolation = false;
@@ -335,6 +336,7 @@ final public function run(): void
335336
$this,
336337
$this->runClassInSeparateProcess && !$this->runTestInSeparateProcess,
337338
$this->preserveGlobalState,
339+
$this->forkIfPossible === true,
338340
);
339341
}
340342
}
@@ -718,6 +720,14 @@ final public function setRunClassInSeparateProcess(bool $runClassInSeparateProce
718720
$this->runClassInSeparateProcess = $runClassInSeparateProcess;
719721
}
720722

723+
/**
724+
* @internal This method is not covered by the backward compatibility promise for PHPUnit
725+
*/
726+
final public function setForkIfPossible(bool $forkIfPossible): void
727+
{
728+
$this->forkIfPossible = $forkIfPossible;
729+
}
730+
721731
/**
722732
* @internal This method is not covered by the backward compatibility promise for PHPUnit
723733
*/

src/Framework/TestRunner.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,9 @@ public function run(TestCase $test): void
249249
* @throws ProcessIsolationException
250250
* @throws StaticAnalysisCacheNotConfiguredException
251251
*/
252-
public function runInSeparateProcess(TestCase $test, bool $runEntireClass, bool $preserveGlobalState): void
252+
public function runInSeparateProcess(TestCase $test, bool $runEntireClass, bool $preserveGlobalState, bool $forkIfPossible): void
253253
{
254-
if (PcntlFork::isPcntlForkAvailable()) {
254+
if ($forkIfPossible && PcntlFork::isPcntlForkAvailable()) {
255255
// forking the parent process is a more lightweight way to run a test in isolation.
256256
// it requires the pcntl extension though.
257257
$fork = new PcntlFork;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\TestFixture\Metadata\Attribute;
11+
12+
use PHPUnit\Framework\Attributes\RunClassInSeparateProcess;
13+
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
14+
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
15+
use PHPUnit\Framework\TestCase;
16+
17+
#[RunClassInSeparateProcess(true)]
18+
#[RunTestsInSeparateProcesses]
19+
final class ProcessIsolationForkedTest extends TestCase
20+
{
21+
#[RunInSeparateProcess]
22+
public function testOne(): void
23+
{
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\TestFixture\TestBuilder;
11+
12+
use PHPUnit\Framework\Attributes\BackupGlobals;
13+
use PHPUnit\Framework\Attributes\BackupStaticProperties;
14+
use PHPUnit\Framework\Attributes\RunClassInSeparateProcess;
15+
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
16+
use PHPUnit\Framework\TestCase;
17+
18+
#[BackupGlobals(true)]
19+
#[BackupStaticProperties(true)]
20+
#[RunClassInSeparateProcess]
21+
#[RunTestsInSeparateProcesses(true)]
22+
final class TestWithClassLevelIsolationAttributesForked extends TestCase
23+
{
24+
public function testOne(): void
25+
{
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\TestFixture\TestBuilder;
11+
12+
use PHPUnit\Framework\Attributes\BackupGlobals;
13+
use PHPUnit\Framework\Attributes\BackupStaticProperties;
14+
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
15+
use PHPUnit\Framework\TestCase;
16+
17+
final class TestWithMethodLevelIsolationAttributes extends TestCase
18+
{
19+
#[BackupGlobals(true)]
20+
#[BackupStaticProperties(true)]
21+
#[RunInSeparateProcess(true)]
22+
public function testOne(): void
23+
{
24+
}
25+
}

0 commit comments

Comments
 (0)