Skip to content

Commit 8219df7

Browse files
committed
wire annotations
1 parent f3fb3f2 commit 8219df7

6 files changed

+147
-4
lines changed

src/Framework/TestBuilder.php

+58-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,50 @@ 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+
if ($forkIfPossible !== null) {
302+
return $forkIfPossible;
303+
}
304+
}
305+
306+
$metadataForClass = MetadataRegistry::parser()->forClass($className);
307+
308+
if ($metadataForClass->isRunTestsInSeparateProcesses()->isNotEmpty()) {
309+
$metadata = $metadataForClass->isRunTestsInSeparateProcesses()->asArray()[0];
310+
311+
assert($metadata instanceof RunTestsInSeparateProcesses);
312+
313+
$forkIfPossible = $metadata->forkIfPossible();
314+
if ($forkIfPossible !== null) {
315+
return $forkIfPossible;
316+
}
317+
}
318+
319+
if ($metadataForClass->isRunClassInSeparateProcess()->isNotEmpty()) {
320+
$metadata = $metadataForClass->isRunClassInSeparateProcess()->asArray()[0];
321+
322+
assert($metadata instanceof RunClassInSeparateProcess);
323+
324+
$forkIfPossible = $metadata->forkIfPossible();
325+
if ($forkIfPossible !== null) {
326+
return $forkIfPossible;
327+
}
328+
}
329+
330+
return false;
331+
}
276332
}

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 <sebastian@phpunit.de>
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 <sebastian@phpunit.de>
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 <sebastian@phpunit.de>
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)