diff --git a/src/Testing/PHPStanTestCase.php b/src/Testing/PHPStanTestCase.php index 03b2e4335c7..f70ec82fcff 100644 --- a/src/Testing/PHPStanTestCase.php +++ b/src/Testing/PHPStanTestCase.php @@ -2,6 +2,7 @@ namespace PHPStan\Testing; +use Override; use PHPStan\Analyser\ConstantResolver; use PHPStan\Analyser\DirectInternalScopeFactoryFactory; use PHPStan\Analyser\Error; @@ -40,6 +41,24 @@ abstract class PHPStanTestCase extends TestCase use PHPStanTestCaseTrait; + /** + * Re-register the runtime container as the global static reflection provider before + * every test. Enable this in tests that construct Type objects directly and assert + * PHP-version-dependent reflection results, so a foreign PhpVersion leaked by another + * test can't flake them. See https://github.com/phpstan/phpstan/issues/14860 + */ + protected bool $reinitializeContainerBeforeEachTest = false; + + #[Override] + protected function setUp(): void + { + if (!$this->reinitializeContainerBeforeEachTest) { + return; + } + + self::getContainer(); + } + public static function getParser(): Parser { /** @var Parser $parser */ diff --git a/tests/PHPStan/Analyser/AnalyserTraitsIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserTraitsIntegrationTest.php index 4680f7fccb2..eb5fbc4d67a 100644 --- a/tests/PHPStan/Analyser/AnalyserTraitsIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserTraitsIntegrationTest.php @@ -22,6 +22,7 @@ class AnalyserTraitsIntegrationTest extends PHPStanTestCase #[Override] protected function setUp(): void { + parent::setUp(); $this->fileHelper = self::getContainer()->getByType(FileHelper::class); } diff --git a/tests/PHPStan/Analyser/TypeSpecifierTest.php b/tests/PHPStan/Analyser/TypeSpecifierTest.php index aa66c940016..faeacb2f9fc 100644 --- a/tests/PHPStan/Analyser/TypeSpecifierTest.php +++ b/tests/PHPStan/Analyser/TypeSpecifierTest.php @@ -61,6 +61,7 @@ class TypeSpecifierTest extends PHPStanTestCase #[Override] protected function setUp(): void { + parent::setUp(); $reflectionProvider = self::createReflectionProvider(); $this->printer = new Printer(); $this->typeSpecifier = self::getContainer()->getService('typeSpecifier'); diff --git a/tests/PHPStan/Command/ErrorFormatter/RawErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/RawErrorFormatterTest.php index cf0c0711631..72718f0a28a 100644 --- a/tests/PHPStan/Command/ErrorFormatter/RawErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/RawErrorFormatterTest.php @@ -19,6 +19,7 @@ class RawErrorFormatterTest extends ErrorFormatterTestCase #[Override] protected function setUp(): void { + parent::setUp(); foreach (AgentDetector::ENV_VARS as $var) { $this->originalEnvVars[$var] = getenv($var); putenv($var); diff --git a/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php index 2ec0679fabd..8396630f7c6 100644 --- a/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php @@ -23,6 +23,7 @@ class TableErrorFormatterTest extends ErrorFormatterTestCase #[Override] protected function setUp(): void { + parent::setUp(); putenv('GITHUB_ACTIONS'); $this->terminalEmulator = getenv('TERMINAL_EMULATOR'); diff --git a/tests/PHPStan/PhpDoc/DefaultStubFilesProviderTest.php b/tests/PHPStan/PhpDoc/DefaultStubFilesProviderTest.php index a1e0faf4a2a..eef6033cfdd 100644 --- a/tests/PHPStan/PhpDoc/DefaultStubFilesProviderTest.php +++ b/tests/PHPStan/PhpDoc/DefaultStubFilesProviderTest.php @@ -17,6 +17,7 @@ class DefaultStubFilesProviderTest extends PHPStanTestCase #[Override] protected function setUp(): void { + parent::setUp(); $this->currentWorkingDirectory = $this->getContainer()->getParameter('currentWorkingDirectory'); } diff --git a/tests/PHPStan/Rules/Functions/PrintfHelperTest.php b/tests/PHPStan/Rules/Functions/PrintfHelperTest.php index c8175508082..c2dae58ec4e 100644 --- a/tests/PHPStan/Rules/Functions/PrintfHelperTest.php +++ b/tests/PHPStan/Rules/Functions/PrintfHelperTest.php @@ -15,6 +15,7 @@ class PrintfHelperTest extends PHPStanTestCase #[Override] protected function setUp(): void { + parent::setUp(); $this->printf = new PrintfHelper(new PhpVersion(PHP_VERSION_ID)); } diff --git a/tests/PHPStan/Type/Accessory/HasPropertyTypeTest.php b/tests/PHPStan/Type/Accessory/HasPropertyTypeTest.php index 8219bc5eab3..5771e7d52da 100644 --- a/tests/PHPStan/Type/Accessory/HasPropertyTypeTest.php +++ b/tests/PHPStan/Type/Accessory/HasPropertyTypeTest.php @@ -23,6 +23,11 @@ class HasPropertyTypeTest extends PHPStanTestCase { + // Pin the runtime container so a foreign PhpVersion leaked by another test + // can't flake the version-dependent Closure data set below. + // See https://github.com/phpstan/phpstan/issues/14860 + protected bool $reinitializeContainerBeforeEachTest = true; + public static function dataIsSuperTypeOf(): array { return [ diff --git a/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php b/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php index 2f3733c363b..7564cbe9f33 100644 --- a/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php +++ b/tests/PHPStan/Type/Generic/GenericObjectTypeTest.php @@ -32,6 +32,11 @@ class GenericObjectTypeTest extends PHPStanTestCase { + // Pin the runtime container so a foreign PhpVersion leaked by another test + // can't flake the version-dependent data sets (reflected variance of built-in + // generics). See https://github.com/phpstan/phpstan/issues/14860 + protected bool $reinitializeContainerBeforeEachTest = true; + public static function dataIsSuperTypeOf(): array { return [ diff --git a/tests/PHPStan/Type/ObjectTypeTest.php b/tests/PHPStan/Type/ObjectTypeTest.php index 3a0344983ba..c9a9688c215 100644 --- a/tests/PHPStan/Type/ObjectTypeTest.php +++ b/tests/PHPStan/Type/ObjectTypeTest.php @@ -51,6 +51,11 @@ class ObjectTypeTest extends PHPStanTestCase { + // Pin the runtime container so a foreign PhpVersion leaked by another test + // can't flake the version-dependent Closure data sets (dynamic-property + // handling). See https://github.com/phpstan/phpstan/issues/14860 + protected bool $reinitializeContainerBeforeEachTest = true; + public static function dataIsIterable(): array { return [ diff --git a/tests/PHPStan/Type/Php/GmpOperatorTypeSpecifyingExtensionTest.php b/tests/PHPStan/Type/Php/GmpOperatorTypeSpecifyingExtensionTest.php index 97c50184e0f..9e8aee6d8b2 100644 --- a/tests/PHPStan/Type/Php/GmpOperatorTypeSpecifyingExtensionTest.php +++ b/tests/PHPStan/Type/Php/GmpOperatorTypeSpecifyingExtensionTest.php @@ -24,6 +24,7 @@ class GmpOperatorTypeSpecifyingExtensionTest extends PHPStanTestCase #[Override] protected function setUp(): void { + parent::setUp(); $this->extension = new GmpOperatorTypeSpecifyingExtension(); } diff --git a/tests/PHPStan/Type/TypeCombinatorTest.php b/tests/PHPStan/Type/TypeCombinatorTest.php index 996beeeed75..c5499d47447 100644 --- a/tests/PHPStan/Type/TypeCombinatorTest.php +++ b/tests/PHPStan/Type/TypeCombinatorTest.php @@ -73,6 +73,11 @@ class TypeCombinatorTest extends PHPStanTestCase { + // Pin the runtime container so a foreign PhpVersion leaked by another test + // can't flake the version-dependent data sets (dynamic-property handling of + // final classes). See https://github.com/phpstan/phpstan/issues/14860 + protected bool $reinitializeContainerBeforeEachTest = true; + public static function dataAddNull(): array { return [