You are here

public function ConfigImporterTest::testUnmetDependency in Drupal 9

Same name and namespace in other branches
  1. 8 core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php \Drupal\KernelTests\Core\Config\ConfigImporterTest::testUnmetDependency()

Tests dependency validation during configuration import.

See also

\Drupal\Core\EventSubscriber\ConfigImportSubscriber

\Drupal\Core\Config\ConfigImporter::createExtensionChangelist()

File

core/tests/Drupal/KernelTests/Core/Config/ConfigImporterTest.php, line 552

Class

ConfigImporterTest
Tests importing configuration from files into active configuration.

Namespace

Drupal\KernelTests\Core\Config

Code

public function testUnmetDependency() {
  $storage = $this->container
    ->get('config.storage');
  $sync = $this->container
    ->get('config.storage.sync');

  // Test an unknown configuration owner.
  $sync
    ->write('unknown.config', [
    'test' => 'test',
  ]);

  // Make a config entity have unmet dependencies.
  $config_entity_data = $sync
    ->read('config_test.dynamic.dotted.default');
  $config_entity_data['dependencies'] = [
    'module' => [
      'unknown',
    ],
  ];
  $sync
    ->write('config_test.dynamic.dotted.module', $config_entity_data);
  $config_entity_data['dependencies'] = [
    'theme' => [
      'unknown',
    ],
  ];
  $sync
    ->write('config_test.dynamic.dotted.theme', $config_entity_data);
  $config_entity_data['dependencies'] = [
    'config' => [
      'unknown',
    ],
  ];
  $sync
    ->write('config_test.dynamic.dotted.config', $config_entity_data);

  // Make an active config depend on something that is missing in sync.
  // The whole configuration needs to be consistent, not only the updated one.
  $config_entity_data['dependencies'] = [];
  $storage
    ->write('config_test.dynamic.dotted.deleted', $config_entity_data);
  $config_entity_data['dependencies'] = [
    'config' => [
      'config_test.dynamic.dotted.deleted',
    ],
  ];
  $storage
    ->write('config_test.dynamic.dotted.existing', $config_entity_data);
  $sync
    ->write('config_test.dynamic.dotted.existing', $config_entity_data);
  $extensions = $sync
    ->read('core.extension');

  // Add a module and a theme that do not exist.
  $extensions['module']['unknown_module'] = 0;
  $extensions['theme']['unknown_theme'] = 0;

  // Add a module and a theme that depend on uninstalled extensions.
  $extensions['module']['book'] = 0;
  $extensions['theme']['test_subtheme'] = 0;
  $sync
    ->write('core.extension', $extensions);
  try {
    $this->configImporter
      ->reset()
      ->import();
    $this
      ->fail('ConfigImporterException not thrown; an invalid import was not stopped due to missing dependencies.');
  } catch (ConfigImporterException $e) {
    $expected = [
      static::FAIL_MESSAGE,
      'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
      'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User</em> modules.',
      'Unable to install the <em class="placeholder">unknown_theme</em> theme since it does not exist.',
      'Unable to install the <em class="placeholder">Theme test subtheme</em> theme since it requires the <em class="placeholder">Theme test base theme</em> theme.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on the <em class="placeholder">unknown</em> configuration that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.existing</em> depends on the <em class="placeholder">config_test.dynamic.dotted.deleted</em> configuration that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.module</em> depends on the <em class="placeholder">unknown</em> module that will not be installed after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on the <em class="placeholder">unknown</em> theme that will not be installed after import.',
      'Configuration <em class="placeholder">unknown.config</em> depends on the <em class="placeholder">unknown</em> extension that will not be installed after import.',
    ];
    $this
      ->assertEquals(implode(PHP_EOL, $expected), $e
      ->getMessage());
    $error_log = $this->configImporter
      ->getErrors();
    $expected = [
      'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
      'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User</em> modules.',
      'Unable to install the <em class="placeholder">unknown_theme</em> theme since it does not exist.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on the <em class="placeholder">unknown</em> configuration that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.existing</em> depends on the <em class="placeholder">config_test.dynamic.dotted.deleted</em> configuration that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.module</em> depends on the <em class="placeholder">unknown</em> module that will not be installed after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on the <em class="placeholder">unknown</em> theme that will not be installed after import.',
      'Configuration <em class="placeholder">unknown.config</em> depends on the <em class="placeholder">unknown</em> extension that will not be installed after import.',
    ];
    foreach ($expected as $expected_message) {
      $this
        ->assertContainsEquals($expected_message, $error_log, $expected_message);
    }
  }

  // Make a config entity have multiple unmet dependencies.
  $config_entity_data = $sync
    ->read('config_test.dynamic.dotted.default');
  $config_entity_data['dependencies'] = [
    'module' => [
      'unknown',
      'dblog',
    ],
  ];
  $sync
    ->write('config_test.dynamic.dotted.module', $config_entity_data);
  $config_entity_data['dependencies'] = [
    'theme' => [
      'unknown',
      'seven',
    ],
  ];
  $sync
    ->write('config_test.dynamic.dotted.theme', $config_entity_data);
  $config_entity_data['dependencies'] = [
    'config' => [
      'unknown',
      'unknown2',
    ],
  ];
  $sync
    ->write('config_test.dynamic.dotted.config', $config_entity_data);
  try {
    $this->configImporter
      ->reset()
      ->import();
    $this
      ->fail('ConfigImporterException not thrown, invalid import was not stopped due to missing dependencies.');
  } catch (ConfigImporterException $e) {
    $expected = [
      static::FAIL_MESSAGE,
      'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
      'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User</em> modules.',
      'Unable to install the <em class="placeholder">unknown_theme</em> theme since it does not exist.',
      'Unable to install the <em class="placeholder">Theme test subtheme</em> theme since it requires the <em class="placeholder">Theme test base theme</em> theme.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on the <em class="placeholder">unknown</em> configuration that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.existing</em> depends on the <em class="placeholder">config_test.dynamic.dotted.deleted</em> configuration that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.module</em> depends on the <em class="placeholder">unknown</em> module that will not be installed after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on the <em class="placeholder">unknown</em> theme that will not be installed after import.',
      'Configuration <em class="placeholder">unknown.config</em> depends on the <em class="placeholder">unknown</em> extension that will not be installed after import.',
      'Unable to install the <em class="placeholder">unknown_module</em> module since it does not exist.',
      'Unable to install the <em class="placeholder">Book</em> module since it requires the <em class="placeholder">Node, Text, Field, Filter, User</em> modules.',
      'Unable to install the <em class="placeholder">unknown_theme</em> theme since it does not exist.',
      'Unable to install the <em class="placeholder">Theme test subtheme</em> theme since it requires the <em class="placeholder">Theme test base theme</em> theme.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on configuration (<em class="placeholder">unknown, unknown2</em>) that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.existing</em> depends on the <em class="placeholder">config_test.dynamic.dotted.deleted</em> configuration that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.module</em> depends on modules (<em class="placeholder">unknown, Database Logging</em>) that will not be installed after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on themes (<em class="placeholder">unknown, Seven</em>) that will not be installed after import.',
      'Configuration <em class="placeholder">unknown.config</em> depends on the <em class="placeholder">unknown</em> extension that will not be installed after import.',
    ];
    $this
      ->assertEquals(implode(PHP_EOL, $expected), $e
      ->getMessage());
    $error_log = $this->configImporter
      ->getErrors();
    $expected = [
      'Configuration <em class="placeholder">config_test.dynamic.dotted.config</em> depends on configuration (<em class="placeholder">unknown, unknown2</em>) that will not exist after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.module</em> depends on modules (<em class="placeholder">unknown, Database Logging</em>) that will not be installed after import.',
      'Configuration <em class="placeholder">config_test.dynamic.dotted.theme</em> depends on themes (<em class="placeholder">unknown, Seven</em>) that will not be installed after import.',
    ];
    foreach ($expected as $expected_message) {
      $this
        ->assertContainsEquals($expected_message, $error_log, $expected_message);
    }
  }
}