From fbee2baaab8fb8f8be29462e4798b51e1fe758d4 Mon Sep 17 00:00:00 2001 From: Lee Rowlands Date: Thu, 28 Dec 2023 08:03:14 +1000 Subject: [PATCH] Issue #2484991 by znerol, voleger, andypost, dww, anmolgoyal74, markdorison, ankithashetty, larowlan, daffie, alexpott: Add the session to the request in KernelTestBase, BrowserTestBase, and drush --- core/lib/Drupal/Core/DrupalKernel.php | 26 ++++++++++++++++ .../Drupal/Core/StackMiddleware/Session.php | 31 ++++++++++++++++--- .../Core/Test/FunctionalTestSetupTrait.php | 8 ++--- .../tests/src/Kernel/BookMultilingualTest.php | 6 +++- .../tests/src/Kernel/CommentHostnameTest.php | 3 ++ .../tests/src/Kernel/RequirementsTest.php | 3 ++ .../LanguageNegotiationContentEntityTest.php | 3 ++ .../LanguageUILanguageNegotiationTest.php | 3 ++ .../src/Kernel/EntityUrlLanguageTest.php | 3 ++ ...enuLinkContentCacheabilityBubblingTest.php | 3 ++ .../Functional/Views/StyleSerializerTest.php | 3 ++ .../syslog/tests/src/Kernel/SyslogTest.php | 3 ++ .../Database/SelectPagerDefaultTest.php | 3 ++ .../src/Kernel/Block/SystemMenuBlockTest.php | 4 +++ .../src/Kernel/Theme/TwigIncludeTest.php | 18 +++++++---- .../Kernel/Token/TokenReplaceKernelTest.php | 3 ++ .../src/Tests/AssertViewsCacheTagsTrait.php | 4 +++ .../Kernel/Handler/AreaDisplayLinkTest.php | 10 ++++-- .../FunctionalTests/BrowserTestBaseTest.php | 25 +++++++++++++++ .../Installer/InstallerTestBase.php | 3 ++ .../Core/Entity/EntityQueryTest.php | 4 +++ .../Core/File/FileUrlGeneratorTest.php | 5 +++ .../Core/File/UrlTransformRelativeTest.php | 3 ++ .../Core/Form/ExternalFormUrlTest.php | 4 +++ .../Core/Form/FormActionXssTest.php | 3 ++ .../Core/Pager/PagerManagerTest.php | 4 +++ .../Core/Pager/RequestPagerTest.php | 4 +++ .../Core/Path/PathValidatorTest.php | 10 +++++- .../Core/Plugin/Condition/RequestPathTest.php | 3 ++ .../Plugin/Condition/ResponseStatusTest.php | 3 ++ .../Render/Element/TableSortExtenderTest.php | 13 ++++++++ .../Core/RouteProcessor/RouteNoneTest.php | 6 ++++ .../RouteProcessorCurrentIntegrationTest.php | 7 +++++ .../TranslationStringTest.php | 6 ++-- .../KernelTests/Core/Theme/ImageTest.php | 3 ++ .../Drupal/KernelTests/KernelTestBase.php | 14 +++++++++ .../Drupal/KernelTests/KernelTestBaseTest.php | 29 +++++++++++++++++ core/tests/Drupal/Tests/BrowserTestBase.php | 14 +++++++++ 38 files changed, 279 insertions(+), 21 deletions(-) diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index dd67a2b5416..d778693888f 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -28,6 +28,8 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\TerminableInterface; @@ -582,6 +584,11 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { (bool) Settings::get(RequestSanitizer::SANITIZE_LOG, FALSE) ); + // Ensure that there is a session on every request. + if (!$request->hasSession()) { + $this->initializeEphemeralSession($request); + } + $this->loadLegacyIncludes(); // Load all enabled modules. @@ -1638,4 +1645,23 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { return $config['profile'] ?? NULL; } + /** + * Initializes a session backed by in-memory store and puts it on the request. + * + * A simple in-memory store is sufficient for command line tools and tests. + * Web requests will be processed by the session middleware where the mock + * session is replaced by a session object backed with persistent storage and + * a real session handler. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request. + * + * @see \Drupal\Core\StackMiddleware\Session::handle() + */ + protected function initializeEphemeralSession(Request $request): void { + $session = new Session(new MockArraySessionStorage()); + $session->start(); + $request->setSession($session); + } + } diff --git a/core/lib/Drupal/Core/StackMiddleware/Session.php b/core/lib/Drupal/Core/StackMiddleware/Session.php index d9da60ac602..94841e1508d 100644 --- a/core/lib/Drupal/Core/StackMiddleware/Session.php +++ b/core/lib/Drupal/Core/StackMiddleware/Session.php @@ -49,19 +49,42 @@ class Session implements HttpKernelInterface { * {@inheritdoc} */ public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = TRUE): Response { + // Initialize and start a session for web requests. Command line tools and + // the parent site in functional tests must continue to use the ephemeral + // session initialized and started in DrupalKernel::preHandle(). if ($type === self::MAIN_REQUEST && PHP_SAPI !== 'cli') { - $session = $this->container->get($this->sessionServiceName); - $session->start(); - $request->setSession($session); + $this->initializePersistentSession($request); } $result = $this->httpKernel->handle($request, $type, $catch); - if ($type === self::MAIN_REQUEST && $request->hasSession()) { + if ($type === self::MAIN_REQUEST && PHP_SAPI !== 'cli' && $request->hasSession()) { $request->getSession()->save(); } return $result; } + /** + * Initializes a session backed by persistent store and puts it on the request. + * + * Sessions for web requests need to be backed by a persistent session store + * and a real session handler (responsible for session cookie management). + * In contrast, a simple in-memory store is sufficient for command line tools + * and tests. Hence, the persistent session should only ever be placed on web + * requests while command line tools and the parent site in functional tests + * must continue to use the ephemeral session initialized in + * DrupalKernel::preHandle(). + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request. + * + * @see \Drupal\Core\DrupalKernel::preHandle() + */ + protected function initializePersistentSession(Request $request): void { + $session = $this->container->get($this->sessionServiceName); + $session->start(); + $request->setSession($session); + } + } diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php index 2e7083ff86f..737f1ef247e 100644 --- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php +++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php @@ -23,6 +23,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Yaml\Yaml as SymfonyYaml; use Drupal\Core\Routing\RouteObjectInterface; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -210,10 +212,6 @@ trait FunctionalTestSetupTrait { protected function rebuildContainer() { // Rebuild the kernel and bring it back to a fully bootstrapped state. $this->container = $this->kernel->rebuildContainer(); - - // Make sure the URL generator has a request object, otherwise calls to - // $this->drupalGet() will fail. - $this->prepareRequestForGenerator(); } /** @@ -254,6 +252,7 @@ trait FunctionalTestSetupTrait { */ protected function prepareRequestForGenerator($clean_urls = TRUE, $override_server_vars = []) { $request = Request::createFromGlobals(); + $request->setSession(new Session(new MockArraySessionStorage())); $base_path = $request->getBasePath(); if ($clean_urls) { $request_path = $base_path ? $base_path . '/user' : 'user'; @@ -265,6 +264,7 @@ trait FunctionalTestSetupTrait { $server = array_merge($request->server->all(), $override_server_vars); $request = Request::create($request_path, 'GET', [], [], [], $server); + $request->setSession(new Session(new MockArraySessionStorage())); // Ensure the request time is REQUEST_TIME to ensure that API calls // in the test use the right timestamp. $request->server->set('REQUEST_TIME', REQUEST_TIME); diff --git a/core/modules/book/tests/src/Kernel/BookMultilingualTest.php b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php index fbdfc3d8499..7c2ead6bc72 100644 --- a/core/modules/book/tests/src/Kernel/BookMultilingualTest.php +++ b/core/modules/book/tests/src/Kernel/BookMultilingualTest.php @@ -14,6 +14,8 @@ use Drupal\node\Entity\NodeType; use Drupal\Tests\user\Traits\UserCreationTrait; use Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUser; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -271,7 +273,9 @@ class BookMultilingualTest extends KernelTestBase { * is used instead of the content language. */ protected function setCurrentLanguage(string $langcode): void { - \Drupal::requestStack()->push(Request::create("http://$langcode.book.test.domain/")); + $request = Request::create("http://$langcode.book.test.domain/"); + $request->setSession(new Session(new MockArraySessionStorage())); + \Drupal::requestStack()->push($request); $language_manager = $this->container->get('language_manager'); $language_manager->reset(); $current_user = \Drupal::currentUser(); diff --git a/core/modules/comment/tests/src/Kernel/CommentHostnameTest.php b/core/modules/comment/tests/src/Kernel/CommentHostnameTest.php index a056c086de7..7099c6d9353 100644 --- a/core/modules/comment/tests/src/Kernel/CommentHostnameTest.php +++ b/core/modules/comment/tests/src/Kernel/CommentHostnameTest.php @@ -6,6 +6,8 @@ use Drupal\comment\Entity\Comment; use Drupal\comment\Entity\CommentType; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the hostname base field. @@ -29,6 +31,7 @@ class CommentHostnameTest extends KernelTestBase { public function testGetDefaultHostname() { // Create a fake request to be used for testing. $request = Request::create('/', 'GET', [], [], [], ['REMOTE_ADDR' => '203.0.113.1']); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $stack */ $stack = $this->container->get('request_stack'); $stack->push($request); diff --git a/core/modules/file/tests/src/Kernel/RequirementsTest.php b/core/modules/file/tests/src/Kernel/RequirementsTest.php index 4d472644dc4..224616e089b 100644 --- a/core/modules/file/tests/src/Kernel/RequirementsTest.php +++ b/core/modules/file/tests/src/Kernel/RequirementsTest.php @@ -7,6 +7,8 @@ namespace Drupal\Tests\file\Kernel; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the file requirements. @@ -69,6 +71,7 @@ class RequirementsTest extends KernelTestBase { */ private function setServerSoftware(?string $software): void { $request = new Request(); + $request->setSession(new Session(new MockArraySessionStorage())); if (is_string($software)) { $request->server->set('SERVER_SOFTWARE', $software); } diff --git a/core/modules/language/tests/src/Functional/LanguageNegotiationContentEntityTest.php b/core/modules/language/tests/src/Functional/LanguageNegotiationContentEntityTest.php index d13b923e3b7..d74a1def394 100644 --- a/core/modules/language/tests/src/Functional/LanguageNegotiationContentEntityTest.php +++ b/core/modules/language/tests/src/Functional/LanguageNegotiationContentEntityTest.php @@ -10,6 +10,8 @@ use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; use Drupal\Tests\BrowserTestBase; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -185,6 +187,7 @@ class LanguageNegotiationContentEntityTest extends BrowserTestBase { $request = Request::create($path); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, $route_name); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route($path)); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); } diff --git a/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php b/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php index 7a635e11407..46f518b2194 100644 --- a/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php +++ b/core/modules/language/tests/src/Functional/LanguageUILanguageNegotiationTest.php @@ -19,6 +19,8 @@ use Drupal\Core\Language\LanguageInterface; use Symfony\Component\HttpFoundation\Request; use Drupal\language\LanguageNegotiatorInterface; use Drupal\block\Entity\Block; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the language UI for language switching. @@ -564,6 +566,7 @@ class LanguageUILanguageNegotiationTest extends BrowserTestBase { // Test HTTPS via current URL scheme. $request = Request::create('', 'GET', [], [], [], ['HTTPS' => 'on']); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); $italian_url = Url::fromRoute('system.admin', [], ['language' => $languages['it']])->toString(); $correct_link = 'https://' . $link; diff --git a/core/modules/language/tests/src/Kernel/EntityUrlLanguageTest.php b/core/modules/language/tests/src/Kernel/EntityUrlLanguageTest.php index 58ccffc612e..44505aac764 100644 --- a/core/modules/language/tests/src/Kernel/EntityUrlLanguageTest.php +++ b/core/modules/language/tests/src/Kernel/EntityUrlLanguageTest.php @@ -9,6 +9,8 @@ use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationContentEntity; use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -132,6 +134,7 @@ class EntityUrlLanguageTest extends LanguageTestBase { $request = Request::create($path); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, $route_name); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route($path)); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); } diff --git a/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php b/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php index bc128897293..fd37d6720ea 100644 --- a/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php +++ b/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php @@ -12,6 +12,8 @@ use Drupal\Tests\user\Traits\UserCreationTrait; use Drupal\user\Entity\User; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -62,6 +64,7 @@ class MenuLinkContentCacheabilityBubblingTest extends KernelTestBase { $request = Request::create('/'); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); diff --git a/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php b/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php index 7c72ea90ed2..3e10fe98bfc 100644 --- a/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php +++ b/core/modules/rest/tests/src/Functional/Views/StyleSerializerTest.php @@ -16,6 +16,8 @@ use Drupal\views\Entity\View; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\Views; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the serializer style plugin. @@ -594,6 +596,7 @@ class StyleSerializerTest extends ViewTestBase { // We set up a request so it looks like a request in the live preview. $request = new Request(); $request->query->add([MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = \Drupal::service('request_stack'); $request_stack->push($request); diff --git a/core/modules/syslog/tests/src/Kernel/SyslogTest.php b/core/modules/syslog/tests/src/Kernel/SyslogTest.php index 14137c73efa..987f6bef6ec 100644 --- a/core/modules/syslog/tests/src/Kernel/SyslogTest.php +++ b/core/modules/syslog/tests/src/Kernel/SyslogTest.php @@ -4,6 +4,8 @@ namespace Drupal\Tests\syslog\Kernel; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Test syslog logger functionality. @@ -30,6 +32,7 @@ class SyslogTest extends KernelTestBase { $request = Request::create('/page-not-found', 'GET', [], [], [], ['REMOTE_ADDR' => '1.2.3.4']); $request->headers->set('Referer', 'other-site'); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::requestStack()->push($request); $user = $this->getMockBuilder('Drupal\Core\Session\AccountInterface')->getMock(); diff --git a/core/modules/system/tests/src/Functional/Database/SelectPagerDefaultTest.php b/core/modules/system/tests/src/Functional/Database/SelectPagerDefaultTest.php index 41aa5c3a830..67129d429c7 100644 --- a/core/modules/system/tests/src/Functional/Database/SelectPagerDefaultTest.php +++ b/core/modules/system/tests/src/Functional/Database/SelectPagerDefaultTest.php @@ -6,6 +6,8 @@ use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Database\Database; use Drupal\Core\Database\Query\PagerSelectExtender; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the pager query select extender. @@ -141,6 +143,7 @@ class SelectPagerDefaultTest extends DatabaseTestBase { $request->query->replace([ 'page' => '3, 2, 1, 0', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $connection = Database::getConnection(); diff --git a/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php index a335d9648a5..a09d42b4021 100644 --- a/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php +++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php @@ -11,6 +11,8 @@ use Drupal\Tests\Core\Menu\MenuLinkMock; use Drupal\user\Entity\User; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -233,6 +235,7 @@ class SystemMenuBlockTest extends KernelTestBase { $request = new Request(); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'example3'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $route); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); // \Drupal\Core\Menu\MenuActiveTrail uses the cache collector pattern, which // includes static caching. Since this second scenario simulates a second @@ -300,6 +303,7 @@ class SystemMenuBlockTest extends KernelTestBase { $request = new Request(); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, $active_route); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, $route); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); $block_build = $block->build(); diff --git a/core/modules/system/tests/src/Kernel/Theme/TwigIncludeTest.php b/core/modules/system/tests/src/Kernel/Theme/TwigIncludeTest.php index 78298c5044d..2abfc8f1708 100644 --- a/core/modules/system/tests/src/Kernel/Theme/TwigIncludeTest.php +++ b/core/modules/system/tests/src/Kernel/Theme/TwigIncludeTest.php @@ -68,8 +68,10 @@ class TwigIncludeTest extends KernelTestBase { $twig_config = $this->container->getParameter('twig.config'); $twig_config['allowed_file_extensions'][] = 'sql'; $this->twigConfig = $twig_config; - $this->container->get('kernel')->shutdown(); - $this->container->get('kernel')->boot(); + // @todo This used to call shutdown() and boot(). rebuildContainer() is + // needed until we stop pushing the request twice and only popping it once. + // @see https://www.drupal.org/i/2613044 + $this->container->get('kernel')->rebuildContainer(); /** @var \Drupal\Core\Template\Loader\FilesystemLoader $loader */ $loader = \Drupal::service('twig.loader.filesystem'); $source = $loader->getSourceContext('@__main__\/core/tests/fixtures/files/sql-2.sql'); @@ -80,8 +82,10 @@ class TwigIncludeTest extends KernelTestBase { $this->assertSame(['css', 'html', 'js', 'svg', 'twig', 'sql'], \Drupal::getContainer()->getParameter('twig.config')['allowed_file_extensions']); unset($twig_config['allowed_file_extensions']); $this->twigConfig = $twig_config; - $this->container->get('kernel')->shutdown(); - $this->container->get('kernel')->boot(); + // @todo This used to call shutdown() and boot(). rebuildContainer() is + // needed until we stop pushing the request twice and only popping it once. + // @see https://www.drupal.org/i/2613044 + $this->container->get('kernel')->rebuildContainer(); $this->assertArrayNotHasKey('allowed_file_extensions', \Drupal::getContainer()->getParameter('twig.config')); /** @var \Drupal\Core\Template\Loader\FilesystemLoader $loader */ $loader = \Drupal::service('twig.loader.filesystem'); @@ -108,8 +112,10 @@ class TwigIncludeTest extends KernelTestBase { // Allow files with no extension. $twig_config['allowed_file_extensions'] = ['twig', '']; $this->twigConfig = $twig_config; - $this->container->get('kernel')->shutdown(); - $this->container->get('kernel')->boot(); + // @todo This used to call shutdown() and boot(). rebuildContainer() is + // needed until we stop pushing the request twice and only popping it once. + // @see https://www.drupal.org/i/2613044 + $this->container->get('kernel')->rebuildContainer(); /** @var \Drupal\Core\Template\Loader\FilesystemLoader $loader */ $loader = \Drupal::service('twig.loader.filesystem'); $source = $loader->getSourceContext('@__main__\/' . $this->siteDirectory . '/test_file'); diff --git a/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php b/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php index 516e3bd40c3..802190359b4 100644 --- a/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php +++ b/core/modules/system/tests/src/Kernel/Token/TokenReplaceKernelTest.php @@ -7,6 +7,8 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Xss; use Drupal\Core\Render\BubbleableMetadata; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests token replacement. @@ -137,6 +139,7 @@ class TokenReplaceKernelTest extends TokenReplaceKernelTestBase { 'SERVER_NAME' => 'http://localhost', ]; $request = Request::create('/subdir/', 'GET', [], [], [], $server); + $request->setSession(new Session(new MockArraySessionStorage())); $request->server->add($server); $request_stack->push($request); $bubbleable_metadata = new BubbleableMetadata(); diff --git a/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php b/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php index 897290b2877..d41a6dea939 100644 --- a/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php +++ b/core/modules/views/src/Tests/AssertViewsCacheTagsTrait.php @@ -6,6 +6,8 @@ use Drupal\Core\Cache\Cache; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\ViewExecutable; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; trait AssertViewsCacheTagsTrait { @@ -43,6 +45,7 @@ trait AssertViewsCacheTagsTrait { $request_stack = \Drupal::service('request_stack'); $request = Request::createFromGlobals(); $request->server->set('REQUEST_TIME', REQUEST_TIME); + $request->setSession(new Session(new MockArraySessionStorage())); $view->setRequest($request); $request_stack->push($request); $renderer->renderRoot($build); @@ -123,6 +126,7 @@ trait AssertViewsCacheTagsTrait { $request_stack = \Drupal::service('request_stack'); $request = new Request(); $request->server->set('REQUEST_TIME', REQUEST_TIME); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $renderer->renderRoot($build); diff --git a/core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php b/core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php index e3bbdfa5681..87a1afea800 100644 --- a/core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/AreaDisplayLinkTest.php @@ -15,6 +15,8 @@ use Prophecy\Argument; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests the core views_handler_area_display_link handler. @@ -148,8 +150,7 @@ class AreaDisplayLinkTest extends ViewsKernelTestBase { // Assert some special request parameters are filtered from the display // links. - $request_stack = new RequestStack(); - $request_stack->push(Request::create('page_1', 'GET', [ + $request = Request::create('page_1', 'GET', [ 'name' => 'John', 'sort_by' => 'created', 'sort_order' => 'ASC', @@ -166,7 +167,10 @@ class AreaDisplayLinkTest extends ViewsKernelTestBase { AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER => 1, FormBuilderInterface::AJAX_FORM_REQUEST => 1, MainContentViewSubscriber::WRAPPER_FORMAT => 1, - ])); + ]); + $request->setSession(new Session(new MockArraySessionStorage())); + $request_stack = new RequestStack(); + $request_stack->push($request); $this->container->set('request_stack', $request_stack); $view->destroy(); $view->setDisplay('page_1'); diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index e83b425dc42..f0035f4b1f4 100644 --- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -11,6 +11,7 @@ use Drupal\Tests\StreamCapturer; use Drupal\Tests\Traits\Core\CronRunTrait; use Drupal\user\Entity\Role; use PHPUnit\Framework\ExpectationFailedException; +use Symfony\Component\HttpFoundation\Request; /** * Tests BrowserTestBase functionality. @@ -521,6 +522,30 @@ class BrowserTestBaseTest extends BrowserTestBase { $this->assertSession()->statusCodeEquals(403); } + /** + * Tests that a usable session is on the request in test-runner. + */ + public function testSessionOnRequest(): void { + /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ + $session = $this->container->get('request_stack')->getSession(); + + $session->set('some-val', 'do-not-cleanup'); + $this->assertEquals('do-not-cleanup', $session->get('some-val')); + + $session->set('some-other-val', 'do-cleanup'); + $this->assertEquals('do-cleanup', $session->remove('some-other-val')); + } + + /** + * Tests deprecation of modified request stack lacking a session. + * + * @group legacy + */ + public function testDeprecatedSessionMissing(): void { + $this->expectDeprecation('Pushing requests without a session onto the request_stack is deprecated in drupal:10.3.0 and an error will be thrown from drupal:11.0.0. See https://www.drupal.org/node/3337193'); + $this->container->get('request_stack')->push(Request::create('/')); + } + /** * Tests that deprecation headers do not get duplicated. * diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php index 7cd1ae5682c..52c226c93ea 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerTestBase.php @@ -15,6 +15,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Base class for testing the interactive installer. @@ -118,6 +120,7 @@ abstract class InstallerTestBase extends BrowserTestBase { // server information so that XDebug works. // @see install_begin_request() $request = Request::create($GLOBALS['base_url'] . '/core/install.php', 'GET', [], $_COOKIE, [], $_SERVER); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container = new ContainerBuilder(); $request_stack = new RequestStack(); $request_stack->push($request); diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php index 42ff9e293aa..f941802c143 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php @@ -13,6 +13,8 @@ use Drupal\taxonomy\Entity\Term; use Drupal\taxonomy\Entity\Vocabulary; use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; // cspell:ignore merhaba siema xsiemax @@ -464,6 +466,7 @@ class EntityQueryTest extends EntityKernelTestBase { $request->query->replace([ 'page' => '0,2', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $this->queryResults = $this->storage ->getQuery() @@ -500,6 +503,7 @@ class EntityQueryTest extends EntityKernelTestBase { 'sort' => 'asc', 'order' => 'Type', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $header = [ diff --git a/core/tests/Drupal/KernelTests/Core/File/FileUrlGeneratorTest.php b/core/tests/Drupal/KernelTests/Core/File/FileUrlGeneratorTest.php index a4a004c825f..5359ee3fc56 100644 --- a/core/tests/Drupal/KernelTests/Core/File/FileUrlGeneratorTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/FileUrlGeneratorTest.php @@ -4,6 +4,8 @@ namespace Drupal\KernelTests\Core\File; use Drupal\Core\File\Exception\InvalidStreamWrapperException; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * @coversDefaultClass \Drupal\Core\File\FileUrlGenerator @@ -154,6 +156,7 @@ class FileUrlGeneratorTest extends FileTestBase { // Create a mock Request for transformRelative(). $request = Request::create($GLOBALS['base_url']); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); \Drupal::setContainer($this->container); @@ -183,6 +186,7 @@ class FileUrlGeneratorTest extends FileTestBase { // Create a mock Request for transformRelative(). $request = Request::create($GLOBALS['base_url']); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); \Drupal::setContainer($this->container); @@ -200,6 +204,7 @@ class FileUrlGeneratorTest extends FileTestBase { // Create a mock Request for transformRelative(). $request = Request::create($GLOBALS['base_url']); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container->get('request_stack')->push($request); \Drupal::setContainer($this->container); diff --git a/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php b/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php index 4a4d7e5a42b..c24bd75e3f5 100644 --- a/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/UrlTransformRelativeTest.php @@ -4,6 +4,8 @@ namespace Drupal\KernelTests\Core\File; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests URL transform to relative. @@ -35,6 +37,7 @@ class UrlTransformRelativeTest extends KernelTestBase { $_SERVER['HTTPS'] = $https; $request = Request::createFromGlobals(); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::requestStack()->push($request); $this->assertSame($expected, \Drupal::service('file_url_generator')->transformRelative($url, $root_relative)); diff --git a/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php b/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php index b2486202890..caa39c1cb72 100644 --- a/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php +++ b/core/tests/Drupal/KernelTests/Core/Form/ExternalFormUrlTest.php @@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\KernelTests\KernelTestBase; use Drupal\user\Entity\User; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Ensures that form actions can't be tricked into sending to external URLs. @@ -76,6 +78,7 @@ class ExternalFormUrlTest extends KernelTestBase implements FormInterface { $request_stack->pop(); $request_stack->pop(); $request = Request::create($original_request->getSchemeAndHttpHost() . '//example.org'); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $form = \Drupal::formBuilder()->getForm($this); @@ -91,6 +94,7 @@ class ExternalFormUrlTest extends KernelTestBase implements FormInterface { $request_stack = \Drupal::service('request_stack'); $original_request = $request_stack->pop(); $request = Request::create($original_request->getSchemeAndHttpHost() . '/example.org'); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $form = \Drupal::formBuilder()->getForm($this); diff --git a/core/tests/Drupal/KernelTests/Core/Form/FormActionXssTest.php b/core/tests/Drupal/KernelTests/Core/Form/FormActionXssTest.php index fc67b354e94..2cf6e10b909 100644 --- a/core/tests/Drupal/KernelTests/Core/Form/FormActionXssTest.php +++ b/core/tests/Drupal/KernelTests/Core/Form/FormActionXssTest.php @@ -7,6 +7,8 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\KernelTests\KernelTestBase; use Drupal\user\Entity\User; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; // cspell:ignore attribute\'close @@ -77,6 +79,7 @@ class FormActionXssTest extends KernelTestBase implements FormInterface { $request_stack->pop(); $request_stack->pop(); $request = Request::create($original_request->getSchemeAndHttpHost() . '/test/"injected=\'attribute\'close="'); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $form = \Drupal::formBuilder()->getForm($this); diff --git a/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php b/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php index 3624b76e35e..11faa4aeb4a 100644 --- a/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php +++ b/core/tests/Drupal/KernelTests/Core/Pager/PagerManagerTest.php @@ -4,6 +4,8 @@ namespace Drupal\KernelTests\Core\Pager; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * @group Pager @@ -22,6 +24,7 @@ class PagerManagerTest extends KernelTestBase { 'other' => 'arbitrary', ]; $request = Request::create('http://example.com', 'GET', $test_parameters); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = $this->container->get('request_stack'); @@ -43,6 +46,7 @@ class PagerManagerTest extends KernelTestBase { */ public function testFindPage() { $request = Request::create('http://example.com', 'GET', ['page' => '0,10']); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = $this->container->get('request_stack'); diff --git a/core/tests/Drupal/KernelTests/Core/Pager/RequestPagerTest.php b/core/tests/Drupal/KernelTests/Core/Pager/RequestPagerTest.php index b21f75bc6f0..598f68dbafe 100644 --- a/core/tests/Drupal/KernelTests/Core/Pager/RequestPagerTest.php +++ b/core/tests/Drupal/KernelTests/Core/Pager/RequestPagerTest.php @@ -4,6 +4,8 @@ namespace Drupal\KernelTests\Core\Pager; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * @group Pager @@ -17,6 +19,7 @@ class RequestPagerTest extends KernelTestBase { */ public function testFindPage() { $request = Request::create('http://example.com', 'GET', ['page' => '0,10']); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = $this->container->get('request_stack'); @@ -35,6 +38,7 @@ class RequestPagerTest extends KernelTestBase { 'other' => 'arbitrary', ]; $request = Request::create('http://example.com', 'GET', array_merge(['page' => '0,10'], $test_parameters)); + $request->setSession(new Session(new MockArraySessionStorage())); /** @var \Symfony\Component\HttpFoundation\RequestStack $request_stack */ $request_stack = $this->container->get('request_stack'); diff --git a/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php b/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php index 34a7bdf0006..588fecae8c5 100644 --- a/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php +++ b/core/tests/Drupal/KernelTests/Core/Path/PathValidatorTest.php @@ -55,10 +55,12 @@ class PathValidatorTest extends KernelTestBase { FALSE, ]; foreach ($methods as $method) { + /** @var \Symfony\Component\HttpFoundation\Request|null $request */ + $request = NULL; if ($method === FALSE) { $request_stack = $this->container->get('request_stack'); while ($request_stack->getCurrentRequest()) { - $request_stack->pop(); + $request = $request_stack->pop(); } $this->container->set('router.request_context', new RequestContext()); } @@ -69,6 +71,12 @@ class PathValidatorTest extends KernelTestBase { $this->assertEquals($method, $requestContext->getMethod()); $this->assertInstanceOf(Url::class, $url); $this->assertSame(['entity_test' => $entity->id()], $url->getRouteParameters()); + + if ($method === FALSE) { + // Restore main request. + $request_stack = $this->container->get('request_stack'); + $request_stack->push($request); + } } } diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/RequestPathTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/RequestPathTest.php index 5eb8c624ceb..8c8bc794252 100644 --- a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/RequestPathTest.php +++ b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/RequestPathTest.php @@ -7,6 +7,8 @@ use Drupal\KernelTests\KernelTestBase; use Drupal\system\Tests\Routing\MockAliasManager; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests system.module's request path condition. @@ -83,6 +85,7 @@ class RequestPathTest extends KernelTestBase { $pages = "/my/pass/page\r\n/my/pass/page2\r\n/foo"; $request = Request::create('/my/pass/page2'); + $request->setSession(new Session(new MockArraySessionStorage())); $this->requestStack->push($request); /** @var \Drupal\system\Plugin\Condition\RequestPath $condition */ diff --git a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ResponseStatusTest.php b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ResponseStatusTest.php index 9f5690a6bf3..33c407508e7 100644 --- a/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ResponseStatusTest.php +++ b/core/tests/Drupal/KernelTests/Core/Plugin/Condition/ResponseStatusTest.php @@ -9,6 +9,8 @@ use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Exception\HttpException; /** @@ -61,6 +63,7 @@ class ResponseStatusTest extends KernelTestBase { $request = new Request(); $request->attributes->set('exception', new HttpException($response_code)); } + $request->setSession(new Session(new MockArraySessionStorage())); $this->requestStack->push($request); /** @var \Drupal\system\Plugin\Condition\ResponseStatus $condition */ diff --git a/core/tests/Drupal/KernelTests/Core/Render/Element/TableSortExtenderTest.php b/core/tests/Drupal/KernelTests/Core/Render/Element/TableSortExtenderTest.php index b605b2111d4..c0bd45713a6 100644 --- a/core/tests/Drupal/KernelTests/Core/Render/Element/TableSortExtenderTest.php +++ b/core/tests/Drupal/KernelTests/Core/Render/Element/TableSortExtenderTest.php @@ -5,6 +5,8 @@ namespace Drupal\KernelTests\Core\Render\Element; use Drupal\Core\Utility\TableSort; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests table sorting. @@ -31,6 +33,7 @@ class TableSortExtenderTest extends KernelTestBase { ]; $request = Request::createFromGlobals(); $request->query->replace([]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $this->assertEquals($expected_ts, $ts, 'Simple table headers sorted correctly.'); @@ -43,6 +46,7 @@ class TableSortExtenderTest extends KernelTestBase { // headers are overridable. 'order' => 'bar', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $this->assertEquals($expected_ts, $ts, 'Simple table headers plus non-overriding $_GET parameters sorted correctly.'); @@ -56,6 +60,7 @@ class TableSortExtenderTest extends KernelTestBase { // it in the links that it creates. 'alpha' => 'beta', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $expected_ts['sort'] = 'desc'; $expected_ts['query'] = ['alpha' => 'beta']; @@ -83,6 +88,7 @@ class TableSortExtenderTest extends KernelTestBase { $request->query->replace([ 'order' => '2', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -101,6 +107,7 @@ class TableSortExtenderTest extends KernelTestBase { // exist. 'order' => 'bar', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -121,6 +128,7 @@ class TableSortExtenderTest extends KernelTestBase { // it in the links that it creates. 'alpha' => 'beta', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $expected_ts = [ 'name' => '1', @@ -165,6 +173,7 @@ class TableSortExtenderTest extends KernelTestBase { $request->query->replace([ 'order' => '1', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -181,6 +190,7 @@ class TableSortExtenderTest extends KernelTestBase { $request->query->replace([ 'order' => '2', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -197,6 +207,7 @@ class TableSortExtenderTest extends KernelTestBase { $request->query->replace([ 'order' => '3', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -213,6 +224,7 @@ class TableSortExtenderTest extends KernelTestBase { $request->query->replace([ 'order' => '4', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ @@ -229,6 +241,7 @@ class TableSortExtenderTest extends KernelTestBase { $request->query->replace([ 'order' => '5', ]); + $request->setSession(new Session(new MockArraySessionStorage())); \Drupal::getContainer()->get('request_stack')->push($request); $ts = TableSort::getContextFromRequest($headers, $request); $expected_ts = [ diff --git a/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteNoneTest.php b/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteNoneTest.php index 21e62d9680a..7e35066eeba 100644 --- a/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteNoneTest.php +++ b/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteNoneTest.php @@ -8,6 +8,8 @@ use Drupal\Core\Render\BubbleableMetadata; use Drupal\KernelTests\KernelTestBase; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -59,6 +61,7 @@ class RouteNoneTest extends KernelTestBase { $request = Request::create('/subdir', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -76,6 +79,7 @@ class RouteNoneTest extends KernelTestBase { $request = Request::create('/subdir/node/add', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'node.add'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/node/add')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -93,6 +97,7 @@ class RouteNoneTest extends KernelTestBase { $request = Request::create('/', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -110,6 +115,7 @@ class RouteNoneTest extends KernelTestBase { $request = Request::create('/node/add', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'node.add'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/node/add')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); diff --git a/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteProcessorCurrentIntegrationTest.php b/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteProcessorCurrentIntegrationTest.php index 1a99b00171f..1c585d8955d 100644 --- a/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteProcessorCurrentIntegrationTest.php +++ b/core/tests/Drupal/KernelTests/Core/RouteProcessor/RouteProcessorCurrentIntegrationTest.php @@ -8,6 +8,8 @@ use Drupal\Core\Render\BubbleableMetadata; use Drupal\KernelTests\KernelTestBase; use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\Routing\Route; /** @@ -60,6 +62,7 @@ class RouteProcessorCurrentIntegrationTest extends KernelTestBase { $request = Request::create('/subdir/', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -75,6 +78,7 @@ class RouteProcessorCurrentIntegrationTest extends KernelTestBase { $request = Request::create('/subdir/node/add', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'node.add'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/node/add')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -90,6 +94,7 @@ class RouteProcessorCurrentIntegrationTest extends KernelTestBase { $request = Request::create('/', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, ''); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -105,6 +110,7 @@ class RouteProcessorCurrentIntegrationTest extends KernelTestBase { $request = Request::create('/node/add', 'GET', [], [], [], $server); $request->attributes->set(RouteObjectInterface::ROUTE_NAME, 'node.add'); $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/node/add')); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); @@ -119,6 +125,7 @@ class RouteProcessorCurrentIntegrationTest extends KernelTestBase { 'SERVER_NAME' => 'http://www.example.com', ]; $request = Request::create('/invalid-path', 'GET', [], [], [], $server); + $request->setSession(new Session(new MockArraySessionStorage())); $request_stack->push($request); $request_context->fromRequest($request); diff --git a/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationStringTest.php b/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationStringTest.php index 77e37755f3c..b9544e82412 100644 --- a/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationStringTest.php +++ b/core/tests/Drupal/KernelTests/Core/StringTranslation/TranslationStringTest.php @@ -58,8 +58,10 @@ class TranslationStringTest extends KernelTestBase { // Reboot the container so that different services are injected and the new // settings are picked. $kernel = $this->container->get('kernel'); - $kernel->shutdown(); - $kernel->boot(); + // @todo This used to call shutdown() and boot(). rebuildContainer() is + // needed until we stop pushing the request twice and only popping it once. + // @see https://www.drupal.org/i/2613044 + $kernel->rebuildContainer(); $settings = Settings::getAll(); $settings['locale_custom_strings_de'] = ['' => ['Example @number' => 'Example @number translated']]; // Recreate the settings static. diff --git a/core/tests/Drupal/KernelTests/Core/Theme/ImageTest.php b/core/tests/Drupal/KernelTests/Core/Theme/ImageTest.php index 509b6dea77f..c5b6336e5e8 100644 --- a/core/tests/Drupal/KernelTests/Core/Theme/ImageTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/ImageTest.php @@ -4,6 +4,8 @@ namespace Drupal\KernelTests\Core\Theme; use Drupal\KernelTests\KernelTestBase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Tests built-in image theme functions. @@ -43,6 +45,7 @@ class ImageTest extends KernelTestBase { // the Request containing the correct hostname. KernelTestBase doesn't set // it, so push another request onto the stack to ensure it's correct. $request = Request::create('/', 'GET', [], [], [], $_SERVER); + $request->setSession(new Session(new MockArraySessionStorage())); $this->container = \Drupal::service('kernel')->getContainer(); $this->container->get('request_stack')->push($request); diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index 46b4d880189..0a07f19c064 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -37,6 +37,7 @@ use Drupal\Core\Routing\RouteObjectInterface; use Symfony\Component\Routing\Route; use Symfony\Component\VarDumper\VarDumper; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; /** * Base class for functional integration tests. @@ -667,6 +668,19 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa * {@inheritdoc} */ protected function tearDown(): void { + if ($this->container) { + // Clean up mock session started in DrupalKernel::preHandle(). + try { + /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ + $session = $this->container->get('request_stack')->getSession(); + $session->clear(); + $session->save(); + } + catch (SessionNotFoundException) { + @trigger_error('Pushing requests without a session onto the request_stack is deprecated in drupal:10.3.0 and an error will be thrown from drupal:11.0.0. See https://www.drupal.org/node/3337193', E_USER_DEPRECATED); + } + } + // Destroy the testing kernel. if (isset($this->kernel)) { $this->kernel->shutdown(); diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php index 689cf8b953e..be83c0a2672 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php +++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php @@ -11,6 +11,7 @@ use Drupal\user\Entity\Role; use org\bovigo\vfs\vfsStream; use org\bovigo\vfs\visitor\vfsStreamStructureVisitor; use PHPUnit\Framework\SkippedTestError; +use Symfony\Component\HttpFoundation\Request; /** * @coversDefaultClass \Drupal\KernelTests\KernelTestBase @@ -235,6 +236,34 @@ class KernelTestBaseTest extends KernelTestBase { $this->assertEquals('public', \Drupal::config('system.file')->get('default_scheme')); } + /** + * Tests that a usable session is on the request. + * + * @covers ::bootKernel + */ + public function testSessionOnRequest(): void { + /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ + $session = $this->container->get('request_stack')->getSession(); + + $session->set('some-val', 'do-not-cleanup'); + $this->assertEquals('do-not-cleanup', $session->get('some-val')); + + $session->set('some-other-val', 'do-cleanup'); + $this->assertEquals('do-cleanup', $session->remove('some-other-val')); + } + + /** + * Tests deprecation of modified request stack lacking a session. + * + * @covers ::tearDown + * + * @group legacy + */ + public function testDeprecatedSessionMissing(): void { + $this->expectDeprecation('Pushing requests without a session onto the request_stack is deprecated in drupal:10.3.0 and an error will be thrown from drupal:11.0.0. See https://www.drupal.org/node/3337193'); + $this->container->get('request_stack')->push(Request::create('/')); + } + /** * Tests the assumption that local time is in 'Australia/Sydney'. */ diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index 38b41f4163d..082292646ee 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -24,6 +24,7 @@ use Drupal\TestTools\TestVarDumper; use GuzzleHttp\Cookie\CookieJar; use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; +use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; use Symfony\Component\VarDumper\VarDumper; /** @@ -446,6 +447,19 @@ abstract class BrowserTestBase extends TestCase { protected function tearDown(): void { parent::tearDown(); + if ($this->container) { + // Cleanup mock session started in DrupalKernel::preHandle(). + try { + /** @var \Symfony\Component\HttpFoundation\Session\Session $session */ + $session = $this->container->get('request_stack')->getSession(); + $session->clear(); + $session->save(); + } + catch (SessionNotFoundException) { + @trigger_error('Pushing requests without a session onto the request_stack is deprecated in drupal:10.3.0 and an error will be thrown from drupal:11.0.0. See https://www.drupal.org/node/3337193', E_USER_DEPRECATED); + } + } + // Destroy the testing kernel. if (isset($this->kernel)) { $this->cleanupEnvironment();