diff --git a/core/lib/Drupal/Core/Extension/ExtensionSchemaVersionException.php b/core/lib/Drupal/Core/Extension/ExtensionSchemaVersionException.php new file mode 100644 index 0000000..2b166ac --- /dev/null +++ b/core/lib/Drupal/Core/Extension/ExtensionSchemaVersionException.php @@ -0,0 +1,13 @@ +assertTrue($update_dependencies['system'][8000]['update_test_1'] == 8000, 'An update function that has a dependency on two separate modules has the first dependency recorded correctly.'); - $this->assertTrue($update_dependencies['system'][8000]['update_test_2'] == 8001, 'An update function that has a dependency on two separate modules has the second dependency recorded correctly.'); - $this->assertTrue($update_dependencies['system'][8001]['update_test_1'] == 8002, 'An update function that depends on more than one update from the same module only has the dependency on the higher-numbered update function recorded.'); + $this->assertTrue($update_dependencies['update_test_0'][8001]['update_test_1'] == 8001, 'An update function that has a dependency on two separate modules has the first dependency recorded correctly.'); + $this->assertTrue($update_dependencies['update_test_0'][8001]['update_test_2'] == 8002, 'An update function that has a dependency on two separate modules has the second dependency recorded correctly.'); + $this->assertTrue($update_dependencies['update_test_0'][8002]['update_test_1'] == 8003, 'An update function that depends on more than one update from the same module only has the dependency on the higher-numbered update function recorded.'); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyMissingTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyMissingTest.php index 6c71371..167beea 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyMissingTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyMissingTest.php @@ -19,7 +19,7 @@ class DependencyMissingTest extends WebTestBase { * * @var array */ - public static $modules = array('update_test_2'); + public static $modules = array('update_test_0', 'update_test_2'); public static function getInfo() { return array( @@ -38,11 +38,11 @@ function setUp() { function testMissingUpdate() { $starting_updates = array( - 'update_test_2' => 8000, + 'update_test_2' => 8001, ); $update_graph = update_resolve_dependencies($starting_updates); - $this->assertTrue($update_graph['update_test_2_update_8000']['allowed'], "The module's first update function is allowed to run, since it does not have any missing dependencies."); - $this->assertFalse($update_graph['update_test_2_update_8001']['allowed'], "The module's second update function is not allowed to run, since it has a direct dependency on a missing update."); - $this->assertFalse($update_graph['update_test_2_update_8002']['allowed'], "The module's third update function is not allowed to run, since it has an indirect dependency on a missing update."); + $this->assertTrue($update_graph['update_test_2_update_8001']['allowed'], "The module's first update function is allowed to run, since it does not have any missing dependencies."); + $this->assertFalse($update_graph['update_test_2_update_8002']['allowed'], "The module's second update function is not allowed to run, since it has a direct dependency on a missing update."); + $this->assertFalse($update_graph['update_test_2_update_8003']['allowed'], "The module's third update function is not allowed to run, since it has an indirect dependency on a missing update."); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyOrderingTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyOrderingTest.php index b007546..5667be0 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Update/DependencyOrderingTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Update/DependencyOrderingTest.php @@ -19,7 +19,7 @@ class DependencyOrderingTest extends WebTestBase { * * @var array */ - public static $modules = array('update_test_1', 'update_test_2', 'update_test_3'); + public static $modules = array('update_test_0', 'update_test_1', 'update_test_2', 'update_test_3'); public static function getInfo() { return array( @@ -39,12 +39,12 @@ function setUp() { */ function testUpdateOrderingSingleModule() { $starting_updates = array( - 'update_test_1' => 8000, + 'update_test_1' => 8001, ); $expected_updates = array( - 'update_test_1_update_8000', 'update_test_1_update_8001', 'update_test_1_update_8002', + 'update_test_1_update_8003', ); $actual_updates = array_keys(update_resolve_dependencies($starting_updates)); $this->assertEqual($expected_updates, $actual_updates, 'Updates within a single module run in the correct order.'); @@ -55,14 +55,14 @@ function testUpdateOrderingSingleModule() { */ function testUpdateOrderingModuleInterdependency() { $starting_updates = array( - 'update_test_2' => 8000, - 'update_test_3' => 8000, + 'update_test_2' => 8001, + 'update_test_3' => 8001, ); $update_order = array_keys(update_resolve_dependencies($starting_updates)); // Make sure that each dependency is satisfied. - $first_dependency_satisfied = array_search('update_test_2_update_8000', $update_order) < array_search('update_test_3_update_8000', $update_order); + $first_dependency_satisfied = array_search('update_test_2_update_8001', $update_order) < array_search('update_test_3_update_8001', $update_order); $this->assertTrue($first_dependency_satisfied, 'The dependency of the second module on the first module is respected by the update function order.'); - $second_dependency_satisfied = array_search('update_test_3_update_8000', $update_order) < array_search('update_test_2_update_8001', $update_order); + $second_dependency_satisfied = array_search('update_test_3_update_8001', $update_order) < array_search('update_test_2_update_8002', $update_order); $this->assertTrue($second_dependency_satisfied, 'The dependency of the first module on the second module is respected by the update function order.'); } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/InvalidUpdateHook.php b/core/modules/system/lib/Drupal/system/Tests/Update/InvalidUpdateHook.php new file mode 100644 index 0000000..4a3e48d --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Update/InvalidUpdateHook.php @@ -0,0 +1,42 @@ + 'Invalid update hook', + 'description' => 'Tests that a module implementing hook_update_8000() causes an exception to be thrown on update.', + 'group' => 'Update API', + ); + } + + function setUp() { + parent::setUp(); + require_once DRUPAL_ROOT . '/core/includes/update.inc'; + } + + function testInvalidUpdateHook() { + // Confirm that a module with hook_update_8000() cannot be installed. + try { + \Drupal::moduleHandler()->install(array('update_test_invalid_hook')); + $this->fail('Enabling a module with hook_update_8000() is disallowed.'); + } + catch (ExtensionSchemaVersionException $e) { + $this->pass('Enabling a module with hook_update_8000() is disallowed.'); + } + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php index d581147..4158cea 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Update/UpdateScriptTest.php @@ -99,7 +99,7 @@ function testRequirements() { $this->assertNoText('This is a requirements warning provided by the update_script_test module.'); $this->drupalPostForm(NULL, array(), t('Continue')); $this->drupalPostForm(NULL, array(), 'Apply pending updates'); - $this->assertText(t('The update_script_test_update_8000() update was executed successfully.'), 'End of update process was reached.'); + $this->assertText(t('The update_script_test_update_8001() update was executed successfully.'), 'End of update process was reached.'); // Confirm that all caches were cleared. $this->assertText(t('hook_cache_flush() invoked for update_script_test.module.'), 'Caches were cleared after resolving a requirements warning and applying updates.'); @@ -165,20 +165,46 @@ function testNoUpdateFunctionality() { * Tests update.php after performing a successful update. */ function testSuccessfulUpdateFunctionality() { - drupal_set_installed_schema_version('update_script_test', drupal_get_installed_schema_version('update_script_test') - 1); + $schema_version = drupal_get_installed_schema_version('update_script_test'); + $this->assertEqual($schema_version, 8001, 'update_script_test is initially installed with schema version 8001.'); + + // Set the installed schema version to one less than the current update. + drupal_set_installed_schema_version('update_script_test', $schema_version - 1); + $schema_version = drupal_get_installed_schema_version('update_script_test', TRUE); + $this->assertEqual($schema_version, 8000, 'update_script_test schema version overridden to 8000.'); + // Click through update.php with 'administer software updates' permission. $this->drupalLogin($this->update_user); $this->drupalPostForm($this->update_url, array(), t('Continue'), array('external' => TRUE)); $this->drupalPostForm(NULL, array(), t('Apply pending updates')); + + // Verify that updates were completed successfully. $this->assertText('Updates were attempted.'); $this->assertLink('site'); + $this->assertText('The update_script_test_update_8001() update was executed successfully.'); + + // Verify that no 7.x updates were run. + $this->assertNoText('The update_script_test_update_7200() update was executed successfully.'); + $this->assertNoText('The update_script_test_update_7201() update was executed successfully.'); + + // Verify that there are no links to different parts of the workflow. $this->assertNoLink('Administration pages'); $this->assertNoLinkByHref('update.php', 0); $this->assertNoLink('logged'); + + // Verify the front page can be visited following the upgrade. $this->clickLink('Front page'); $this->assertResponse(200); - drupal_set_installed_schema_version('update_script_test', drupal_get_installed_schema_version('update_script_test') - 1); + // Reset the static cache to ensure we have the most current setting. + $schema_version = drupal_get_installed_schema_version('update_script_test', TRUE); + $this->assertEqual($schema_version, 8001, 'update_script_test schema version is 8001 after updating.'); + + // Set the installed schema version to one less than the current update. + drupal_set_installed_schema_version('update_script_test', $schema_version - 1); + $schema_version = drupal_get_installed_schema_version('update_script_test', TRUE); + $this->assertEqual($schema_version, 8000, 'update_script_test schema version overridden to 8000.'); + // Click through update.php with 'access administration pages' and // 'access site reports' permissions. $admin_user = $this->drupalCreateUser(array('administer software updates', 'access administration pages', 'access site reports')); diff --git a/core/modules/system/lib/Drupal/system/Tests/Update/UpdatesWith7x.php b/core/modules/system/lib/Drupal/system/Tests/Update/UpdatesWith7x.php new file mode 100644 index 0000000..0808b97 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Update/UpdatesWith7x.php @@ -0,0 +1,63 @@ + '7.x update hooks', + 'description' => 'Tests that the minimum schema version is correct even if only 7.x update hooks are retained .', + 'group' => 'Update API', + ); + } + + function setUp() { + parent::setUp(); + require_once DRUPAL_ROOT . '/core/includes/update.inc'; + $this->update_url = $GLOBALS['base_url'] . '/core/update.php'; + $this->update_user = $this->drupalCreateUser(array('administer software updates')); + } + + function testWith7x() { + // Ensure that the minimum schema version is 8000, despite 7200 update + // hooks and a 7XXX hook_update_last_removed(). + $this->assertEqual(drupal_get_installed_schema_version('update_test_with_7x'), 8000); + + // Try to manually set the schema version to 7110 and ensure that no + // updates are allowed. + drupal_set_installed_schema_version('update_test_with_7x', 7110); + + // Click through update.php with 'administer software updates' permission. + $this->drupalLogin($this->update_user); + $this->drupalPostForm($this->update_url, array(), t('Continue'), array('external' => TRUE)); + $this->assertText(t('No pending updates.')); + } +} diff --git a/core/modules/system/tests/modules/update_script_test/update_script_test.install b/core/modules/system/tests/modules/update_script_test/update_script_test.install index 594dfa3..0f1718d 100644 --- a/core/modules/system/tests/modules/update_script_test/update_script_test.install +++ b/core/modules/system/tests/modules/update_script_test/update_script_test.install @@ -38,8 +38,29 @@ function update_script_test_requirements($phase) { } /** + * Implements hook_update_last_removed(). + */ +function update_script_test_update_last_removed() { + return 7110; +} + +/** + * Dummy update_script_test update 7200. + */ +function update_script_test_update_7200() { + return 'The update_script_test_update_7200() update was executed successfully.'; +} + +/** + * Dummy update_script_test update 7201. + */ +function update_script_test_update_7201() { + return 'The update_script_test_update_7201() update was executed successfully.'; +} + +/** * Dummy update function to run during the tests. */ -function update_script_test_update_8000() { - return t('The update_script_test_update_8000() update was executed successfully.'); +function update_script_test_update_8001() { + return 'The update_script_test_update_8001() update was executed successfully.'; } diff --git a/core/modules/system/tests/modules/update_test_0/update_test_0.info.yml b/core/modules/system/tests/modules/update_test_0/update_test_0.info.yml new file mode 100644 index 0000000..d9f07cd --- /dev/null +++ b/core/modules/system/tests/modules/update_test_0/update_test_0.info.yml @@ -0,0 +1,7 @@ +name: 'Update test 0' +type: module +description: 'Support module for update testing.' +package: Testing +version: VERSION +core: 8.x +hidden: true diff --git a/core/modules/system/tests/modules/update_test_0/update_test_0.install b/core/modules/system/tests/modules/update_test_0/update_test_0.install new file mode 100644 index 0000000..16e0c38 --- /dev/null +++ b/core/modules/system/tests/modules/update_test_0/update_test_0.install @@ -0,0 +1,24 @@ + 8000, + // the correct array structure. Therefore, we use updates from the + // update_test_0 module (which will be installed first) that they will not + // get in the way of other tests. + $dependencies['update_test_0'][8001] = array( + // Compare to update_test_2_update_dependencies(), where the same + // update_test_0 module update function is forced to depend on an update + // function from a different module. This allows us to test that both + // dependencies are correctly recorded. + 'update_test_1' => 8001, ); - $dependencies['system'][8001] = array( - // Compare to update_test_2_update_dependencies(), where the same System - // module update function is forced to depend on a different update - // function within the same module. This allows us to test that only the - // dependency on the higher-numbered update function is recorded. - 'update_test_1' => 8002, + $dependencies['update_test_0'][8002] = array( + // Compare to update_test_2_update_dependencies(), where the same + // update_test_0 module update function is forced to depend on a + // different update function within the same module. This allows us to + // test that only the dependency on the higher-numbered update function + // is recorded. + 'update_test_1' => 8003, ); return $dependencies; } /** - * Dummy update_test_1 update 8000. - */ -function update_test_1_update_8000() { -} - -/** * Dummy update_test_1 update 8001. */ function update_test_1_update_8001() { @@ -52,3 +47,9 @@ function update_test_1_update_8001() { */ function update_test_1_update_8002() { } + +/** + * Dummy update_test_1 update 8003. + */ +function update_test_1_update_8003() { +} diff --git a/core/modules/system/tests/modules/update_test_2/update_test_2.install b/core/modules/system/tests/modules/update_test_2/update_test_2.install index c73271a..4202720 100644 --- a/core/modules/system/tests/modules/update_test_2/update_test_2.install +++ b/core/modules/system/tests/modules/update_test_2/update_test_2.install @@ -14,33 +14,27 @@ function update_test_2_update_dependencies() { // Combined with update_test_3_update_dependencies(), we are declaring here // that these two modules run updates in the following order: - // 1. update_test_2_update_8000() - // 2. update_test_3_update_8000() - // 3. update_test_2_update_8001() - // 4. update_test_2_update_8002() - $dependencies['update_test_2'][8001] = array( - 'update_test_3' => 8000, + // 1. update_test_2_update_8001() + // 2. update_test_3_update_8001() + // 3. update_test_2_update_8002() + // 4. update_test_2_update_8003() + $dependencies['update_test_2'][8002] = array( + 'update_test_3' => 8001, ); // These are coordinated with the corresponding dependencies declared in // update_test_1_update_dependencies(). - $dependencies['system'][8000] = array( - 'update_test_2' => 8001, + $dependencies['update_test_0'][8001] = array( + 'update_test_2' => 8002, ); - $dependencies['system'][8001] = array( - 'update_test_1' => 8001, + $dependencies['update_test_0'][8002] = array( + 'update_test_1' => 8002, ); return $dependencies; } /** - * Dummy update_test_2 update 8000. - */ -function update_test_2_update_8000() { -} - -/** * Dummy update_test_2 update 8001. */ function update_test_2_update_8001() { @@ -51,3 +45,9 @@ function update_test_2_update_8001() { */ function update_test_2_update_8002() { } + +/** + * Dummy update_test_2 update 8003. + */ +function update_test_2_update_8003() { +} diff --git a/core/modules/system/tests/modules/update_test_3/update_test_3.install b/core/modules/system/tests/modules/update_test_3/update_test_3.install index 96830c8..ae2da4b 100644 --- a/core/modules/system/tests/modules/update_test_3/update_test_3.install +++ b/core/modules/system/tests/modules/update_test_3/update_test_3.install @@ -11,14 +11,14 @@ * @see update_test_2_update_dependencies() */ function update_test_3_update_dependencies() { - $dependencies['update_test_3'][8000] = array( - 'update_test_2' => 8000, + $dependencies['update_test_3'][8001] = array( + 'update_test_2' => 8001, ); return $dependencies; } /** - * Dummy update_test_3 update 8000. + * Dummy update_test_3 update 8001. */ -function update_test_3_update_8000() { +function update_test_3_update_8001() { } diff --git a/core/modules/system/tests/modules/update_test_invalid_hook/update_test_invalid_hook.info.yml b/core/modules/system/tests/modules/update_test_invalid_hook/update_test_invalid_hook.info.yml new file mode 100644 index 0000000..a41ace9 --- /dev/null +++ b/core/modules/system/tests/modules/update_test_invalid_hook/update_test_invalid_hook.info.yml @@ -0,0 +1,7 @@ +name: 'Update test with an invalid hook_update_8000().' +type: module +description: 'Support module for update testing.' +package: Testing +version: VERSION +core: 8.x +hidden: true diff --git a/core/modules/system/tests/modules/update_test_invalid_hook/update_test_invalid_hook.install b/core/modules/system/tests/modules/update_test_invalid_hook/update_test_invalid_hook.install new file mode 100644 index 0000000..c1160fa --- /dev/null +++ b/core/modules/system/tests/modules/update_test_invalid_hook/update_test_invalid_hook.install @@ -0,0 +1,13 @@ +