From f4ef94ae70bb153fd08bca116c56c2b1e26e0c3c Mon Sep 17 00:00:00 2001
From: Lee Rowlands <lee.rowlands@previousnext.com.au>
Date: Fri, 1 Mar 2019 06:44:06 +1000
Subject: [PATCH] Issue #2975081 by alexpott, amateescu, larowlan, mtodor,
 catch: UpdatePathTestBase fails to re-initialize the test site (rebuild
 container, clear caches) after running the database updates

---
 .../BlockConditionMissingSchemaUpdateTest.php | 11 ----
 .../src/Functional/Update/FieldUpdateTest.php | 18 +++----
 .../drupal-8.responsive_image-enabled.php     | 46 +++++++++++++++++
 .../Update/ResponsiveImageUpdateTest.php      | 19 +------
 .../update_test_schema.install                | 16 ++++++
 .../EntityUpdateAddRevisionDefaultTest.php    | 15 ++----
 ...dateAddRevisionTranslationAffectedTest.php | 15 ++----
 .../Update/UpdatePathTestBase.php             | 36 +++++++++++--
 .../Update/UpdatePathTestBaseTest.php         | 51 +++++++++++++++++++
 9 files changed, 160 insertions(+), 67 deletions(-)
 create mode 100644 core/modules/responsive_image/tests/fixtures/update/drupal-8.responsive_image-enabled.php

diff --git a/core/modules/block/tests/src/Functional/Update/BlockConditionMissingSchemaUpdateTest.php b/core/modules/block/tests/src/Functional/Update/BlockConditionMissingSchemaUpdateTest.php
index 79c3beaacf1f..751dd54170a6 100644
--- a/core/modules/block/tests/src/Functional/Update/BlockConditionMissingSchemaUpdateTest.php
+++ b/core/modules/block/tests/src/Functional/Update/BlockConditionMissingSchemaUpdateTest.php
@@ -14,17 +14,6 @@
  */
 class BlockConditionMissingSchemaUpdateTest extends UpdatePathTestBase {
 
-  /**
-   * This test does not have a failed update but the configuration has missing
-   * schema so can not do the full post update testing offered by
-   * UpdatePathTestBase.
-   *
-   * @var bool
-   *
-   * @see \Drupal\system\Tests\Update\UpdatePathTestBase::runUpdates()
-   */
-  protected $checkFailedUpdates = FALSE;
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/field/tests/src/Functional/Update/FieldUpdateTest.php b/core/modules/field/tests/src/Functional/Update/FieldUpdateTest.php
index 67c72dc58765..bec6e96546ac 100644
--- a/core/modules/field/tests/src/Functional/Update/FieldUpdateTest.php
+++ b/core/modules/field/tests/src/Functional/Update/FieldUpdateTest.php
@@ -48,13 +48,6 @@ class FieldUpdateTest extends UpdatePathTestBase {
    */
   protected $state;
 
-  /**
-   * The deleted fields repository.
-   *
-   * @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface
-   */
-  protected $deletedFieldsRepository;
-
   /**
    * {@inheritdoc}
    */
@@ -65,7 +58,6 @@ protected function setUp() {
     $this->database = $this->container->get('database');
     $this->installedStorageSchema = $this->container->get('keyvalue')->get('entity.storage_schema.sql');
     $this->state = $this->container->get('state');
-    $this->deletedFieldsRepository = $this->container->get('entity_field.deleted_fields_repository');
   }
 
   /**
@@ -193,16 +185,18 @@ public function testFieldUpdate8500() {
     // Run updates.
     $this->runUpdates();
 
+    $deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
+
     // Now that we can use the API, check that the "delete fields" state entries
     // have been converted to proper field definition objects.
-    $deleted_fields = $this->deletedFieldsRepository->getFieldDefinitions();
+    $deleted_fields = $deleted_fields_repository->getFieldDefinitions();
 
     $this->assertCount(1, $deleted_fields);
     $this->assertArrayHasKey($field_uuid, $deleted_fields);
     $this->assertTrue($deleted_fields[$field_uuid] instanceof FieldDefinitionInterface);
     $this->assertEquals($field_name, $deleted_fields[$field_uuid]->getName());
 
-    $deleted_field_storages = $this->deletedFieldsRepository->getFieldStorageDefinitions();
+    $deleted_field_storages = $deleted_fields_repository->getFieldStorageDefinitions();
     $this->assertCount(1, $deleted_field_storages);
     $this->assertArrayHasKey($field_storage_uuid, $deleted_field_storages);
     $this->assertTrue($deleted_field_storages[$field_storage_uuid] instanceof FieldStorageDefinitionInterface);
@@ -223,10 +217,10 @@ public function testFieldUpdate8500() {
     // Run cron and repeat the checks above.
     $this->cronRun();
 
-    $deleted_fields = $this->deletedFieldsRepository->getFieldDefinitions();
+    $deleted_fields = $deleted_fields_repository->getFieldDefinitions();
     $this->assertCount(0, $deleted_fields);
 
-    $deleted_field_storages = $this->deletedFieldsRepository->getFieldStorageDefinitions();
+    $deleted_field_storages = $deleted_fields_repository->getFieldStorageDefinitions();
     $this->assertCount(0, $deleted_field_storages);
 
     // Check that the installed storage schema has been deleted.
diff --git a/core/modules/responsive_image/tests/fixtures/update/drupal-8.responsive_image-enabled.php b/core/modules/responsive_image/tests/fixtures/update/drupal-8.responsive_image-enabled.php
new file mode 100644
index 000000000000..a23eea791396
--- /dev/null
+++ b/core/modules/responsive_image/tests/fixtures/update/drupal-8.responsive_image-enabled.php
@@ -0,0 +1,46 @@
+<?php
+// @codingStandardsIgnoreFile
+
+use Drupal\Core\Database\Database;
+
+$connection = Database::getConnection();
+
+// Set the schema version.
+$connection->merge('key_value')
+  ->fields([
+    'value' => 'i:8000;',
+    'name' => 'responsive_image',
+    'collection' => 'system.schema',
+  ])
+  ->condition('collection', 'system.schema')
+  ->condition('name', 'responsive_image')
+  ->execute();
+
+// Update core.extension.
+$extensions = $connection->select('config')
+  ->fields('config', ['data'])
+  ->condition('collection', '')
+  ->condition('name', 'core.extension')
+  ->execute()
+  ->fetchField();
+$extensions = unserialize($extensions);
+$extensions['module']['responsive_image'] = 8000;
+$connection->update('config')
+  ->fields([
+    'data' => serialize($extensions),
+    'collection' => '',
+    'name' => 'core.extension',
+  ])
+  ->condition('collection', '')
+  ->condition('name', 'core.extension')
+  ->execute();
+
+$connection->merge('key_value')
+  ->condition('collection', 'entity.definitions.installed')
+  ->condition('name', 'responsive_image_style.entity_type')
+  ->fields([
+    'value' => 'O:42:"Drupal\Core\Config\Entity\ConfigEntityType":44:{s:16:" * config_prefix";s:6:"styles";s:15:" * static_cache";b:0;s:14:" * lookup_keys";a:1:{i:0;s:4:"uuid";}s:16:" * config_export";a:5:{i:0;s:2:"id";i:1;s:5:"label";i:2;s:20:"image_style_mappings";i:3;s:16:"breakpoint_group";i:4;s:20:"fallback_image_style";}s:21:" * mergedConfigExport";a:0:{}s:15:" * render_cache";b:1;s:19:" * persistent_cache";b:1;s:14:" * entity_keys";a:8:{s:2:"id";s:2:"id";s:5:"label";s:5:"label";s:8:"revision";s:0:"";s:6:"bundle";s:0:"";s:8:"langcode";s:8:"langcode";s:16:"default_langcode";s:16:"default_langcode";s:29:"revision_translation_affected";s:29:"revision_translation_affected";s:4:"uuid";s:4:"uuid";}s:5:" * id";s:22:"responsive_image_style";s:16:" * originalClass";s:51:"Drupal\responsive_image\Entity\ResponsiveImageStyle";s:11:" * handlers";a:4:{s:12:"list_builder";s:55:"Drupal\responsive_image\ResponsiveImageStyleListBuilder";s:4:"form";a:4:{s:4:"edit";s:48:"Drupal\responsive_image\ResponsiveImageStyleForm";s:3:"add";s:48:"Drupal\responsive_image\ResponsiveImageStyleForm";s:6:"delete";s:35:"Drupal\Core\Entity\EntityDeleteForm";s:9:"duplicate";s:48:"Drupal\responsive_image\ResponsiveImageStyleForm";}s:6:"access";s:45:"Drupal\Core\Entity\EntityAccessControlHandler";s:7:"storage";s:45:"Drupal\Core\Config\Entity\ConfigEntityStorage";}s:19:" * admin_permission";s:28:"administer responsive images";s:25:" * permission_granularity";s:11:"entity_type";s:8:" * links";a:4:{s:9:"edit-form";s:67:"/admin/config/media/responsive-image-style/{responsive_image_style}";s:14:"duplicate-form";s:77:"/admin/config/media/responsive-image-style/{responsive_image_style}/duplicate";s:11:"delete-form";s:74:"/admin/config/media/responsive-image-style/{responsive_image_style}/delete";s:10:"collection";s:42:"/admin/config/media/responsive-image-style";}s:17:" * label_callback";N;s:21:" * bundle_entity_type";N;s:12:" * bundle_of";N;s:15:" * bundle_label";N;s:13:" * base_table";N;s:22:" * revision_data_table";N;s:17:" * revision_table";N;s:13:" * data_table";N;s:11:" * internal";b:0;s:15:" * translatable";b:0;s:19:" * show_revision_ui";b:0;s:8:" * label";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:22:"Responsive image style";s:12:" * arguments";a:0:{}s:10:" * options";a:0:{}}s:19:" * label_collection";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:23:"Responsive image styles";s:12:" * arguments";a:0:{}s:10:" * options";a:0:{}}s:17:" * label_singular";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:22:"responsive image style";s:12:" * arguments";a:0:{}s:10:" * options";a:0:{}}s:15:" * label_plural";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:23:"responsive image styles";s:12:" * arguments";a:0:{}s:10:" * options";a:0:{}}s:14:" * label_count";a:3:{s:8:"singular";s:29:"@count responsive image style";s:6:"plural";s:30:"@count responsive image styles";s:7:"context";N;}s:15:" * uri_callback";N;s:8:" * group";s:13:"configuration";s:14:" * group_label";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:" * string";s:13:"Configuration";s:12:" * arguments";a:0:{}s:10:" * options";a:1:{s:7:"context";s:17:"Entity type group";}}s:22:" * field_ui_base_route";N;s:26:" * common_reference_target";b:0;s:22:" * list_cache_contexts";a:0:{}s:18:" * list_cache_tags";a:1:{i:0;s:34:"config:responsive_image_style_list";}s:14:" * constraints";a:0:{}s:13:" * additional";a:0:{}s:8:" * class";s:51:"Drupal\responsive_image\Entity\ResponsiveImageStyle";s:11:" * provider";s:16:"responsive_image";s:14:" * _serviceIds";a:0:{}s:18:" * _entityStorages";a:0:{}s:20:" * stringTranslation";N;}',
+    'name' => 'responsive_image_style.entity_type',
+    'collection' => 'entity.definitions.installed',
+  ])
+  ->execute();
diff --git a/core/modules/responsive_image/tests/src/Functional/Update/ResponsiveImageUpdateTest.php b/core/modules/responsive_image/tests/src/Functional/Update/ResponsiveImageUpdateTest.php
index 32b89d4256d0..e14f58d696a6 100644
--- a/core/modules/responsive_image/tests/src/Functional/Update/ResponsiveImageUpdateTest.php
+++ b/core/modules/responsive_image/tests/src/Functional/Update/ResponsiveImageUpdateTest.php
@@ -20,27 +20,10 @@ class ResponsiveImageUpdateTest extends UpdatePathTestBase {
   public function setDatabaseDumpFiles() {
     $this->databaseDumpFiles = [
       __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8-rc1.bare.standard.php.gz',
+      __DIR__ . '/../../../fixtures/update/drupal-8.responsive_image-enabled.php',
     ];
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    /** @var \Drupal\Core\State\StateInterface $state */
-    $state = $this->container->get('state');
-
-    // Enable responsive_image module without using the module installer to
-    // avoid installation of configuration shipped in module.
-    $system_module_files = $state->get('system.module.files', []);
-    $system_module_files += ['responsive_image' => 'core/modules/responsive_image/responsive_image.info.yml'];
-    $state->set('system.module.files', $system_module_files);
-    $this->config('core.extension')->set('module.responsive_image', 0)->save();
-    $this->container->get('module_handler')->addModule('responsive_image', 'core/modules/responsive_image');
-  }
-
   /**
    * Tests post-update responsive_image_post_update_dependency().
    *
diff --git a/core/modules/system/tests/modules/update_test_schema/update_test_schema.install b/core/modules/system/tests/modules/update_test_schema/update_test_schema.install
index 2d86fdec033b..c4a7cfc0ad5a 100644
--- a/core/modules/system/tests/modules/update_test_schema/update_test_schema.install
+++ b/core/modules/system/tests/modules/update_test_schema/update_test_schema.install
@@ -86,3 +86,19 @@ function update_test_schema_update_8002() {
   }
 
 }
+
+if ($schema_version >= 8003) {
+
+  /**
+   * Schema version 8003.
+   */
+  function update_test_schema_update_8003() {
+    // Uninstall a module with no dependencies installed by the Standard
+    // profile.
+    \Drupal::service('module_installer')->uninstall(['page_cache']);
+    // Install a test module that is not installed in any of the database
+    // dumps.
+    \Drupal::service('module_installer')->install(['module_test']);
+  }
+
+}
diff --git a/core/modules/system/tests/src/Functional/Update/EntityUpdateAddRevisionDefaultTest.php b/core/modules/system/tests/src/Functional/Update/EntityUpdateAddRevisionDefaultTest.php
index aa8ba00461b1..26f5c2c9bf5d 100644
--- a/core/modules/system/tests/src/Functional/Update/EntityUpdateAddRevisionDefaultTest.php
+++ b/core/modules/system/tests/src/Functional/Update/EntityUpdateAddRevisionDefaultTest.php
@@ -25,13 +25,6 @@ class EntityUpdateAddRevisionDefaultTest extends UpdatePathTestBase {
    */
   protected $entityManager;
 
-  /**
-   * The last installed schema repository service.
-   *
-   * @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface
-   */
-  protected $lastInstalledSchemaRepository;
-
   /**
    * The state service.
    *
@@ -45,8 +38,8 @@ class EntityUpdateAddRevisionDefaultTest extends UpdatePathTestBase {
   protected function setUp() {
     parent::setUp();
 
+    // Do not use this property after calling ::runUpdates().
     $this->entityManager = \Drupal::entityManager();
-    $this->lastInstalledSchemaRepository = \Drupal::service('entity.last_installed_schema.repository');
     $this->state = \Drupal::state();
   }
 
@@ -71,20 +64,20 @@ public function testAddingTheRevisionDefaultField() {
 
     // Check that the test entity type does not have the 'revision_default'
     // field before running the updates.
-    $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update');
+    $field_storage_definitions = \Drupal::service('entity.last_installed_schema.repository')->getLastInstalledFieldStorageDefinitions('entity_test_update');
     $this->assertFalse(isset($field_storage_definitions['revision_default']));
 
     $this->runUpdates();
 
     // Check that the 'revision_default' field has been added by
     // system_update_8501().
-    $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update');
+    $field_storage_definitions = \Drupal::service('entity.last_installed_schema.repository')->getLastInstalledFieldStorageDefinitions('entity_test_update');
     $this->assertTrue(isset($field_storage_definitions['revision_default']));
 
     // Check that the correct initial value was set when the field was
     // installed.
     /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-    $entity = $this->entityManager->getStorage('entity_test_update')->load(1);
+    $entity = \Drupal::entityTypeManager()->getStorage('entity_test_update')->load(1);
     $this->assertTrue($entity->wasDefaultRevision());
   }
 
diff --git a/core/modules/system/tests/src/Functional/Update/EntityUpdateAddRevisionTranslationAffectedTest.php b/core/modules/system/tests/src/Functional/Update/EntityUpdateAddRevisionTranslationAffectedTest.php
index 6553fcb06eb3..b6c4fd03777d 100644
--- a/core/modules/system/tests/src/Functional/Update/EntityUpdateAddRevisionTranslationAffectedTest.php
+++ b/core/modules/system/tests/src/Functional/Update/EntityUpdateAddRevisionTranslationAffectedTest.php
@@ -25,13 +25,6 @@ class EntityUpdateAddRevisionTranslationAffectedTest extends UpdatePathTestBase
    */
   protected $entityManager;
 
-  /**
-   * The last installed schema repository service.
-   *
-   * @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface
-   */
-  protected $lastInstalledSchemaRepository;
-
   /**
    * The state service.
    *
@@ -45,8 +38,8 @@ class EntityUpdateAddRevisionTranslationAffectedTest extends UpdatePathTestBase
   protected function setUp() {
     parent::setUp();
 
+    // Do not use this property after calling ::runUpdates().
     $this->entityManager = \Drupal::entityManager();
-    $this->lastInstalledSchemaRepository = \Drupal::service('entity.last_installed_schema.repository');
     $this->state = \Drupal::state();
   }
 
@@ -71,19 +64,19 @@ public function testAddingTheRevisionTranslationAffectedField() {
 
     // Check that the test entity type does not have the
     // 'revision_translation_affected' field before running the updates.
-    $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update');
+    $field_storage_definitions = \Drupal::service('entity.last_installed_schema.repository')->getLastInstalledFieldStorageDefinitions('entity_test_update');
     $this->assertFalse(isset($field_storage_definitions['revision_translation_affected']));
 
     $this->runUpdates();
 
     // Check that the 'revision_translation_affected' field has been added by
     // system_update_8402().
-    $field_storage_definitions = $this->lastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions('entity_test_update');
+    $field_storage_definitions = \Drupal::service('entity.last_installed_schema.repository')->getLastInstalledFieldStorageDefinitions('entity_test_update');
     $this->assertTrue(isset($field_storage_definitions['revision_translation_affected']));
 
     // Check that the correct initial value was set when the field was
     // installed.
-    $entity = $this->entityManager->getStorage('entity_test_update')->load(1);
+    $entity = \Drupal::entityTypeManager()->getStorage('entity_test_update')->load(1);
     $this->assertTrue($entity->revision_translation_affected->value);
   }
 
diff --git a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php
index f8b144bfac0c..5855effb41c5 100644
--- a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php
+++ b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBase.php
@@ -321,9 +321,38 @@ protected function runUpdates() {
           }
         }
       }
-      // Reset the static cache of drupal_get_installed_schema_version() so that
-      // more complex update path testing works.
-      drupal_static_reset('drupal_get_installed_schema_version');
+
+      // Ensure that the container is updated if any modules are installed or
+      // uninstalled during the update.
+      /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
+      $module_handler = $this->container->get('module_handler');
+      $config_module_list = $this->config('core.extension')->get('module');
+      $module_handler_list = $module_handler->getModuleList();
+      $modules_installed = FALSE;
+      // Modules that are in configuration but not the module handler have been
+      // installed.
+      foreach (array_keys(array_diff_key($config_module_list, $module_handler_list)) as $module) {
+        $module_handler->addModule($module, drupal_get_path('module', $module));
+        $modules_installed = TRUE;
+      }
+      $modules_uninstalled = FALSE;
+      $module_handler_list = $module_handler->getModuleList();
+      // Modules that are in the module handler but not configuration have been
+      // uninstalled.
+      foreach (array_keys(array_diff_key($module_handler_list, $config_module_list)) as $module) {
+        $modules_uninstalled = TRUE;
+        unset($module_handler_list[$module]);
+      }
+      if ($modules_installed || $modules_uninstalled) {
+        // Note that resetAll() does not reset the kernel module list so we
+        // have to do that manually.
+        $this->kernel->updateModules($module_handler_list, $module_handler_list);
+      }
+
+      // If we have successfully clicked 'Apply pending updates' then we need to
+      // clear the caches in the update test runner as this has occurred as part
+      // of the updates.
+      $this->resetAll();
 
       // The config schema can be incorrect while the update functions are being
       // executed. But once the update has been completed, it needs to be valid
@@ -331,7 +360,6 @@ protected function runUpdates() {
       $names = $this->container->get('config.storage')->listAll();
       /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config */
       $typed_config = $this->container->get('config.typed');
-      $typed_config->clearCachedDefinitions();
       foreach ($names as $name) {
         $config = $this->config($name);
         $this->assertConfigSchema($typed_config, $name, $config->get());
diff --git a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBaseTest.php b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBaseTest.php
index 535d271d2e8d..1d7462d7571d 100644
--- a/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBaseTest.php
+++ b/core/tests/Drupal/FunctionalTests/Update/UpdatePathTestBaseTest.php
@@ -33,6 +33,9 @@ protected function setDatabaseDumpFiles() {
    * Tests that the database was properly loaded.
    */
   public function testDatabaseLoaded() {
+    // Set a value in the cache to prove caches are cleared.
+    \Drupal::service('cache.default')->set(__CLASS__, 'Test');
+
     foreach (['user', 'node', 'system', 'update_test_schema'] as $module) {
       $this->assertEqual(drupal_get_installed_schema_version($module), 8000, new FormattableMarkup('Module @module schema is 8000', ['@module' => $module]));
     }
@@ -70,6 +73,8 @@ public function testDatabaseLoaded() {
       $this->assertEqual('on', $database->query("SHOW standard_conforming_strings")->fetchField());
       $this->assertEqual('escape', $database->query("SHOW bytea_output")->fetchField());
     }
+    // Ensure the test runners cache has been cleared.
+    $this->assertFalse(\Drupal::service('cache.default')->get(__CLASS__));
   }
 
   /**
@@ -131,4 +136,50 @@ public function testPathAliasProcessing() {
     $this->assertSession()->linkByHrefExists('/admin-structure-alias');
   }
 
+  /**
+   * Tests that test running environment is updated when module list changes.
+   *
+   * @see update_test_schema_update_8003()
+   */
+  public function testModuleListChange() {
+    // Set a value in the cache to prove caches are cleared.
+    \Drupal::service('cache.default')->set(__CLASS__, 'Test');
+
+    // Ensure that modules are installed and uninstalled as expected prior to
+    // running updates.
+    $extension_config = $this->config('core.extension')->get();
+    $this->assertArrayHasKey('page_cache', $extension_config['module']);
+    $this->assertArrayNotHasKey('module_test', $extension_config['module']);
+
+    $module_list = \Drupal::moduleHandler()->getModuleList();
+    $this->assertArrayHasKey('page_cache', $module_list);
+    $this->assertArrayNotHasKey('module_test', $module_list);
+
+    $namespaces = \Drupal::getContainer()->getParameter('container.namespaces');
+    $this->assertArrayHasKey('Drupal\page_cache', $namespaces);
+    $this->assertArrayNotHasKey('Drupal\module_test', $namespaces);
+
+    // Increment the schema version so that update_test_schema_update_8003()
+    // runs.
+    \Drupal::state()->set('update_test_schema_version', 8003);
+    $this->runUpdates();
+
+    // Ensure that test running environment has been updated with the changes to
+    // the module list.
+    $extension_config = $this->config('core.extension')->get();
+    $this->assertArrayNotHasKey('page_cache', $extension_config['module']);
+    $this->assertArrayHasKey('module_test', $extension_config['module']);
+
+    $module_list = \Drupal::moduleHandler()->getModuleList();
+    $this->assertArrayNotHasKey('page_cache', $module_list);
+    $this->assertArrayHasKey('module_test', $module_list);
+
+    $namespaces = \Drupal::getContainer()->getParameter('container.namespaces');
+    $this->assertArrayNotHasKey('Drupal\page_cache', $namespaces);
+    $this->assertArrayHasKey('Drupal\module_test', $namespaces);
+
+    // Ensure the test runners cache has been cleared.
+    $this->assertFalse(\Drupal::service('cache.default')->get(__CLASS__));
+  }
+
 }
-- 
GitLab