diff --git a/composer.lock b/composer.lock index ddaa66ee82607f59d194b5e6eaaf801c9535981c..8694dc4cbe29b873c8e76deec9256808899856f7 100644 --- a/composer.lock +++ b/composer.lock @@ -2801,7 +2801,7 @@ "version": "8.2.12", "source": { "type": "git", - "url": "https://github.com/klausi/coder.git", + "url": "https://git.drupal.org/project/coder.git", "reference": "984c54a7b1e8f27ff1c32348df69712afd86b17f" }, "dist": { @@ -4194,23 +4194,23 @@ }, { "name": "symfony/phpunit-bridge", - "version": "v3.2.8", + "version": "v3.4.0-BETA2", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "00916603c524b8048906de460b7ea0dfa1651281" + "reference": "9128796e0cc46f17973e7e9345eb34696aafe00b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/00916603c524b8048906de460b7ea0dfa1651281", - "reference": "00916603c524b8048906de460b7ea0dfa1651281", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/9128796e0cc46f17973e7e9345eb34696aafe00b", + "reference": "9128796e0cc46f17973e7e9345eb34696aafe00b", "shasum": "" }, "require": { "php": ">=5.3.3" }, "conflict": { - "phpunit/phpunit": ">=6.0" + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, "suggest": { "ext-zip": "Zip support is required when using bin/simple-phpunit", @@ -4222,7 +4222,7 @@ "type": "symfony-bridge", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "3.4-dev" } }, "autoload": { @@ -4252,13 +4252,14 @@ ], "description": "Symfony PHPUnit Bridge", "homepage": "https://symfony.com", - "time": "2017-04-12T14:13:17+00:00" + "time": "2017-10-28T16:49:05+00:00" } ], "aliases": [], "minimum-stability": "dev", "stability-flags": { - "behat/mink": 20 + "behat/mink": 20, + "symfony/phpunit-bridge": 10 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/core/composer.json b/core/composer.json index 974626f61038cd69159d7817f38a50601d019f0d..48e66198804679502702aeaecdf84408e2676fbd 100644 --- a/core/composer.json +++ b/core/composer.json @@ -47,7 +47,7 @@ "phpunit/phpunit": ">=4.8.35 <5", "phpspec/prophecy": "^1.4", "symfony/css-selector": "~3.2.8", - "symfony/phpunit-bridge": "~3.2.8" + "symfony/phpunit-bridge": "^3.4.0@beta" }, "replace": { "drupal/action": "self.version", diff --git a/core/includes/errors.inc b/core/includes/errors.inc index 284d1835e914c9664c13bc3f70ccb6a3e703064e..e3fd2256c138b51ce080e2f450d978942b9a2dff 100644 --- a/core/includes/errors.inc +++ b/core/includes/errors.inc @@ -83,6 +83,19 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c '@backtrace_string' => (new \Exception())->getTraceAsString(), ], $recoverable || $to_string); } + // If the site is a test site then fail for user deprecations so they can be + // caught by the deprecation error handler. + elseif (DRUPAL_TEST_IN_CHILD_SITE && $error_level === E_USER_DEPRECATED) { + $backtrace = debug_backtrace(); + $caller = Error::getLastCaller($backtrace); + _drupal_error_header( + Markup::create(Xss::filterAdmin($message)), + 'User deprecated function', + $caller['function'], + $caller['file'], + $caller['line'] + ); + } } /** @@ -136,25 +149,7 @@ function _drupal_log_error($error, $fatal = FALSE) { // When running inside the testing framework, we relay the errors // to the tested site by the way of HTTP headers. if (DRUPAL_TEST_IN_CHILD_SITE && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) { - // $number does not use drupal_static as it should not be reset - // as it uniquely identifies each PHP error. - static $number = 0; - $assertion = [ - $error['@message'], - $error['%type'], - [ - 'function' => $error['%function'], - 'file' => $error['%file'], - 'line' => $error['%line'], - ], - ]; - // For non-fatal errors (e.g. PHP notices) _drupal_log_error can be called - // multiple times per request. In that case the response is typically - // generated outside of the error handler, e.g., in a controller. As a - // result it is not possible to use a Response object here but instead the - // headers need to be emitted directly. - header('X-Drupal-Assertion-' . $number . ': ' . rawurlencode(serialize($assertion))); - $number++; + _drupal_error_header($error['@message'], $error['%type'], $error['%function'], $error['%file'], $error['%line']); } $response = new Response(); @@ -325,3 +320,39 @@ function _drupal_get_error_level() { // request on a public site, so use the non-verbose default value. return $error_level ?: ERROR_REPORTING_DISPLAY_ALL; } + +/** + * Adds error information to headers so that tests can access it. + * + * @param $message + * The error message. + * @param $type + * The type of error. + * @param $function + * The function that emitted the error. + * @param $file + * The file that emitted the error. + * @param $line + * The line number in file that emitted the error. + */ +function _drupal_error_header($message, $type, $function, $file, $line) { + // $number does not use drupal_static as it should not be reset + // as it uniquely identifies each PHP error. + static $number = 0; + $assertion = [ + $message, + $type, + [ + 'function' => $function, + 'file' => $file, + 'line' => $line, + ], + ]; + // For non-fatal errors (e.g. PHP notices) _drupal_log_error can be called + // multiple times per request. In that case the response is typically + // generated outside of the error handler, e.g., in a controller. As a + // result it is not possible to use a Response object here but instead the + // headers need to be emitted directly. + header('X-Drupal-Assertion-' . $number . ': ' . rawurlencode(serialize($assertion))); + $number++; +} diff --git a/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php b/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php index 3c4d1427a82b92fbd5233512248e4cfc0d96a8c1..ecb629316e9fa9c40848782411d22a7a28a905ae 100644 --- a/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php +++ b/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php @@ -41,7 +41,15 @@ public function __invoke() { // the header. $parameters = unserialize(urldecode($header_value)); if (count($parameters) === 3) { - throw new \Exception($parameters[1] . ': ' . $parameters[0] . "\n" . Error::formatBacktrace([$parameters[2]])); + if ($parameters[1] === 'User deprecated function') { + // Fire the same deprecation message to allow it to be + // collected by + // \Symfony\Bridge\PhpUnit\DeprecationErrorHandler::collectDeprecations(). + @trigger_error((string) $parameters[0], E_USER_DEPRECATED); + } + else { + throw new \Exception($parameters[1] . ': ' . $parameters[0] . "\n" . Error::formatBacktrace([$parameters[2]])); + } } else { throw new \Exception('Error thrown with the wrong amount of parameters.'); diff --git a/core/modules/basic_auth/src/Tests/BasicAuthTestTrait.php b/core/modules/basic_auth/src/Tests/BasicAuthTestTrait.php index 0e0aceb5e22a413d6531742cc8063c7d5f3702c5..2d063eb18f18e92deb567f5da0b688f02d27480f 100644 --- a/core/modules/basic_auth/src/Tests/BasicAuthTestTrait.php +++ b/core/modules/basic_auth/src/Tests/BasicAuthTestTrait.php @@ -2,7 +2,7 @@ namespace Drupal\basic_auth\Tests; -@trigger_error(__FILE__ . ' is deprecated in Drupal 8.3.0 and will be removed before Drupal 9.0.0. Use \Drupal\Tests\basic_auth\Traits\BasicAuthTestTrait instead. See https://www.drupal.org/node/2862800.', E_USER_DEPRECATED); +@trigger_error(__NAMESPACE__ . '\BasicAuthTestTrait is deprecated in Drupal 8.3.0 and will be removed before Drupal 9.0.0. Use \Drupal\Tests\basic_auth\Traits\BasicAuthTestTrait instead. See https://www.drupal.org/node/2862800.', E_USER_DEPRECATED); /** * Provides common functionality for Basic Authentication test classes. diff --git a/core/modules/migrate/src/Plugin/migrate/process/Iterator.php b/core/modules/migrate/src/Plugin/migrate/process/Iterator.php index 5400e1870a81e0efe53f404ccda54e4a5f8d60fe..4878ad45f1fb98554990c28c5ae499b4a913100c 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/Iterator.php +++ b/core/modules/migrate/src/Plugin/migrate/process/Iterator.php @@ -2,8 +2,7 @@ namespace Drupal\migrate\Plugin\migrate\process; -@trigger_error('The ' . __NAMESPACE__ . '\Iterator is deprecated in -Drupal 8.4.x and will be removed before Drupal 9.0.0. Instead, use ' . __NAMESPACE__ . '\SubProcess', E_USER_DEPRECATED); +@trigger_error('The ' . __NAMESPACE__ . '\Iterator is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Instead, use ' . __NAMESPACE__ . '\SubProcess', E_USER_DEPRECATED); /** * Iterates and processes an associative array. diff --git a/core/modules/migrate/src/Plugin/migrate/process/Migration.php b/core/modules/migrate/src/Plugin/migrate/process/Migration.php index ef8ad72c3cbb812e7b3f941e5963d43782294a9c..8cae1dd7034a8d237f3d0c1b4aa04202b176090e 100644 --- a/core/modules/migrate/src/Plugin/migrate/process/Migration.php +++ b/core/modules/migrate/src/Plugin/migrate/process/Migration.php @@ -2,8 +2,7 @@ namespace Drupal\migrate\Plugin\migrate\process; -@trigger_error('The ' . __NAMESPACE__ . '\Migration is deprecated in -Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use ' . __NAMESPACE__ . '\MigrationLookup', E_USER_DEPRECATED); +@trigger_error('The ' . __NAMESPACE__ . '\Migration is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use ' . __NAMESPACE__ . '\MigrationLookup', E_USER_DEPRECATED); /** * Calculates the value of a property based on a previous migration. diff --git a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationDirectoryTest.php b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationDirectoryTest.php index 427ca91a24a47281d98ce80c0fac2af7ca8df8de..b85aea478fe4f34ae6b24d63f0f2864960c5c1f7 100644 --- a/core/modules/migrate/tests/src/Kernel/Plugin/MigrationDirectoryTest.php +++ b/core/modules/migrate/tests/src/Kernel/Plugin/MigrationDirectoryTest.php @@ -8,6 +8,7 @@ * Tests that migrations exist in the migration_templates directory. * * @group migrate + * @group legacy */ class MigrationDirectoryTest extends MigrateDrupalTestBase { @@ -18,6 +19,8 @@ class MigrationDirectoryTest extends MigrateDrupalTestBase { /** * Tests that migrations in the migration_templates directory are created. + * + * @expectedDeprecationMessage Use of the /migration_templates directory to store migration configuration files is deprecated in Drupal 8.1.0 and will be removed before Drupal 9.0.0. */ public function testMigrationDirectory() { /** @var \Drupal\migrate\Plugin\MigrationPluginManager $plugin_manager */ diff --git a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php index 418ddfbb4a7902efaa69b6219150bfd94d2b6072..9a4527fee0ede9e837b523abaf5f8f7bf8f9b0a5 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -483,10 +483,16 @@ public function testGet() { // GET requests - depending on web server configuration. This would usually // be 'Transfer-Encoding: chunked'. $ignored_headers = ['Date', 'Content-Length', 'X-Drupal-Cache', 'X-Drupal-Dynamic-Cache', 'Transfer-Encoding']; - foreach ($ignored_headers as $ignored_header) { - unset($head_headers[$ignored_header]); - unset($get_headers[$ignored_header]); - } + $header_cleaner = function ($headers) use ($ignored_headers) { + foreach ($headers as $header => $value) { + if (strpos($header, 'X-Drupal-Assertion-') === 0 || in_array($header, $ignored_headers)) { + unset($headers[$header]); + } + } + return $headers; + }; + $get_headers = $header_cleaner($get_headers); + $head_headers = $header_cleaner($head_headers); $this->assertSame($get_headers, $head_headers); // BC: serialization_update_8302(). diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index b5874b5ae651cb99cdec832954f820f7650f46ce..22cd7681874cfd7a3cda73d7b945438ae0107c1e 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -18,6 +18,7 @@ use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait; use Drupal\Tests\EntityViewTrait; use Drupal\Tests\block\Traits\BlockCreationTrait as BaseBlockCreationTrait; +use Drupal\Tests\Listeners\DeprecationListener; use Drupal\Tests\node\Traits\ContentTypeCreationTrait; use Drupal\Tests\node\Traits\NodeCreationTrait; use Drupal\Tests\Traits\Core\CronRunTrait; @@ -690,9 +691,21 @@ protected function curlHeaderCallback($curlHandler, $header) { // generated by _drupal_log_error() in the exact form required // by \Drupal\simpletest\WebTestBase::error(). if (preg_match('/^X-Drupal-Assertion-[0-9]+: (.*)$/', $header, $matches)) { - // Call \Drupal\simpletest\WebTestBase::error() with the parameters from - // the header. - call_user_func_array([&$this, 'error'], unserialize(urldecode($matches[1]))); + $parameters = unserialize(urldecode($matches[1])); + // Handle deprecation notices triggered by system under test. + if ($parameters[1] === 'User deprecated function') { + if (getenv('SYMFONY_DEPRECATIONS_HELPER') !== 'disabled') { + $message = (string) $parameters[0]; + if (!in_array($message, DeprecationListener::getSkippedDeprecations())) { + call_user_func_array([&$this, 'error'], $parameters); + } + } + } + else { + // Call \Drupal\simpletest\WebTestBase::error() with the parameters from + // the header. + call_user_func_array([&$this, 'error'], $parameters); + } } // Save cookies. diff --git a/core/modules/system/tests/modules/deprecation_test/deprecation_test.module b/core/modules/system/tests/modules/deprecation_test/deprecation_test.module new file mode 100644 index 0000000000000000000000000000000000000000..e255021d654881760d59fb70a7e8d08081758a3e --- /dev/null +++ b/core/modules/system/tests/modules/deprecation_test/deprecation_test.module @@ -0,0 +1,20 @@ +<?php + +/** + * @file + * Contains functions for testing calling deprecated functions in tests. + */ + +/** + * A deprecated function. + * + * @return string + * A known return value of 'known_return_value'. + * + * @deprecated in Drupal 8.4.x. Might be removed before Drupal 9.0.0. This is + * the deprecation message for deprecated_test_function(). + */ +function deprecation_test_function() { + @trigger_error('This is the deprecation message for deprecation_test_function().', E_USER_DEPRECATED); + return 'known_return_value'; +} diff --git a/core/modules/system/tests/modules/deprecation_test/deprecation_test.routing.yml b/core/modules/system/tests/modules/deprecation_test/deprecation_test.routing.yml new file mode 100644 index 0000000000000000000000000000000000000000..3ef71b806fd5c814ab2101987fd59ed72375de86 --- /dev/null +++ b/core/modules/system/tests/modules/deprecation_test/deprecation_test.routing.yml @@ -0,0 +1,6 @@ +deprecation_test.route: + path: '/this-calls-a-deprecated-method' + defaults: + _controller: \Drupal\deprecation_test\DeprecatedController::deprecatedMethod + requirements: + _access: 'TRUE' diff --git a/core/modules/system/tests/modules/deprecation_test/src/DeprecatedController.php b/core/modules/system/tests/modules/deprecation_test/src/DeprecatedController.php new file mode 100644 index 0000000000000000000000000000000000000000..44cf330cc82fb9a2f59b3fad271c3a68f137055e --- /dev/null +++ b/core/modules/system/tests/modules/deprecation_test/src/DeprecatedController.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\deprecation_test; + +/** + * Defines a controller that calls a deprecated method. + */ +class DeprecatedController { + + /** + * Controller callback. + * + * @return array + * Render array. + */ + public function deprecatedMethod() { + return [ + '#markup' => deprecation_test_function(), + ]; + } + +} diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist index e5bab48f43d095a29a72f59dd9659ccfae94c4b6..9b3a8b2daf172b49513fca7a4af75269207ebaf1 100644 --- a/core/phpunit.xml.dist +++ b/core/phpunit.xml.dist @@ -29,6 +29,8 @@ <env name="SIMPLETEST_DB" value=""/> <!-- Example BROWSERTEST_OUTPUT_DIRECTORY value: /path/to/webroot/sites/simpletest/browser_output --> <env name="BROWSERTEST_OUTPUT_DIRECTORY" value=""/> + <!-- To disable deprecation testing uncomment the next line. --> + <!-- <env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled"/> --> </php> <testsuites> <testsuite name="unit"> @@ -45,6 +47,10 @@ </testsuite> </testsuites> <listeners> + <listener class="\Drupal\Tests\Listeners\DeprecationListener"> + </listener> + <!-- The Symfony deprecation listener has to come after the Drupal + deprecation listener --> <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener"> </listener> <listener class="\Drupal\Tests\Listeners\DrupalStandardsListener"> diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh index 09a7aad57cef099b1b4c03cd21717116d54aa1d0..5ebf9f0c9fba0a8455a4519c547d40a44a9a4e83 100755 --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -305,6 +305,10 @@ function simpletest_script_help() { --non-html Removes escaping from output. Useful for reading results on the CLI. + --suppress-deprecations + + Stops tests from failing if deprecation errors are triggered. + <test1>[,<test2>[,<test3> ...]] One or more tests to be run. By default, these are interpreted @@ -369,6 +373,7 @@ function simpletest_script_parse_args() { 'test_names' => array(), 'repeat' => 1, 'die-on-fail' => FALSE, + 'suppress-deprecations' => FALSE, 'browser' => FALSE, // Used internally. 'test-id' => 0, @@ -784,6 +789,12 @@ function simpletest_script_run_one_test($test_id, $test_class) { $methods = array(); } $test = new $class_name($test_id); + if ($args['suppress-deprecations']) { + putenv('SYMFONY_DEPRECATIONS_HELPER=disabled'); + } + else { + putenv('SYMFONY_DEPRECATIONS_HELPER=strict'); + } if (is_subclass_of($test_class, TestCase::class)) { $status = simpletest_script_run_phpunit($test_id, $test_class); } @@ -834,7 +845,7 @@ function simpletest_script_command($test_id, $test_class) { } $command .= ' --php ' . escapeshellarg($php); $command .= " --test-id $test_id"; - foreach (array('verbose', 'keep-results', 'color', 'die-on-fail') as $arg) { + foreach (array('verbose', 'keep-results', 'color', 'die-on-fail', 'suppress-deprecations') as $arg) { if ($args[$arg]) { $command .= ' --' . $arg; } diff --git a/core/tests/Drupal/FunctionalTests/Core/Test/PhpUnitBridgeTest.php b/core/tests/Drupal/FunctionalTests/Core/Test/PhpUnitBridgeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bc843c31a1c28c5bf3f8ed881b722223689ba2b7 --- /dev/null +++ b/core/tests/Drupal/FunctionalTests/Core/Test/PhpUnitBridgeTest.php @@ -0,0 +1,32 @@ +<?php + +namespace Drupal\FunctionalTests\Core\Test; + +use Drupal\Core\Url; +use Drupal\Tests\BrowserTestBase; + +/** + * Tests Drupal's integration with Symfony PHPUnit Bridge. + * + * @group Test + * @group legacy + */ +class PhpUnitBridgeTest extends BrowserTestBase { + + protected static $modules = ['deprecation_test']; + + /** + * @expectedDeprecation This is the deprecation message for deprecation_test_function(). + */ + public function testSilencedError() { + $this->assertEquals('known_return_value', deprecation_test_function()); + } + + /** + * @expectedDeprecation This is the deprecation message for deprecation_test_function(). + */ + public function testErrorOnSiteUnderTest() { + $this->drupalGet(Url::fromRoute('deprecation_test.route')); + } + +} diff --git a/core/tests/Drupal/KernelTests/Core/Test/PhpUnitBridgeTest.php b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitBridgeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d82a37b90698adf6a7bd4202a9271c2f1d8f89d4 --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Test/PhpUnitBridgeTest.php @@ -0,0 +1,33 @@ +<?php + +namespace Drupal\KernelTests\Core\Test; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass; + +/** + * Test how kernel tests interact with deprecation errors. + * + * @group Test + * @group legacy + */ +class PhpUnitBridgeTest extends KernelTestBase { + + public static $modules = ['deprecation_test']; + + /** + * @expectedDeprecation Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass is deprecated. + */ + public function testDeprecatedClass() { + $deprecated = new FixtureDeprecatedClass(); + $this->assertEquals('test', $deprecated->testFunction()); + } + + /** + * @expectedDeprecation This is the deprecation message for deprecation_test_function(). + */ + public function testDeprecatedFunction() { + $this->assertEquals('known_return_value', \deprecation_test_function()); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeIsolatedTest.php b/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeIsolatedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..28e331af37e721e6abe1aa1ebd162040252312ae --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeIsolatedTest.php @@ -0,0 +1,27 @@ +<?php + +namespace Drupal\Tests\Core\Test; + +use Drupal\Tests\UnitTestCase; +use Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass; + +/** + * Test how unit tests interact with deprecation errors in process isolation. + * + * @runTestsInSeparateProcesses + * @preserveGlobalState disabled + * + * @group Test + * @group legacy + */ +class PhpUnitBridgeIsolatedTest extends UnitTestCase { + + /** + * @expectedDeprecation Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass is deprecated. + */ + public function testDeprecatedClass() { + $deprecated = new FixtureDeprecatedClass(); + $this->assertEquals('test', $deprecated->testFunction()); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeTest.php b/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..73ba0de1676c3e463528bca50293cbe22280f918 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Test/PhpUnitBridgeTest.php @@ -0,0 +1,29 @@ +<?php + +namespace Drupal\Tests\Core\Test; + +use Drupal\Tests\UnitTestCase; +use Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass; + +/** + * Test how unit tests interact with deprecation errors. + * + * @group Test + * @group legacy + */ +class PhpUnitBridgeTest extends UnitTestCase { + + /** + * @expectedDeprecation Drupal\deprecation_test\Deprecation\FixtureDeprecatedClass is deprecated. + */ + public function testDeprecatedClass() { + $deprecated = new FixtureDeprecatedClass(); + $this->assertEquals('test', $deprecated->testFunction()); + } + + public function testDeprecatedFunction() { + $this->markTestIncomplete('Modules are not loaded for unit tests, so deprecated_test_function() will not be available.'); + $this->assertEquals('known_return_value', \deprecation_test_function()); + } + +} diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListener.php b/core/tests/Drupal/Tests/Listeners/DeprecationListener.php new file mode 100644 index 0000000000000000000000000000000000000000..a037c0224d4807a67979223a068180bf88c83923 --- /dev/null +++ b/core/tests/Drupal/Tests/Listeners/DeprecationListener.php @@ -0,0 +1,116 @@ +<?php + +namespace Drupal\Tests\Listeners; + +/** + * Removes deprecations that we are yet to fix. + * + * @internal + * This class will be removed once all the deprecation notices have been + * fixed. + */ +class DeprecationListener extends \PHPUnit_Framework_BaseTestListener { + + /** + * {@inheritdoc} + */ + public function endTest(\PHPUnit_Framework_Test $test, $time) { + // Need to edit the file of deprecations. + if ($file = getenv('SYMFONY_DEPRECATIONS_SERIALIZE')) { + $deprecations = file_get_contents($file); + $deprecations = $deprecations ? unserialize($deprecations) : []; + $resave = FALSE; + foreach ($deprecations as $key => $deprecation) { + if (in_array($deprecation[1], static::getSkippedDeprecations())) { + unset($deprecations[$key]); + $resave = TRUE; + } + } + if ($resave) { + file_put_contents($file, serialize($deprecations)); + } + } + } + + /** + * A list of deprecations to ignore whilst fixes are put in place. + * + * @return string[] + * A list of deprecations to ignore. + * + * @internal + */ + public static function getSkippedDeprecations() { + return [ + 'As of 3.1 an Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface is used to resolve arguments. In 4.0 the $argumentResolver becomes the Symfony\Component\HttpKernel\Controller\ArgumentResolver if no other is provided instead of using the $resolver argument.', + 'Symfony\Component\HttpKernel\Controller\ControllerResolver::getArguments is deprecated as of 3.1 and will be removed in 4.0. Implement the Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface and inject it in the HttpKernel instead.', + 'The Twig_Node::getLine method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateLine() instead.', + 'The Twig_Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', + 'Install profile will be a mandatory parameter in Drupal 9.0.', + 'Setting the strict option of the Choice constraint to false is deprecated since version 3.2 and will be removed in 4.0.', + 'The revision_user revision metadata key is not set.', + 'The revision_created revision metadata key is not set.', + 'The revision_log_message revision metadata key is not set.', + 'The "entity.query" service relies on the deprecated "Drupal\Core\Entity\Query\QueryFactory" class. It should either be deprecated or its implementation upgraded.', + 'MigrateCckField is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField instead.', + 'MigrateCckFieldPluginManager is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManager instead.', + 'MigrateCckFieldPluginManagerInterface is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateFieldPluginManagerInterface instead.', + 'The "plugin.manager.migrate.cckfield" service is deprecated. You should use the \'plugin.manager.migrate.field\' service instead. See https://www.drupal.org/node/2751897', + 'The Drupal\migrate\Plugin\migrate\process\Iterator is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. Instead, use Drupal\migrate\Plugin\migrate\process\SubProcess', + 'Drupal\system\Tests\Update\DbUpdatesTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use \Drupal\FunctionalTests\Update\DbUpdatesTrait instead. See https://www.drupal.org/node/2896640.', + 'Using "null" for the value of node "count" of "Drupal\Core\Template\TwigNodeTrans" is deprecated since version 1.25 and will be removed in 2.0.', + 'Using "null" for the value of node "options" of "Drupal\Core\Template\TwigNodeTrans" is deprecated since version 1.25 and will be removed in 2.0.', + 'Using "null" for the value of node "plural" of "Drupal\Core\Template\TwigNodeTrans" is deprecated since version 1.25 and will be removed in 2.0.', + 'The Behat\Mink\Selector\SelectorsHandler::xpathLiteral method is deprecated as of 1.7 and will be removed in 2.0. Use \Behat\Mink\Selector\Xpath\Escaper::escapeLiteral instead when building Xpath or pass the unescaped value when using the named selector.', + 'Passing an escaped locator to the named selector is deprecated as of 1.7 and will be removed in 2.0. Pass the raw value instead.', + 'Providing settings under \'handler_settings\' is deprecated and will be removed before 9.0.0. Move the settings in the root of the configuration array. See https://www.drupal.org/node/2870971.', + 'AssertLegacyTrait::getRawContent() is scheduled for removal in Drupal 9.0.0. Use $this->getSession()->getPage()->getContent() instead.', + 'AssertLegacyTrait::getAllOptions() is scheduled for removal in Drupal 9.0.0. Use $element->findAll(\'xpath\', \'option\') instead.', + 'assertNoCacheTag() is deprecated and scheduled for removal in Drupal 9.0.0. Use $this->assertSession()->responseHeaderNotContains() instead. See https://www.drupal.org/node/2864029.', + 'assertNoPattern() is deprecated and scheduled for removal in Drupal 9.0.0. Use $this->assertSession()->responseNotMatches($pattern) instead. See https://www.drupal.org/node/2864262.', + 'The $published parameter is deprecated since version 8.3.x and will be removed in 9.0.0.', + 'The Drupal\config\Tests\AssertConfigEntityImportTrait is deprecated in Drupal 8.4.1 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\config\Traits\AssertConfigEntityImportTrait. See https://www.drupal.org/node/2916197.', + 'Drupal\system\Tests\Menu\AssertBreadcrumbTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait', + '\Drupal\Tests\node\Functional\AssertButtonsTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\node\Functional\AssertButtonsTrait', + 'Drupal\system\Tests\Menu\AssertMenuActiveTrailTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\system\Functional\Menu\AssertMenuActiveTrailTrait', + 'Drupal\taxonomy\Tests\TaxonomyTranslationTestTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTranslationTestTrait', + 'Drupal\basic_auth\Tests\BasicAuthTestTrait is deprecated in Drupal 8.3.0 and will be removed before Drupal 9.0.0. Use \Drupal\Tests\basic_auth\Traits\BasicAuthTestTrait instead. See https://www.drupal.org/node/2862800.', + 'Drupal\taxonomy\Tests\TaxonomyTestTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait', + 'Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "/system-test/È„chÈ/meφΩ/{text}".', + 'Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "/somewhere/{item}/over/the/קainbow".', + 'Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "/place/meφω".', + 'Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "/PLACE/meφω".', + 'Passing a Session object to the ExpectationException constructor is deprecated as of Mink 1.7. Pass the driver instead.', + 'The Drupal\editor\Plugin\EditorBase::settingsFormValidate method is deprecated since version 8.3.x and will be removed in 9.0.0.', + 'CckFile is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\file\Plugin\migrate\process\d6\FieldFile instead.', + 'The Drupal\migrate\Plugin\migrate\process\Migration is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use Drupal\migrate\Plugin\migrate\process\MigrationLookup', + 'LinkField is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\link\Plugin\migrate\field\d7\LinkField instead.', + 'LinkField is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\link\Plugin\migrate\field\d6\LinkField instead.', + 'CckFieldPluginBase is deprecated in Drupal 8.3.x and will be be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Plugin\migrate\field\FieldPluginBase instead.', + 'MigrateCckFieldInterface is deprecated in Drupal 8.3.x and will be removed before Drupal 9.0.x. Use \Drupal\migrate_drupal\Annotation\MigrateField instead.', + 'Drupal\system\Plugin\views\field\BulkForm is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Use \Drupal\views\Plugin\views\field\BulkForm instead. See https://www.drupal.org/node/2916716.', + 'The numeric plugin for watchdog.wid field is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Must use standard plugin instead. See https://www.drupal.org/node/2876378.', + 'The numeric plugin for watchdog.uid field is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Must use standard plugin instead. See https://www.drupal.org/node/2876378.', + 'The in_operator plugin for watchdog.type filter is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Must use dblog_types plugin instead. See https://www.drupal.org/node/2876378.', + 'Using an instance of "Twig_Filter_Function" for filter "testfilter" is deprecated since version 1.21. Use Twig_SimpleFilter instead.', + 'The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', + 'Using an instance of "Twig_Function_Function" for function "testfunc" is deprecated since version 1.21. Use Twig_SimpleFunction instead.', + 'The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', + 'The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', + 'The Twig_Filter class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', + 'The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', + 'Referencing the "twig_extension_test.test_extension" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', + 'Passing in arguments the legacy way is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Provide the right parameter names in the method, similar to controllers. See https://www.drupal.org/node/2894819', + 'DateField is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\datetime\Plugin\migrate\field\DateField instead.', + 'The Drupal\taxonomy\Entity\Term::getVocabularyId method is deprecated since version 8.4.0 and will be removed before 9.0.0. Use Drupal\taxonomy\Entity\Term::bundle() instead to get the vocabulary ID.', + 'The Drupal\editor\Plugin\EditorBase::settingsFormSubmit method is deprecated since version 8.3.x and will be removed in 9.0.0.', + 'CommentVariable is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\node\Plugin\migrate\source\d6\NodeType instead.', + 'CommentType is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\node\Plugin\migrate\source\d7\NodeType instead.', + 'CommentVariablePerCommentType is deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.x. Use \Drupal\node\Plugin\migrate\source\d6\NodeType instead.', + 'The Drupal\config_translation\Plugin\migrate\source\d6\I18nProfileField is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use Drupal\config_translation\Plugin\migrate\source\d6\ProfileFieldTranslation', + 'The Drupal\migrate_drupal\Plugin\migrate\source\d6\i18nVariable is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use Drupal\migrate_drupal\Plugin\migrate\source\d6\VariableTranslation', + 'Implicit cacheability metadata bubbling (onto the global render context) in normalizers is deprecated since Drupal 8.5.0 and will be removed in Drupal 9.0.0. Use the "cacheability" serialization context instead, for explicit cacheability metadata bubbling. See https://www.drupal.org/node/2918937', + ]; + } + +}