Commit 5756615d authored by catch's avatar catch

Issue #2498625 by jhedstrom, larowlan: Write tests that ensure hook_update_N is properly run

parent 691697f3
This diff is collapsed.
<?php
/**
* @file
* Contains \Drupal\system\Tests\Update\UpdatePathTestBase.
*/
namespace Drupal\system\Tests\Update;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Database\Database;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
use Drupal\user\Entity\User;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides a base class that loads a database as a starting point.
*/
abstract class UpdatePathTestBase extends WebTestBase {
/**
* Modules to enable after the database is loaded.
*/
protected static $modules = [];
/**
* The file path(s) to the dumped database(s) to load into the child site.
*
* @var array
*/
protected $databaseDumpFiles = [];
/**
* The install profile used in the database dump file.
*
* @var string
*/
protected $installProfile = 'standard';
/**
* Flag that indicates whether the child site has been upgraded.
*
* @var bool
*/
protected $upgradedSite = FALSE;
/**
* Array of errors triggered during the upgrade process.
*
* @var array
*/
protected $upgradeErrors = [];
/**
* Array of modules loaded when the test starts.
*
* @var array
*/
protected $loadedModules = [];
/**
* Flag to indicate whether zlib is installed or not.
*
* @var bool
*/
protected $zlibInstalled = TRUE;
/**
* Flag to indicate whether there are pending updates or not.
*
* @var bool
*/
protected $pendingUpdates = TRUE;
/**
* The update URL.
*
* @var string
*/
protected $updateUrl;
/**
* Constructs an UpdatePathTestCase object.
*
* @param $test_id
* (optional) The ID of the test. Tests with the same id are reported
* together.
*/
function __construct($test_id = NULL) {
parent::__construct($test_id);
$this->zlibInstalled = function_exists('gzopen');
// Set the update url.
$this->updateUrl = Url::fromRoute('system.db_update');
}
/**
* Overrides WebTestBase::setUp() for upgrade testing.
*
* The main difference in this method is that rather than performing the
* installation via the installer, a database is loaded. Additional work is
* then needed to set various things such as the config directories and the
* container that would normally be done via the installer.
*/
protected function setUp() {
// We are going to set a missing zlib requirement property for usage
// during the performUpgrade() and tearDown() methods. Also set that the
// tests failed.
if (!$this->zlibInstalled) {
parent::setUp();
return;
}
// These methods are called from parent::setUp().
$this->setBatch();
$this->initUserSession();
$this->prepareSettings();
// Load the database(s).
foreach ($this->databaseDumpFiles as $file) {
if (substr($file, -3) == '.gz') {
$file = "compress.zlib://$file";
}
require $file;
}
$this->initSettings();
$request = Request::createFromGlobals();
$container = $this->initKernel($request);
$this->initConfig($container);
// Add the config directories to settings.php.
drupal_install_config_directories();
// Install any additional modules.
$this->installModulesFromClassProperty($container);
// Restore the original Simpletest batch.
$this->restoreBatch();
// Rebuild and reset.
$this->rebuildAll();
// Replace User 1 with the user created here.
/** @var \Drupal\user\UserInterface $account */
$account = User::load(1);
$account->setPassword($this->rootUser->pass_raw);
$account->setEmail($this->rootUser->getEmail());
$account->setUsername($this->rootUser->getUsername());
$account->save();
}
/**
* Add settings that are missed since the installer isn't run.
*/
protected function prepareSettings() {
parent::prepareSettings();
// Remember the profile which was used.
$settings['settings']['install_profile'] = (object) [
'value' => $this->installProfile,
'required' => TRUE,
];
// Generate a hash salt.
$settings['settings']['hash_salt'] = (object) [
'value' => Crypt::randomBytesBase64(55),
'required' => TRUE,
];
// Since the installer isn't run, add the database settings here too.
$settings['databases']['default'] = (object) [
'value' => Database::getConnectionInfo(),
'required' => TRUE,
];
$this->writeSettings($settings);
}
/**
* Helper function to run pending database updates.
*/
protected function runUpdates() {
if (!$this->zlibInstalled) {
$this->fail('Missing zlib requirement for upgrade tests.');
return FALSE;
}
$this->drupalLogin($this->rootUser);
$this->drupalGet($this->updateUrl);
$this->clickLink(t('Continue'));
// Run the update hooks.
$this->clickLink(t('Apply pending updates'));
}
}
<?php
/**
* @file
* Contains \Drupal\system\Tests\Update\UpdatePathTestBaseTest.php
*/
namespace Drupal\system\Tests\Update;
use Drupal\Component\Utility\SafeMarkup;
/**
* Tests the update path base class.
*
* @group Update
*/
class UpdatePathTestBaseTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['update_test_schema'];
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->databaseDumpFiles = [__DIR__ . '/../../../tests/fixtures/update/drupal-8.beta11.bare.standard.php.gz'];
parent::setUp();
}
/**
* Tests that the database was properly loaded.
*/
public function testDatabaseLoaded() {
foreach (['user', 'node', 'system', 'update_test_schema'] as $module) {
$this->assertEqual(drupal_get_installed_schema_version($module), 8000, SafeMarkup::format('Module @module schema is 8000', ['@module' => $module]));
}
$this->assertEqual(\Drupal::config('system.site')->get('name'), 'Site-Install');
$this->drupalGet('<front>');
$this->assertText('Site-Install');
}
/**
* Test that updates are properly run.
*/
public function testUpdateHookN() {
// Increment the schema version.
\Drupal::state()->set('update_test_schema_version', 8001);
$this->runUpdates();
// Ensure schema has changed.
$this->assertEqual(drupal_get_installed_schema_version('update_test_schema', TRUE), 8001);
// Ensure the index was added for column a.
$this->assertTrue(db_index_exists('update_test_schema_table', 'test'), 'Version 8001 of the update_test_schema module is installed.');
}
}
<?php
/**
* Contains \Drupal\system\Tests\Update\UpdateSchemaTest.
*/
namespace Drupal\system\Tests\Update;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
/**
* Tests that update hooks are properly run.
*
* @group Update
*/
class UpdateSchemaTest extends WebTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['update_test_schema'];
/**
* @var \Drupal\user\UserInterface
*/
protected $user;
/**
* The update URL.
*
* @var string
*/
protected $updateUrl;
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
require_once \Drupal::root() . '/core/includes/update.inc';
$this->user = $this->drupalCreateUser(['administer software updates', 'access site in maintenance mode']);
$this->updateUrl = Url::fromRoute('system.db_update');
}
/**
* Tests that update hooks are properly run.
*/
public function testUpdateHooks() {
// Verify that the 8000 schema is in place.
$this->assertEqual(drupal_get_installed_schema_version('update_test_schema'), 8000);
$this->assertFalse(db_index_exists('update_test_schema_table', 'test'), 'Version 8000 of the update_test_schema module is installed.');
// Increment the schema version.
\Drupal::state()->set('update_test_schema_version', 8001);
$this->drupalLogin($this->user);
$this->drupalGet($this->updateUrl, ['external' => TRUE]);
$this->clickLink(t('Continue'));
$this->assertRaw('Schema version 8001.');
// Run the update hooks.
$this->clickLink(t('Apply pending updates'));
// Ensure schema has changed.
$this->assertEqual(drupal_get_installed_schema_version('update_test_schema', TRUE), 8001);
// Ensure the index was added for column a.
$this->assertTrue(db_index_exists('update_test_schema_table', 'test'), 'Version 8001 of the update_test_schema module is installed.');
}
}
name: 'Update test schema'
type: module
description: 'Support module for update testing.'
package: Testing
version: VERSION
core: 8.x
<?php
/**
* @file
* Update hooks and schema definition for the update_test_schema module.
*/
/**
* Implements hook_schema().
*
* The schema defined here will vary on state to allow for update hook testing.
*/
function update_test_schema_schema() {
$schema_version = \Drupal::state()->get('update_test_schema_version', 8000);
$table = [
'fields' => [
'a' => ['type' => 'int', 'not null' => TRUE],
'b' => ['type' => 'blob', 'not null' => FALSE],
],
];
switch ($schema_version) {
case 8001:
// Add the index.
$table['indexes']['test'] = ['a'];
break;
}
return ['update_test_schema_table' => $table];
}
// Update hooks are defined depending on state as well.
$schema_version = \Drupal::state()->get('update_test_schema_version', 8000);
if ($schema_version >= 8001) {
/**
* Schema version 8001.
*/
function update_test_schema_update_8001() {
// Add a column.
db_add_index('update_test_schema_table', 'test', ['a']);
}
}
......@@ -72,23 +72,23 @@ public function testToolbarCacheContextsCaller() {
// Test without user toolbar tab. User module is a required module so we have to
// manually remove the user toolbar tab.
$this->installModules(['toolbar_disable_user_toolbar']);
$this->installExtraModules(['toolbar_disable_user_toolbar']);
$this->assertToolbarCacheContexts(['user.permissions'], 'Expected cache contexts found without user toolbar tab.');
// Test with the toolbar and contextual enabled.
$this->installModules(['contextual']);
$this->installExtraModules(['contextual']);
$this->adminUser2 = $this->drupalCreateUser(array_merge($this->perms, ['access contextual links']));
$this->assertToolbarCacheContexts(['user.permissions'], 'Expected cache contexts found with contextual module enabled.');
\Drupal::service('module_installer')->uninstall(['contextual']);
// Test with the tour module enabled.
$this->installModules(['tour']);
$this->installExtraModules(['tour']);
$this->adminUser2 = $this->drupalCreateUser(array_merge($this->perms, ['access tour']));
$this->assertToolbarCacheContexts(['user.permissions'], 'Expected cache contexts found with tour module enabled.');
\Drupal::service('module_installer')->uninstall(['tour']);
// Test with shortcut module enabled.
$this->installModules(['shortcut']);
$this->installExtraModules(['shortcut']);
$this->adminUser2 = $this->drupalCreateUser(array_merge($this->perms, ['access shortcuts', 'administer shortcuts']));
$this->assertToolbarCacheContexts(['user'], 'Expected cache contexts found with shortcut module enabled.');
}
......@@ -138,7 +138,7 @@ protected function assertToolbarCacheContexts(array $cache_contexts, $message =
* @param string[] $module_list
* An array of module names.
*/
protected function installModules(array $module_list) {
protected function installExtraModules(array $module_list) {
\Drupal::service('module_installer')->install($module_list);
// Installing modules updates the container and needs a router rebuild.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment