You are here

protected function UpdatePathTestTrait::runUpdates in Drupal 9

Same name and namespace in other branches
  1. 8 core/tests/Drupal/Tests/UpdatePathTestTrait.php \Drupal\Tests\UpdatePathTestTrait::runUpdates()

Helper function to run pending database updates.

Parameters

string|null $update_url: The update URL.

10 calls to UpdatePathTestTrait::runUpdates()
ActiveWorkspaceUpdateTest::testActiveWorkspaceDuringUpdate in core/modules/workspaces/tests/src/Functional/UpdateSystem/ActiveWorkspaceUpdateTest.php
Tests that there is no active workspace during database updates.
BrokenCacheUpdateTest::testUpdate in core/modules/system/tests/src/Functional/UpdateSystem/BrokenCacheUpdateTest.php
Ensures that a broken or out-of-date element info cache is not used.
EntityUpdateInitialTest::testInitialIsIgnored in core/modules/system/tests/src/Functional/UpdateSystem/EntityUpdateInitialTest.php
Tests that a pre-existing initial key in the field schema is not a change.
UpdatePathLastRemovedTest::testLastRemovedVersion in core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathLastRemovedTest.php
Tests that a module with a too old schema version can not be updated.
UpdatePathNewDependencyTest::testUpdateNewDependency in core/modules/system/tests/src/Functional/UpdateSystem/UpdatePathNewDependencyTest.php
Tests that a module can add services that depend on new modules.

... See full list

File

core/tests/Drupal/Tests/UpdatePathTestTrait.php, line 30

Class

UpdatePathTestTrait
Trait UpdatePathTestTrait.

Namespace

Drupal\Tests

Code

protected function runUpdates($update_url = NULL) {
  if (!$update_url) {
    $update_url = Url::fromRoute('system.db_update');
  }
  require_once $this->root . '/core/includes/update.inc';

  // The site might be broken at the time so logging in using the UI might
  // not work, so we use the API itself.
  $this
    ->writeSettings([
    'settings' => [
      'update_free_access' => (object) [
        'value' => TRUE,
        'required' => TRUE,
      ],
    ],
  ]);
  $this
    ->drupalGet($update_url);
  $this
    ->updateRequirementsProblem();
  $this
    ->clickLink('Continue');
  $this
    ->doSelectionTest();

  // Run the update hooks.
  $this
    ->clickLink('Apply pending updates');
  $this
    ->checkForMetaRefresh();

  // Ensure there are no failed updates.
  if ($this->checkFailedUpdates) {
    $failure = $this
      ->cssSelect('.failure');
    if ($failure) {
      $this
        ->fail('The update failed with the following message: "' . reset($failure)
        ->getText() . '"');
    }

    // Ensure that there are no pending updates.
    foreach ([
      'update',
      'post_update',
    ] as $update_type) {
      switch ($update_type) {
        case 'update':
          $all_updates = update_get_update_list();
          break;
        case 'post_update':
          $all_updates = \Drupal::service('update.post_update_registry')
            ->getPendingUpdateInformation();
          break;
      }
      foreach ($all_updates as $module => $updates) {
        if (!empty($updates['pending'])) {
          foreach (array_keys($updates['pending']) as $update_name) {
            $this
              ->fail("The {$update_name}() update function from the {$module} module did not run.");
          }
        }
      }
    }

    // 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.

    /** @var \Drupal\Core\Extension\ModuleExtensionList $module_list */
    $module_list = $this->container
      ->get('extension.list.module');
    foreach (array_keys(array_diff_key($config_module_list, $module_handler_list)) as $module) {
      $module_handler
        ->addModule($module, $module_list
        ->getPath($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);
    }

    // Close any open database connections. This allows DB drivers that store
    // static information to refresh it in the update runner.
    // @todo https://drupal.org/i/3222121 consider doing this in
    //   \Drupal\Core\DrupalKernel::initializeContainer() for container
    //   rebuilds.
    foreach (Database::getAllConnectionInfo() as $key => $info) {
      Database::closeConnection(NULL, $key);
    }

    // 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
    // again. Assert the schema of all configuration objects now.
    $names = $this->container
      ->get('config.storage')
      ->listAll();

    // Allow tests to opt out of checking specific configuration.
    $exclude = $this
      ->getConfigSchemaExclusions();

    /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config */
    $typed_config = $this->container
      ->get('config.typed');
    foreach ($names as $name) {
      if (in_array($name, $exclude, TRUE)) {

        // Skip checking schema if the config is listed in the
        // $configSchemaCheckerExclusions property.
        continue;
      }
      $config = $this
        ->config($name);
      $this
        ->assertConfigSchema($typed_config, $name, $config
        ->get());
    }

    // Ensure that the update hooks updated all entity schema.
    $needs_updates = \Drupal::entityDefinitionUpdateManager()
      ->needsUpdates();
    if ($needs_updates) {
      foreach (\Drupal::entityDefinitionUpdateManager()
        ->getChangeSummary() as $entity_type_id => $summary) {
        $entity_type_label = \Drupal::entityTypeManager()
          ->getDefinition($entity_type_id)
          ->getLabel();
        foreach ($summary as $message) {
          $this
            ->fail("{$entity_type_label}: {$message}");
        }
      }

      // The above calls to `fail()` should prevent this from ever being
      // called, but it is here in case something goes really wrong.
      $this
        ->assertFalse($needs_updates, 'After all updates ran, entity schema is up to date.');
    }
  }
}