From 3ddfcf58c5d73b4db502c353463083114ab13ff7 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Mon, 3 Oct 2022 15:39:53 +0100
Subject: [PATCH] Issue #3293446 by alexpott, daffie: Create less static cache
 in ExtensionDiscovery during KernelTests

---
 core/lib/Drupal/Core/Database/Database.php    | 16 +++++++++---
 core/lib/Drupal/Core/Test/TestSetupTrait.php  |  2 +-
 core/scripts/run-tests.sh                     |  2 +-
 .../Drupal/KernelTests/KernelTestBase.php     |  2 +-
 .../Tests/Core/Database/DatabaseTest.php      | 16 +++++-------
 .../Tests/Core/Database/UrlConversionTest.php | 25 +++++++++++++------
 6 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/core/lib/Drupal/Core/Database/Database.php b/core/lib/Drupal/Core/Database/Database.php
index 3198bccd46b2..9b5364942b8a 100644
--- a/core/lib/Drupal/Core/Database/Database.php
+++ b/core/lib/Drupal/Core/Database/Database.php
@@ -504,6 +504,10 @@ public static function ignoreTarget($key, $target) {
    *   The URL.
    * @param string $root
    *   The root directory of the Drupal installation.
+   * @param bool|null $include_test_drivers
+   *   (optional) Whether to include test extensions. If FALSE, all 'tests'
+   *   directories are excluded in the search. When NULL will be determined by
+   *   the extension_discovery_scan_tests setting.
    *
    * @return array
    *   The database connection info.
@@ -514,7 +518,7 @@ public static function ignoreTarget($key, $target) {
    * @throws \RuntimeException
    *   Exception thrown when a module provided database driver does not exist.
    */
-  public static function convertDbUrlToConnectionInfo($url, $root) {
+  public static function convertDbUrlToConnectionInfo($url, $root, ?bool $include_test_drivers = NULL) {
     // Check that the URL is well formed, starting with 'scheme://', where
     // 'scheme' is a database driver name.
     if (preg_match('/^(.*):\/\//', $url, $matches) !== 1) {
@@ -543,7 +547,7 @@ public static function convertDbUrlToConnectionInfo($url, $root) {
       // this method can be called before Drupal is installed and is never
       // called during regular runtime.
       $namespace = "Drupal\\$module\\Driver\\Database\\$driver";
-      $psr4_base_directory = Database::findDriverAutoloadDirectory($namespace, $root, TRUE);
+      $psr4_base_directory = Database::findDriverAutoloadDirectory($namespace, $root, $include_test_drivers);
       $additional_class_loader = new ClassLoader();
       $additional_class_loader->addPsr4($namespace . '\\', $psr4_base_directory);
       $additional_class_loader->register(TRUE);
@@ -615,6 +619,10 @@ public static function convertDbUrlToConnectionInfo($url, $root) {
    *   The database driver's namespace.
    * @param string $root
    *   The root directory of the Drupal installation.
+   * @param bool|null $include_test_drivers
+   *   (optional) Whether to include test extensions. If FALSE, all 'tests'
+   *   directories are excluded in the search. When NULL will be determined by
+   *   the extension_discovery_scan_tests setting.
    *
    * @return string|false
    *   The PSR-4 directory to add to the autoloader for the namespace if the
@@ -624,7 +632,7 @@ public static function convertDbUrlToConnectionInfo($url, $root) {
    * @throws \RuntimeException
    *   Exception thrown when a module provided database driver does not exist.
    */
-  public static function findDriverAutoloadDirectory($namespace, $root) {
+  public static function findDriverAutoloadDirectory($namespace, $root, ?bool $include_test_drivers = NULL) {
     // As explained by this method's documentation, return FALSE if the
     // namespace is not a sub-namespace of a Drupal module.
     if (!static::isWithinModuleNamespace($namespace)) {
@@ -637,7 +645,7 @@ public static function findDriverAutoloadDirectory($namespace, $root) {
     // The namespace is within a Drupal module. Find the directory where the
     // module is located.
     $extension_discovery = new ExtensionDiscovery($root, FALSE, []);
-    $modules = $extension_discovery->scan('module');
+    $modules = $extension_discovery->scan('module', $include_test_drivers);
     if (!isset($modules[$module])) {
       throw new \RuntimeException(sprintf("Cannot find the module '%s' for the database driver namespace '%s'", $module, $namespace));
     }
diff --git a/core/lib/Drupal/Core/Test/TestSetupTrait.php b/core/lib/Drupal/Core/Test/TestSetupTrait.php
index 52d640094f5d..457966323dbb 100644
--- a/core/lib/Drupal/Core/Test/TestSetupTrait.php
+++ b/core/lib/Drupal/Core/Test/TestSetupTrait.php
@@ -164,7 +164,7 @@ protected function changeDatabasePrefix() {
       // Ensure no existing database gets in the way. If a default database
       // exists already it must be removed.
       Database::removeConnection('default');
-      $database = Database::convertDbUrlToConnectionInfo($db_url, $this->root ?? DRUPAL_ROOT);
+      $database = Database::convertDbUrlToConnectionInfo($db_url, $this->root ?? DRUPAL_ROOT, TRUE);
       Database::addConnectionInfo('default', 'default', $database);
     }
 
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 7daf364cef34..2174a5e8522a 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -604,7 +604,7 @@ function simpletest_script_setup_database($new = FALSE) {
     // Remove a possibly existing default connection (from settings.php).
     Database::removeConnection('default');
     try {
-      $databases['default']['default'] = Database::convertDbUrlToConnectionInfo($args['dburl'], DRUPAL_ROOT);
+      $databases['default']['default'] = Database::convertDbUrlToConnectionInfo($args['dburl'], DRUPAL_ROOT, TRUE);
     }
     catch (\InvalidArgumentException $e) {
       simpletest_script_print_error('Invalid --dburl. Reason: ' . $e->getMessage());
diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php
index fe9996d4da6c..eab4a431aa08 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBase.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBase.php
@@ -453,7 +453,7 @@ protected function getDatabaseConnectionInfo() {
       throw new \Exception('There is no database connection so no tests can be run. You must provide a SIMPLETEST_DB environment variable to run PHPUnit based functional tests outside of run-tests.sh. See https://www.drupal.org/node/2116263#skipped-tests for more information.');
     }
     else {
-      $database = Database::convertDbUrlToConnectionInfo($db_url, $this->root);
+      $database = Database::convertDbUrlToConnectionInfo($db_url, $this->root, TRUE);
       Database::addConnectionInfo('default', 'default', $database);
     }
 
diff --git a/core/tests/Drupal/Tests/Core/Database/DatabaseTest.php b/core/tests/Drupal/Tests/Core/Database/DatabaseTest.php
index 1eb469399fd0..bf61c2467c3e 100644
--- a/core/tests/Drupal/Tests/Core/Database/DatabaseTest.php
+++ b/core/tests/Drupal/Tests/Core/Database/DatabaseTest.php
@@ -4,7 +4,6 @@
 
 use Composer\Autoload\ClassLoader;
 use Drupal\Core\Database\Database;
-use Drupal\Core\Site\Settings;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -57,10 +56,8 @@ protected function setUp(): void {
    * @covers ::findDriverAutoloadDirectory
    * @dataProvider providerFindDriverAutoloadDirectory
    */
-  public function testFindDriverAutoloadDirectory($expected, $namespace) {
-    new Settings(['extension_discovery_scan_tests' => TRUE]);
-    // The only module that provides a driver in core is a test module.
-    $this->assertSame($expected, Database::findDriverAutoloadDirectory($namespace, $this->root));
+  public function testFindDriverAutoloadDirectory($expected, $namespace, $include_test_drivers) {
+    $this->assertSame($expected, Database::findDriverAutoloadDirectory($namespace, $this->root, $include_test_drivers));
   }
 
   /**
@@ -70,9 +67,9 @@ public function testFindDriverAutoloadDirectory($expected, $namespace) {
    */
   public function providerFindDriverAutoloadDirectory() {
     return [
-      'core mysql' => ['core/modules/mysql/src/Driver/Database/mysql/', 'Drupal\mysql\Driver\Database\mysql'],
-      'D8 custom fake' => [FALSE, 'Drupal\Driver\Database\corefake'],
-      'module mysql' => ['core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestMysql/', 'Drupal\driver_test\Driver\Database\DrivertestMysql'],
+      'core mysql' => ['core/modules/mysql/src/Driver/Database/mysql/', 'Drupal\mysql\Driver\Database\mysql', FALSE],
+      'D8 custom fake' => [FALSE, 'Drupal\Driver\Database\corefake', TRUE],
+      'module mysql' => ['core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestMysql/', 'Drupal\driver_test\Driver\Database\DrivertestMysql', TRUE],
     ];
   }
 
@@ -81,10 +78,9 @@ public function providerFindDriverAutoloadDirectory() {
    * @dataProvider providerFindDriverAutoloadDirectoryException
    */
   public function testFindDriverAutoloadDirectoryException($expected_message, $namespace, $include_tests) {
-    new Settings(['extension_discovery_scan_tests' => $include_tests]);
     $this->expectException(\RuntimeException::class);
     $this->expectExceptionMessage($expected_message);
-    Database::findDriverAutoloadDirectory($namespace, $this->root);
+    Database::findDriverAutoloadDirectory($namespace, $this->root, $include_tests);
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php b/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php
index fb1c9dde8df2..2e836da87c36 100644
--- a/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php
+++ b/core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php
@@ -3,7 +3,6 @@
 namespace Drupal\Tests\Core\Database;
 
 use Drupal\Core\Database\Database;
-use Drupal\Core\Site\Settings;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -39,8 +38,6 @@ protected function setUp(): void {
       ->with('site.path')
       ->willReturn('');
     \Drupal::setContainer($container);
-
-    new Settings(['extension_discovery_scan_tests' => TRUE]);
   }
 
   /**
@@ -48,8 +45,8 @@ protected function setUp(): void {
    *
    * @dataProvider providerConvertDbUrlToConnectionInfo
    */
-  public function testDbUrlToConnectionConversion($url, $database_array) {
-    $result = Database::convertDbUrlToConnectionInfo($url, $this->root);
+  public function testDbUrlToConnectionConversion($url, $database_array, $include_test_drivers) {
+    $result = Database::convertDbUrlToConnectionInfo($url, $this->root, $include_test_drivers);
     $this->assertEquals($database_array, $result);
   }
 
@@ -76,6 +73,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\mysql\Driver\Database\mysql',
           'autoload' => 'core/modules/mysql/src/Driver/Database/mysql/',
         ],
+        FALSE,
       ],
       'SQLite, relative to root, without prefix' => [
         'sqlite://localhost/test_database',
@@ -86,6 +84,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\sqlite\Driver\Database\sqlite',
           'autoload' => 'core/modules/sqlite/src/Driver/Database/sqlite/',
         ],
+        FALSE,
       ],
       'MySql with prefix' => [
         'mysql://test_user:test_pass@test_host:3306/test_database#bar',
@@ -100,6 +99,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\mysql\Driver\Database\mysql',
           'autoload' => 'core/modules/mysql/src/Driver/Database/mysql/',
         ],
+        FALSE,
       ],
       'SQLite, relative to root, with prefix' => [
         'sqlite://localhost/test_database#foo',
@@ -111,6 +111,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\sqlite\Driver\Database\sqlite',
           'autoload' => 'core/modules/sqlite/src/Driver/Database/sqlite/',
         ],
+        FALSE,
       ],
       'SQLite, absolute path, without prefix' => [
         'sqlite://localhost//baz/test_database',
@@ -121,6 +122,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\sqlite\Driver\Database\sqlite',
           'autoload' => 'core/modules/sqlite/src/Driver/Database/sqlite/',
         ],
+        FALSE,
       ],
       'MySQL contrib test driver without prefix' => [
         'DrivertestMysql://test_user:test_pass@test_host:3306/test_database?module=driver_test',
@@ -134,6 +136,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\driver_test\Driver\Database\DrivertestMysql',
           'autoload' => 'core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestMysql/',
         ],
+        TRUE,
       ],
       'MySQL contrib test driver with prefix' => [
         'DrivertestMysql://test_user:test_pass@test_host:3306/test_database?module=driver_test#bar',
@@ -148,6 +151,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\driver_test\Driver\Database\DrivertestMysql',
           'autoload' => 'core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestMysql/',
         ],
+        TRUE,
       ],
       'PostgreSQL contrib test driver without prefix' => [
         'DrivertestPgsql://test_user:test_pass@test_host:5432/test_database?module=driver_test',
@@ -161,6 +165,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\driver_test\Driver\Database\DrivertestPgsql',
           'autoload' => 'core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestPgsql/',
         ],
+        TRUE,
       ],
       'PostgreSQL contrib test driver with prefix' => [
         'DrivertestPgsql://test_user:test_pass@test_host:5432/test_database?module=driver_test#bar',
@@ -175,6 +180,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\driver_test\Driver\Database\DrivertestPgsql',
           'autoload' => 'core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestPgsql/',
         ],
+        TRUE,
       ],
       'MySql with a custom query parameter' => [
         'mysql://test_user:test_pass@test_host:3306/test_database?extra=value',
@@ -188,6 +194,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\mysql\Driver\Database\mysql',
           'autoload' => 'core/modules/mysql/src/Driver/Database/mysql/',
         ],
+        FALSE,
       ],
       'MySql with the module name mysql' => [
         'mysql://test_user:test_pass@test_host:3306/test_database?module=mysql',
@@ -201,6 +208,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\mysql\Driver\Database\mysql',
           'autoload' => 'core/modules/mysql/src/Driver/Database/mysql/',
         ],
+        FALSE,
       ],
       'PostgreSql without the module name set' => [
         'pgsql://test_user:test_pass@test_host/test_database',
@@ -213,6 +221,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\pgsql\Driver\Database\pgsql',
           'autoload' => 'core/modules/pgsql/src/Driver/Database/pgsql/',
         ],
+        FALSE,
       ],
       'PostgreSql with the module name pgsql' => [
         'pgsql://test_user:test_pass@test_host/test_database?module=pgsql',
@@ -225,6 +234,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\pgsql\Driver\Database\pgsql',
           'autoload' => 'core/modules/pgsql/src/Driver/Database/pgsql/',
         ],
+        FALSE,
       ],
       'SQLite, relative to root, without prefix and with the module name sqlite' => [
         'sqlite://localhost/test_database?module=sqlite',
@@ -235,6 +245,7 @@ public function providerConvertDbUrlToConnectionInfo() {
           'namespace' => 'Drupal\sqlite\Driver\Database\sqlite',
           'autoload' => 'core/modules/sqlite/src/Driver/Database/sqlite/',
         ],
+        FALSE,
       ],
     ];
   }
@@ -439,7 +450,7 @@ public function testDriverModuleDoesNotExist() {
     $url = 'mysql://test_user:test_pass@test_host:3306/test_database?module=does_not_exist';
     $this->expectException(\RuntimeException::class);
     $this->expectExceptionMessage("Cannot find the module 'does_not_exist' for the database driver namespace 'Drupal\does_not_exist\Driver\Database\mysql'");
-    Database::convertDbUrlToConnectionInfo($url, $this->root);
+    Database::convertDbUrlToConnectionInfo($url, $this->root, TRUE);
   }
 
   /**
@@ -449,7 +460,7 @@ public function testModuleDriverDoesNotExist() {
     $url = 'mysql://test_user:test_pass@test_host:3306/test_database?module=driver_test';
     $this->expectException(\RuntimeException::class);
     $this->expectExceptionMessage("Cannot find the database driver namespace 'Drupal\driver_test\Driver\Database\mysql' in module 'driver_test'");
-    Database::convertDbUrlToConnectionInfo($url, $this->root);
+    Database::convertDbUrlToConnectionInfo($url, $this->root, TRUE);
   }
 
 }
-- 
GitLab