diff --git a/core/tests/Drupal/Tests/ExpectDeprecationTest.php b/core/tests/Drupal/Tests/ExpectDeprecationTest.php index 8ebf3b5a210def0c8168a23457e14806463870a6..aefb6a0ad927c37d74b5f1c92ecb49541b388480 100644 --- a/core/tests/Drupal/Tests/ExpectDeprecationTest.php +++ b/core/tests/Drupal/Tests/ExpectDeprecationTest.php @@ -21,4 +21,16 @@ public function testExpectDeprecation() { @trigger_error('Test deprecation', E_USER_DEPRECATED); } + /** + * @covers ::expectDeprecation + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testExpectDeprecationInIsolation() { + $this->expectDeprecation('Test isolated deprecation'); + $this->expectDeprecation('Test isolated deprecation2'); + @trigger_error('Test isolated deprecation', E_USER_DEPRECATED); + @trigger_error('Test isolated deprecation2', E_USER_DEPRECATED); + } + } diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php index 027ead6c24f813f105c9f971b0d856872d4e5cca..26967fae9b6850ad8132d08d569b47c79d121aac 100644 --- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php @@ -2,6 +2,9 @@ namespace Drupal\Tests\Listeners; +use Drupal\Tests\Traits\ExpectDeprecationTrait; +use PHPUnit\Framework\TestCase; + /** * Removes deprecations that we are yet to fix. * @@ -10,6 +13,15 @@ * fixed. */ trait DeprecationListenerTrait { + use ExpectDeprecationTrait; + + protected function deprecationStartTest($test) { + if ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) { + if ($this->willBeIsolated($test)) { + putenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE=' . tempnam(sys_get_temp_dir(), 'exdep')); + } + } + } /** * Reacts to the end of a test. @@ -21,6 +33,13 @@ trait DeprecationListenerTrait { */ protected function deprecationEndTest($test, $time) { /** @var \PHPUnit\Framework\Test $test */ + if ($file = getenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE')) { + putenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE'); + $expected_deprecations = file_get_contents($file); + if ($expected_deprecations) { + $test->expectedDeprecations(unserialize($expected_deprecations)); + } + } if ($file = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) { $util_test_class = class_exists('PHPUnit_Util_Test') ? 'PHPUnit_Util_Test' : 'PHPUnit\Util\Test'; $method = $test->getName(FALSE); @@ -50,6 +69,26 @@ protected function deprecationEndTest($test, $time) { } } + /** + * Determines if a test is isolated. + * + * @param \PHPUnit_Framework_TestCase|\PHPUnit\Framework\TestCase $test + * The test to check. + * + * @return bool + * TRUE if the isolated, FALSE if not. + */ + private function willBeIsolated($test) { + if ($test->isInIsolation()) { + return FALSE; + } + + $r = new \ReflectionProperty($test, 'runTestInSeparateProcess'); + $r->setAccessible(TRUE); + + return $r->getValue($test); + } + /** * A list of deprecations to ignore whilst fixes are put in place. * diff --git a/core/tests/Drupal/Tests/Listeners/DrupalListener.php b/core/tests/Drupal/Tests/Listeners/DrupalListener.php index 9ed976f76c44a57e25af719377c94ff8781f3328..cafaa2292b373e50f74fd41ec2bb1f70b1ed8a8e 100644 --- a/core/tests/Drupal/Tests/Listeners/DrupalListener.php +++ b/core/tests/Drupal/Tests/Listeners/DrupalListener.php @@ -23,6 +23,13 @@ class DrupalListener extends BaseTestListener { use DrupalComponentTestListenerTrait; use DrupalStandardsListenerTrait; + /** + * {@inheritdoc} + */ + public function startTest(Test $test) { + $this->deprecationStartTest($test); + } + /** * {@inheritdoc} */ diff --git a/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php b/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php index f7c2c76668cb2ddcde72a10517800e04b8e7be72..1fc603a6f4f17be006350bd807cad1896f1a5760 100644 --- a/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php +++ b/core/tests/Drupal/Tests/Listeners/Legacy/DrupalListener.php @@ -17,6 +17,13 @@ class DrupalListener extends \PHPUnit_Framework_BaseTestListener { use DrupalComponentTestListenerTrait; use DrupalStandardsListenerTrait; + /** + * {@inheritdoc} + */ + public function startTest(\PHPUnit_Framework_Test $test) { + $this->deprecationStartTest($test); + } + /** * {@inheritdoc} */ diff --git a/core/tests/Drupal/Tests/Traits/ExpectDeprecationTrait.php b/core/tests/Drupal/Tests/Traits/ExpectDeprecationTrait.php index 279612e9436916090f0b7e607415cd6292058795..4e47f77fe59866ea45328f79afc5f1347dcb72ca 100644 --- a/core/tests/Drupal/Tests/Traits/ExpectDeprecationTrait.php +++ b/core/tests/Drupal/Tests/Traits/ExpectDeprecationTrait.php @@ -4,6 +4,7 @@ use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener as LegacySymfonyTestsListener; use Symfony\Bridge\PhpUnit\SymfonyTestsListener; +use PHPUnit\Framework\TestCase; /** * Adds the ability to dynamically set expected deprecation messages in tests. @@ -19,11 +20,20 @@ trait ExpectDeprecationTrait { /** * Sets an expected deprecation message. * - * @param string $msg + * @param string $message * The expected deprecation message. */ - protected function expectDeprecation($msg) { - // Ensure the class or method is in the legacy group. + protected function expectDeprecation($message) { + $this->expectedDeprecations([$message]); + } + + /** + * Sets expected deprecation messages. + * + * @param string[] $messages + * The expected deprecation messages. + */ + public function expectedDeprecations(array $messages) { if (class_exists('PHPUnit_Util_Test', FALSE)) { $test_util = 'PHPUnit_Util_Test'; $assertion_failed_error = 'PHPUnit_Framework_AssertionFailedError'; @@ -32,36 +42,54 @@ protected function expectDeprecation($msg) { $test_util = 'PHPUnit\Util\Test'; $assertion_failed_error = 'PHPUnit\Framework\AssertionFailedError'; } - $groups = $test_util::getGroups(get_class($this), $this->getName(FALSE)); - if (!in_array('legacy', $groups, TRUE)) { - throw new $assertion_failed_error('Only tests with the `@group legacy` annotation can call `setExpectedDeprecation()`.'); - } + if ($this instanceof \PHPUnit_Framework_TestCase || $this instanceof TestCase) { + // Ensure the class or method is in the legacy group. + $groups = $test_util::getGroups(get_class($this), $this->getName(FALSE)); + if (!in_array('legacy', $groups, TRUE)) { + throw new $assertion_failed_error('Only tests with the `@group legacy` annotation can call `setExpectedDeprecation()`.'); + } - if ($trait = $this->getSymfonyTestListenerTrait()) { // If setting an expected deprecation there is no need to be strict about // testing nothing as this is an assertion. - $this->getTestResultObject()->beStrictAboutTestsThatDoNotTestAnything(FALSE); + $this->getTestResultObject() + ->beStrictAboutTestsThatDoNotTestAnything(FALSE); - // Add the expected deprecation message to the class property. - $reflection_class = new \ReflectionClass($trait); - $expected_deprecations_property = $reflection_class->getProperty('expectedDeprecations'); - $expected_deprecations_property->setAccessible(TRUE); - $expected_deprecations = $expected_deprecations_property->getValue($trait); - $expected_deprecations[] = $msg; - $expected_deprecations_property->setValue($trait, $expected_deprecations); + if ($trait = $this->getSymfonyTestListenerTrait()) { + // Add the expected deprecation message to the class property. + $reflection_class = new \ReflectionClass($trait); + $expected_deprecations_property = $reflection_class->getProperty('expectedDeprecations'); + $expected_deprecations_property->setAccessible(TRUE); + $expected_deprecations = $expected_deprecations_property->getValue($trait); + $expected_deprecations = array_merge($expected_deprecations, $messages); + $expected_deprecations_property->setValue($trait, $expected_deprecations); - // Register the error handler if necessary. - $previous_error_handler_property = $reflection_class->getProperty('previousErrorHandler'); - $previous_error_handler_property->setAccessible(TRUE); - $previous_error_handler = $previous_error_handler_property->getValue($trait); - if (!$previous_error_handler) { - $previous_error_handler = set_error_handler([$trait, 'handleError']); - $previous_error_handler_property->setValue($trait, $previous_error_handler); + // Register the error handler if necessary. + $previous_error_handler_property = $reflection_class->getProperty('previousErrorHandler'); + $previous_error_handler_property->setAccessible(TRUE); + $previous_error_handler = $previous_error_handler_property->getValue($trait); + if (!$previous_error_handler) { + $previous_error_handler = set_error_handler([$trait, 'handleError']); + $previous_error_handler_property->setValue($trait, $previous_error_handler); + } + return; } } - else { - throw new $assertion_failed_error('Can not set an expected deprecation message because the Symfony\Bridge\PhpUnit\SymfonyTestsListener is not registered as a PHPUnit test listener.'); + + // Expected deprecations set by isolated tests need to be written to a file + // so that the test running process can take account of them. + if ($file = getenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE')) { + $expected_deprecations = file_get_contents($file); + if ($expected_deprecations) { + $expected_deprecations = array_merge(unserialize($expected_deprecations), $messages); + } + else { + $expected_deprecations = $messages; + } + file_put_contents($file, serialize($expected_deprecations)); + return; } + + throw new $assertion_failed_error('Can not set an expected deprecation message because the Symfony\Bridge\PhpUnit\SymfonyTestsListener is not registered as a PHPUnit test listener.'); } /**