diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV7.php b/src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV7.php deleted file mode 100644 index 33b4b52c65..0000000000 --- a/src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV7.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\PhpUnit\Legacy; - -use PHPUnit\Framework\MockObject\MockObject; - -/** - * @internal - */ -trait ForwardCompatTestTraitForV7 -{ - use ForwardCompatTestTraitForV5; - - /** - * @param string|string[] $originalClassName - */ - protected function createMock($originalClassName): MockObject - { - return $this->getMockBuilder($originalClassName) - ->disableOriginalConstructor() - ->disableOriginalClone() - ->disableArgumentCloning() - ->disallowMockingUnknownTypes() - ->getMock(); - } - - /** - * @param string|string[] $originalClassName - * @param string[] $methods - */ - protected function createPartialMock($originalClassName, array $methods): MockObject - { - return $this->getMockBuilder($originalClassName) - ->disableOriginalConstructor() - ->disableOriginalClone() - ->disableArgumentCloning() - ->disallowMockingUnknownTypes() - ->setMethods(empty($methods) ? null : $methods) - ->getMock(); - } -} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV5.php b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillAssertTrait.php similarity index 57% rename from src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV5.php rename to src/Symfony/Bridge/PhpUnit/Legacy/PolyfillAssertTrait.php index 8e16c47887..85cbe17b71 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV5.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillAssertTrait.php @@ -15,106 +15,12 @@ use PHPUnit\Framework\Constraint\IsEqual; use PHPUnit\Framework\Constraint\LogicalNot; use PHPUnit\Framework\Constraint\StringContains; use PHPUnit\Framework\Constraint\TraversableContains; -use PHPUnit\Framework\MockObject\MockObject; -use PHPUnit\Framework\TestCase; /** * @internal */ -trait ForwardCompatTestTraitForV5 +trait PolyfillAssertTrait { - /** - * @return void - */ - public static function setUpBeforeClass() - { - self::doSetUpBeforeClass(); - } - - /** - * @return void - */ - public static function tearDownAfterClass() - { - self::doTearDownAfterClass(); - } - - /** - * @return void - */ - protected function setUp() - { - self::doSetUp(); - } - - /** - * @return void - */ - protected function tearDown() - { - self::doTearDown(); - } - - private static function doSetUpBeforeClass() - { - parent::setUpBeforeClass(); - } - - private static function doTearDownAfterClass() - { - parent::tearDownAfterClass(); - } - - private function doSetUp() - { - parent::setUp(); - } - - private function doTearDown() - { - parent::tearDown(); - } - - /** - * @param string|string[] $originalClassName - * - * @return MockObject - */ - protected function createMock($originalClassName) - { - $mock = $this->getMockBuilder($originalClassName) - ->disableOriginalConstructor() - ->disableOriginalClone() - ->disableArgumentCloning(); - - if (method_exists($mock, 'disallowMockingUnknownTypes')) { - $mock = $mock->disallowMockingUnknownTypes(); - } - - return $mock->getMock(); - } - - /** - * @param string|string[] $originalClassName - * @param string[] $methods - * - * @return MockObject - */ - protected function createPartialMock($originalClassName, array $methods) - { - $mock = $this->getMockBuilder($originalClassName) - ->disableOriginalConstructor() - ->disableOriginalClone() - ->disableArgumentCloning() - ->setMethods(empty($methods) ? null : $methods); - - if (method_exists($mock, 'disallowMockingUnknownTypes')) { - $mock = $mock->disallowMockingUnknownTypes(); - } - - return $mock->getMock(); - } - /** * @param float $delta * @param string $message @@ -320,12 +226,6 @@ trait ForwardCompatTestTraitForV5 */ public static function assertFinite($actual, $message = '') { - if (method_exists(TestCase::class, 'assertFinite')) { - parent::assertFinite($actual, $message); - - return; - } - static::assertInternalType('float', $actual, $message); static::assertTrue(is_finite($actual), $message ? $message : "Failed asserting that $actual is finite."); } @@ -337,12 +237,6 @@ trait ForwardCompatTestTraitForV5 */ public static function assertInfinite($actual, $message = '') { - if (method_exists(TestCase::class, 'assertInfinite')) { - parent::assertInfinite($actual, $message); - - return; - } - static::assertInternalType('float', $actual, $message); static::assertTrue(is_infinite($actual), $message ? $message : "Failed asserting that $actual is infinite."); } @@ -354,85 +248,7 @@ trait ForwardCompatTestTraitForV5 */ public static function assertNan($actual, $message = '') { - if (method_exists(TestCase::class, 'assertNan')) { - parent::assertNan($actual, $message); - - return; - } - static::assertInternalType('float', $actual, $message); static::assertTrue(is_nan($actual), $message ? $message : "Failed asserting that $actual is nan."); } - - /** - * @param string $exception - * - * @return void - */ - public function expectException($exception) - { - if (method_exists(TestCase::class, 'expectException')) { - parent::expectException($exception); - - return; - } - - $property = new \ReflectionProperty(class_exists('PHPUnit_Framework_TestCase') ? 'PHPUnit_Framework_TestCase' : TestCase::class, 'expectedException'); - $property->setAccessible(true); - $property->setValue($this, $exception); - } - - /** - * @param int|string $code - * - * @return void - */ - public function expectExceptionCode($code) - { - if (method_exists(TestCase::class, 'expectExceptionCode')) { - parent::expectExceptionCode($code); - - return; - } - - $property = new \ReflectionProperty(class_exists('PHPUnit_Framework_TestCase') ? 'PHPUnit_Framework_TestCase' : TestCase::class, 'expectedExceptionCode'); - $property->setAccessible(true); - $property->setValue($this, $code); - } - - /** - * @param string $message - * - * @return void - */ - public function expectExceptionMessage($message) - { - if (method_exists(TestCase::class, 'expectExceptionMessage')) { - parent::expectExceptionMessage($message); - - return; - } - - $property = new \ReflectionProperty(class_exists('PHPUnit_Framework_TestCase') ? 'PHPUnit_Framework_TestCase' : TestCase::class, 'expectedExceptionMessage'); - $property->setAccessible(true); - $property->setValue($this, $message); - } - - /** - * @param string $messageRegExp - * - * @return void - */ - public function expectExceptionMessageRegExp($messageRegExp) - { - if (method_exists(TestCase::class, 'expectExceptionMessageRegExp')) { - parent::expectExceptionMessageRegExp($messageRegExp); - - return; - } - - $property = new \ReflectionProperty(class_exists('PHPUnit_Framework_TestCase') ? 'PHPUnit_Framework_TestCase' : TestCase::class, 'expectedExceptionMessageRegExp'); - $property->setAccessible(true); - $property->setValue($this, $messageRegExp); - } } diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php new file mode 100644 index 0000000000..071a719488 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; + +/** + * @internal + */ +trait PolyfillTestCaseTrait +{ + /** + * @param string|string[] $originalClassName + * + * @return MockObject + */ + protected function createMock($originalClassName) + { + $mock = $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning(); + + if (method_exists($mock, 'disallowMockingUnknownTypes')) { + $mock = $mock->disallowMockingUnknownTypes(); + } + + return $mock->getMock(); + } + + /** + * @param string|string[] $originalClassName + * @param string[] $methods + * + * @return MockObject + */ + protected function createPartialMock($originalClassName, array $methods) + { + $mock = $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->setMethods(empty($methods) ? null : $methods); + + if (method_exists($mock, 'disallowMockingUnknownTypes')) { + $mock = $mock->disallowMockingUnknownTypes(); + } + + return $mock->getMock(); + } + + /** + * @param string $exception + * + * @return void + */ + public function expectException($exception) + { + $property = new \ReflectionProperty(class_exists('PHPUnit_Framework_TestCase') ? 'PHPUnit_Framework_TestCase' : TestCase::class, 'expectedException'); + $property->setAccessible(true); + $property->setValue($this, $exception); + } + + /** + * @param int|string $code + * + * @return void + */ + public function expectExceptionCode($code) + { + $property = new \ReflectionProperty(class_exists('PHPUnit_Framework_TestCase') ? 'PHPUnit_Framework_TestCase' : TestCase::class, 'expectedExceptionCode'); + $property->setAccessible(true); + $property->setValue($this, $code); + } + + /** + * @param string $message + * + * @return void + */ + public function expectExceptionMessage($message) + { + $property = new \ReflectionProperty(class_exists('PHPUnit_Framework_TestCase') ? 'PHPUnit_Framework_TestCase' : TestCase::class, 'expectedExceptionMessage'); + $property->setAccessible(true); + $property->setValue($this, $message); + } + + /** + * @param string $messageRegExp + * + * @return void + */ + public function expectExceptionMessageRegExp($messageRegExp) + { + $property = new \ReflectionProperty(class_exists('PHPUnit_Framework_TestCase') ? 'PHPUnit_Framework_TestCase' : TestCase::class, 'expectedExceptionMessageRegExp'); + $property->setAccessible(true); + $property->setValue($this, $messageRegExp); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SetUpTearDownTraitForV5.php b/src/Symfony/Bridge/PhpUnit/Legacy/SetUpTearDownTraitForV5.php new file mode 100644 index 0000000000..ca29c2ae49 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SetUpTearDownTraitForV5.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * @internal + */ +trait SetUpTearDownTraitForV5 +{ + /** + * @return void + */ + public static function setUpBeforeClass() + { + self::doSetUpBeforeClass(); + } + + /** + * @return void + */ + public static function tearDownAfterClass() + { + self::doTearDownAfterClass(); + } + + /** + * @return void + */ + protected function setUp() + { + self::doSetUp(); + } + + /** + * @return void + */ + protected function tearDown() + { + self::doTearDown(); + } + + private static function doSetUpBeforeClass() + { + parent::setUpBeforeClass(); + } + + private static function doTearDownAfterClass() + { + parent::tearDownAfterClass(); + } + + private function doSetUp() + { + parent::setUp(); + } + + private function doTearDown() + { + parent::tearDown(); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV8.php b/src/Symfony/Bridge/PhpUnit/Legacy/SetUpTearDownTraitForV8.php similarity index 96% rename from src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV8.php rename to src/Symfony/Bridge/PhpUnit/Legacy/SetUpTearDownTraitForV8.php index 4963ed9e0c..cc81df2818 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/ForwardCompatTestTraitForV8.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SetUpTearDownTraitForV8.php @@ -14,7 +14,7 @@ namespace Symfony\Bridge\PhpUnit\Legacy; /** * @internal */ -trait ForwardCompatTestTraitForV8 +trait SetUpTearDownTraitForV8 { public static function setUpBeforeClass(): void { diff --git a/src/Symfony/Bridge/PhpUnit/ForwardCompatTestTrait.php b/src/Symfony/Bridge/PhpUnit/SetUpTearDownTrait.php similarity index 51% rename from src/Symfony/Bridge/PhpUnit/ForwardCompatTestTrait.php rename to src/Symfony/Bridge/PhpUnit/SetUpTearDownTrait.php index 29597bbe10..e27c3a4fb0 100644 --- a/src/Symfony/Bridge/PhpUnit/ForwardCompatTestTrait.php +++ b/src/Symfony/Bridge/PhpUnit/SetUpTearDownTrait.php @@ -14,22 +14,15 @@ namespace Symfony\Bridge\PhpUnit; use PHPUnit\Framework\TestCase; // A trait to provide forward compatibility with newest PHPUnit versions - $r = new \ReflectionClass(TestCase::class); - -if (\PHP_VERSION_ID < 70000 || !$r->hasMethod('createMock') || !$r->getMethod('createMock')->hasReturnType()) { - trait ForwardCompatTestTrait +if (\PHP_VERSION_ID < 70000 || !$r->getMethod('setUp')->hasReturnType()) { + trait SetUpTearDownTrait { - use Legacy\ForwardCompatTestTraitForV5; - } -} elseif ($r->getMethod('tearDown')->hasReturnType()) { - trait ForwardCompatTestTrait - { - use Legacy\ForwardCompatTestTraitForV8; + use Legacy\SetUpTearDownTraitForV5; } } else { - trait ForwardCompatTestTrait + trait SetUpTearDownTrait { - use Legacy\ForwardCompatTestTraitForV7; + use Legacy\SetUpTearDownTraitForV8; } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/ClockMockTest.php b/src/Symfony/Bridge/PhpUnit/Tests/ClockMockTest.php index d438ee1aa8..5b92ccd850 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/ClockMockTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/ClockMockTest.php @@ -13,7 +13,6 @@ namespace Symfony\Bridge\PhpUnit\Tests; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ClockMock; -use Symfony\Bridge\PhpUnit\ForwardCompatTestTrait; /** * @author Dominic Tubach @@ -22,14 +21,12 @@ use Symfony\Bridge\PhpUnit\ForwardCompatTestTrait; */ class ClockMockTest extends TestCase { - use ForwardCompatTestTrait; - - private static function doSetUpBeforeClass() + public static function setUpBeforeClass() { ClockMock::register(__CLASS__); } - private function doSetUp() + protected function setUp() { ClockMock::withClockMock(1234567890.125); } diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index 697687b213..50c805228b 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -63,6 +63,8 @@ if (PHP_VERSION_ID >= 70200) { $PHPUNIT_VERSION = '4.8'; } +$PHPUNIT_REMOVE_RETURN_TYPEHINT = filter_var($getEnvVar('SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT', '0'), FILTER_VALIDATE_BOOLEAN); + $COMPOSER_JSON = getenv('COMPOSER') ?: 'composer.json'; $root = __DIR__; @@ -100,19 +102,20 @@ $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rt $SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy'.($PHPUNIT_VERSION < 6.0 ? ' symfony/yaml': '')); - -if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__FILE__)."\n".$SYMFONY_PHPUNIT_REMOVE !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION.md5")) { +$configurationHash = md5(implode(PHP_EOL, array(md5_file(__FILE__), $SYMFONY_PHPUNIT_REMOVE, (int) $PHPUNIT_REMOVE_RETURN_TYPEHINT))); +$PHPUNIT_VERSION_DIR=sprintf('phpunit-%s-%d', $PHPUNIT_VERSION, $PHPUNIT_REMOVE_RETURN_TYPEHINT); +if (!file_exists("$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/phpunit") || $configurationHash !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION_DIR.md5")) { // Build a standalone phpunit without symfony/yaml nor prophecy by default @mkdir($PHPUNIT_DIR, 0777, true); chdir($PHPUNIT_DIR); - if (file_exists("phpunit-$PHPUNIT_VERSION")) { - passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s > NUL': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION.old")); - rename("phpunit-$PHPUNIT_VERSION", "phpunit-$PHPUNIT_VERSION.old"); - passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION.old")); + if (file_exists("$PHPUNIT_VERSION_DIR")) { + passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s > NUL': 'rm -rf %s', "$PHPUNIT_VERSION_DIR.old")); + rename("$PHPUNIT_VERSION_DIR", "$PHPUNIT_VERSION_DIR.old"); + passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s': 'rm -rf %s', "$PHPUNIT_VERSION_DIR.old")); } - passthru("$COMPOSER create-project --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit phpunit-$PHPUNIT_VERSION \"$PHPUNIT_VERSION.*\""); - chdir("phpunit-$PHPUNIT_VERSION"); + passthru("$COMPOSER create-project --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit $PHPUNIT_VERSION_DIR \"$PHPUNIT_VERSION.*\""); + chdir("$PHPUNIT_VERSION_DIR"); if ($SYMFONY_PHPUNIT_REMOVE) { passthru("$COMPOSER remove --no-update ".$SYMFONY_PHPUNIT_REMOVE); } @@ -139,6 +142,26 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ if ($exit) { exit($exit); } + + // Mutate TestCase code + $alteredCode = file_get_contents($alteredFile = './src/Framework/TestCase.php'); + if ($PHPUNIT_REMOVE_RETURN_TYPEHINT) { + $alteredCode = preg_replace('/^ ((?:protected|public)(?: static)? function \w+\(\)): void/m', ' $1', $alteredCode); + } + $alteredCode = preg_replace('/abstract class (?:TestCase|PHPUnit_Framework_TestCase)[^\{]+\{/', '$0 '.PHP_EOL." use \Symfony\Bridge\PhpUnit\Legacy\PolyfillTestCaseTrait;", $alteredCode, 1); + file_put_contents($alteredFile, $alteredCode); + + // Mutate Assert code + $alteredCode = file_get_contents($alteredFile = './src/Framework/Assert.php'); + $alteredCode = preg_replace('/abstract class (?:Assert|PHPUnit_Framework_Assert)[^\{]+\{/', '$0 '.PHP_EOL." use \Symfony\Bridge\PhpUnit\Legacy\PolyfillAssertTrait;", $alteredCode, 1); + file_put_contents($alteredFile, $alteredCode); + + // remove internal annotation from polyfill + foreach (array('PolyfillTestCaseTrait', 'PolyfillAssertTrait') as $polyfill) { + $traitFile = "./vendor/symfony/phpunit-bridge/Legacy/$polyfill.php"; + file_put_contents($traitFile, str_replace(' * @internal', '', file_get_contents($traitFile))); + } + file_put_contents('phpunit', <<<'EOPHP'