diff --git a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php index 1df7ccf99c..a6915b49b8 100644 --- a/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php +++ b/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php @@ -271,7 +271,19 @@ protected function prepareRequestForGenerator($clean_urls = TRUE, $override_serv } $server = array_merge($server, $override_server_vars); + // Fetch session from existing request. + /** @var \Symfony\Component\HttpFoundation\Request $previous */ + $previous = $this->container->get('request_stack')->getCurrentRequest(); + if ($previous && $previous->hasSession()) { + $session = $previous->getSession(); + } + else { + @trigger_error('Failed to retrieve session from current request, request stack was modified during test.', E_USER_ERROR); + $session = $this->container->get('session'); + } + $request = Request::create($request_path, 'GET', [], [], [], $server); + $request->setSession($session); // 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); @@ -685,6 +697,24 @@ protected function prepareEnvironment() { $callbacks = []; } + /** + * Prepare the session and add it to the request. + */ + protected function prepareSession(ContainerInterface $container) { + // Disable session writing. + //** @var \Drupal\Core\Session\WriteSafeSessionHandlerInterface $writeSafeHandler*/ + $writeSafeHandler = $container->get('session_handler.write_safe'); + $writeSafeHandler->setSessionWritable(FALSE); + + /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ + $session = $container->get('session'); + $session->start(); + + /** @var \Symfony\Component\HttpFoundation\Request $request */ + $request = $container->get('request_stack')->getCurrentRequest(); + $request->setSession($session); + } + /** * Returns all supported database driver installer objects. * diff --git a/core/modules/comment/tests/src/Kernel/CommentDefaultFormatterCacheTagsTest.php b/core/modules/comment/tests/src/Kernel/CommentDefaultFormatterCacheTagsTest.php index e681a4d9ad..8a4d3e0bed 100644 --- a/core/modules/comment/tests/src/Kernel/CommentDefaultFormatterCacheTagsTest.php +++ b/core/modules/comment/tests/src/Kernel/CommentDefaultFormatterCacheTagsTest.php @@ -34,7 +34,7 @@ class CommentDefaultFormatterCacheTagsTest extends EntityKernelTestBase { protected function setUp() { parent::setUp(); - $session = new Session(); + $session = $this->container->get('session'); $request = Request::create('/'); $request->setSession($session); diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index b8247ea88f..a580157043 100644 --- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -743,6 +743,25 @@ public function testEscapingAssertions() { $assert->assertNoEscaped(""); } + /** + * Tests that a usable session is on the request in test-runner. + */ + public function testSessionOnRequest() { + /** @var \Symfony\Component\HttpFoundation\Request $request */ + $request = $this->container->get('request_stack')->getCurrentRequest(); + + // Verify that a usable session is available from the request. + /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ + $session = $request->getSession(); + $this->assertNotNull($session); + + $session->set('some-val', 'do-not-cleanup'); + $this->assertEqual('do-not-cleanup', $session->get('some-val')); + + $session->set('some-other-val', 'do-cleanup'); + $this->assertEqual('do-cleanup', $session->remove('some-other-val')); + } + /** * Tests that deprecation headers do not get duplicated. * diff --git a/core/tests/Drupal/KernelTests/Core/Database/ReplicaKillSwitchTest.php b/core/tests/Drupal/KernelTests/Core/Database/ReplicaKillSwitchTest.php index b2cdf72407..f9fb3d59e0 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/ReplicaKillSwitchTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/ReplicaKillSwitchTest.php @@ -6,7 +6,6 @@ use Drupal\Core\DrupalKernel; use Drupal\Core\Site\Settings; use Drupal\KernelTests\KernelTestBase; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -32,7 +31,7 @@ public function testSystemInitIgnoresSecondaries() { $service->trigger(); $class_loader = require $this->root . '/autoload.php'; $kernel = new DrupalKernel('testing', $class_loader, FALSE); - $event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST); + $event = new GetResponseEvent($kernel, \Drupal::request(), HttpKernelInterface::MASTER_REQUEST); $service->checkReplicaServer($event); $db1 = Database::getConnection('default', 'default'); diff --git a/core/tests/Drupal/KernelTests/Core/Session/MockSessionManager.php b/core/tests/Drupal/KernelTests/Core/Session/MockSessionManager.php new file mode 100644 index 0000000000..97204c99bf --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Session/MockSessionManager.php @@ -0,0 +1,139 @@ +storage = new MockArraySessionStorage('MOCKSESSID', $metadata_bag); + } + + /** + * {@inheritdoc} + */ + public function start() { + return $this->storage->start(); + } + + /** + * {@inheritdoc} + */ + public function isStarted() { + return $this->storage->isStarted(); + } + + /** + * {@inheritdoc} + */ + public function getId() { + return $this->storage->getId(); + } + + /** + * {@inheritdoc} + */ + public function setId($id) { + return $this->storage->setId($id); + } + + /** + * {@inheritdoc} + */ + public function getName() { + return $this->storage->getName(); + } + + /** + * {@inheritdoc} + */ + public function setName($name) { + $this->storage->setName($name); + } + + /** + * {@inheritdoc} + */ + public function regenerate($destroy = FALSE, $lifetime = NULL) { + $this->storage->regenerate($destroy, $lifetime); + } + + /** + * {@inheritdoc} + */ + public function save() { + $this->storage->save(); + } + + /** + * {@inheritdoc} + */ + public function clear() { + $this->storage->clear(); + } + + /** + * {@inheritdoc} + */ + public function getBag($name) { + return $this->storage->getBag($name); + } + + /** + * {@inheritdoc} + */ + public function registerBag(SessionBagInterface $bag) { + $this->storage->registerBag($bag); + } + + /** + * {@inheritdoc} + */ + public function getMetadataBag() { + return $this->storage->getMetadataBag(); + } + + /** + * {@inheritdoc} + */ + public function delete($uid) { + // Ignored. + } + + /** + * {@inheritdoc} + */ + public function destroy() { + @trigger_error(__METHOD__ . ' not implemented in MockSessionManager', E_USER_ERROR); + } + + /** + * {@inheritdoc} + */ + public function setWriteSafeHandler(WriteSafeSessionHandlerInterface $handler) { + @trigger_error(__METHOD__ . ' not implemented in MockSessionManager', E_USER_ERROR); + } + +} diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index a9999936a0..7d4a1d7565 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -360,6 +360,12 @@ private function bootKernel() { $this->container = $kernel->getContainer(); + // Prepare session and add it to the request. + /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ + $session = $this->container->get('session'); + $session->start(); + $request->setSession($session); + // Ensure database tasks have been run. require_once __DIR__ . '/../../../includes/install.inc'; $connection = Database::getConnection(); @@ -535,6 +541,11 @@ public function register(ContainerBuilder $container) { ->addTag('persist'); $container ->setAlias('keyvalue', 'keyvalue.memory'); + $container + ->register('session_manager.memory', 'Drupal\KernelTests\Core\Session\MockSessionManager') + ->addArgument(new Reference('session_manager.metadata_bag')); + $container + ->setAlias('session_manager', 'session_manager.memory'); // Set the default language on the minimal container. $container->setParameter('language.default_values', Language::$defaultValues); diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php index 426fa8bb27..61addd66a3 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php +++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php @@ -142,6 +142,19 @@ public function testRegister() { // Ensure getting the router.route_provider does not trigger a deprecation // message that errors. $this->container->get('router.route_provider'); + + // Verify that a usable session is available from the request. + /** @var \Symfony\Component\HttpFoundation\Session\SessionInterface $session */ + $session = $request->getSession(); + + $this->assertNotNull($session); + $this->assertTrue($session->isStarted()); + + $session->set('some-val', 'do-not-cleanup'); + $this->assertEqual('do-not-cleanup', $session->get('some-val')); + + $session->set('some-other-val', 'do-cleanup'); + $this->assertEqual('do-cleanup', $session->remove('some-other-val')); } /** diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index 4845bf86bd..0c8979cc09 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -455,6 +455,24 @@ protected function cleanupEnvironment() { \Drupal::service('file_system')->deleteRecursive($this->siteDirectory, [$this, 'filePreDeleteCallback']); } + /** + * Clear and stop a session triggered during test run. + */ + protected function cleanupSession() { + /** @var \Symfony\Component\HttpFoundation\Request $request */ + $request = $this->container->get('request_stack')->getCurrentRequest(); + if ($request && $request->hasSession()) { + $session = $request->getSession(); + } + else { + @trigger_error('Failed to retrieve session from current request, request stack was modified during test.', E_USER_ERROR); + $session = $this->container->get('session'); + } + + $session->clear(); + $session->save(); + } + /** * {@inheritdoc} */ @@ -463,6 +481,7 @@ protected function tearDown() { // Destroy the testing kernel. if (isset($this->kernel)) { + $this->cleanupSession(); $this->cleanupEnvironment(); $this->kernel->shutdown(); } @@ -569,6 +588,7 @@ public function installDrupal() { $this->doInstall(); $this->initSettings(); $container = $this->initKernel(\Drupal::request()); + $this->prepareSession($container); $this->initConfig($container); $this->installDefaultThemeFromClassProperty($container); $this->installModulesFromClassProperty($container);