From de3bb2cc241c21695106811246a1ac77bbff82bc Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Mon, 2 Dec 2019 10:24:57 +0000 Subject: [PATCH] Issue #2979317 by tstoeckler, hchonov, alexpott: Duplicate deprecation header messages break Chromedriver --- core/includes/errors.inc | 24 +++++++++----- .../test_page_test/src/Controller/Test.php | 13 ++++++++ .../test_page_test/test_page_test.routing.yml | 8 +++++ .../FunctionalTests/BrowserTestBaseTest.php | 33 +++++++++++++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/core/includes/errors.inc b/core/includes/errors.inc index 8fc4f39a4c5..68e2482d8d1 100644 --- a/core/includes/errors.inc +++ b/core/includes/errors.inc @@ -87,15 +87,21 @@ function _drupal_error_handler_real($error_level, $message, $filename, $line, $c // 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'] - ); + static $seen = []; + if (array_search($message, $seen, TRUE) === FALSE) { + // Only report each deprecation once. Too many headers can break some + // Chrome and web driver testing. + $seen[] = $message; + $backtrace = debug_backtrace(); + $caller = Error::getLastCaller($backtrace); + _drupal_error_header( + Markup::create(Xss::filterAdmin($message)), + 'User deprecated function', + $caller['function'], + $caller['file'], + $caller['line'] + ); + } } } diff --git a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php index 725c530472d..08ff6155105 100644 --- a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php +++ b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php @@ -155,4 +155,17 @@ class Test { return new RedirectResponse(Url::fromRoute('test_page_test.test_page', [], ['absolute' => TRUE])->toString(), 302); } + /** + * Returns a page while triggering deprecation notices. + */ + public function deprecations() { + // Create 2 identical deprecation messages. This should only trigger a + // single response header. + @trigger_error('Test deprecation message', E_USER_DEPRECATED); + @trigger_error('Test deprecation message', E_USER_DEPRECATED); + return [ + '#markup' => 'Content that triggers deprecation messages', + ]; + } + } diff --git a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml index 08fa101b7c9..336f6c704ba 100644 --- a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml +++ b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml @@ -114,3 +114,11 @@ test_page_test.meta_refresh: _controller: '\Drupal\test_page_test\Controller\Test::metaRefresh' requirements: _access: 'TRUE' + +test_page_test.deprecations: + path: '/test-deprecations' + defaults: + _title: 'Page with deprecation notices' + _controller: '\Drupal\test_page_test\Controller\Test::deprecations' + requirements: + _access: 'TRUE' diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index fecbb0ca4e6..b8247ea88f3 100644 --- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -743,4 +743,37 @@ class BrowserTestBaseTest extends BrowserTestBase { $assert->assertNoEscaped(""); } + /** + * Tests that deprecation headers do not get duplicated. + * + * @group legacy + * + * @see \Drupal\Core\Test\HttpClientMiddleware\TestHttpClientMiddleware::__invoke() + */ + public function testDeprecationHeaders() { + $this->drupalGet('/test-deprecations'); + + $deprecation_messages = []; + foreach ($this->getSession()->getResponseHeaders() as $name => $values) { + if (preg_match('/^X-Drupal-Assertion-[0-9]+$/', $name, $matches)) { + foreach ($values as $value) { + // Call \Drupal\simpletest\WebTestBase::error() with the parameters from + // the header. + $parameters = unserialize(urldecode($value)); + if (count($parameters) === 3) { + if ($parameters[1] === 'User deprecated function') { + $deprecation_messages[] = (string) $parameters[0]; + } + } + } + } + } + + $this->assertContains('Test deprecation message', $deprecation_messages); + $test_deprecation_messages = array_filter($deprecation_messages, function ($message) { + return $message === 'Test deprecation message'; + }); + $this->assertCount(1, $test_deprecation_messages); + } + }