Issue #2498625 by jhedstrom, larowlan: Write tests that ensure hook_update_N is properly run
parent
691697f39c
commit
5756615df3
|
@ -20,6 +20,7 @@ use Drupal\Core\Database\Database;
|
|||
use Drupal\Core\DrupalKernel;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
|
||||
use Drupal\Core\Extension\MissingDependencyException;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Session\AnonymousUserSession;
|
||||
|
@ -28,6 +29,7 @@ use Drupal\Core\Site\Settings;
|
|||
use Drupal\Core\StreamWrapper\PublicStream;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
|
@ -188,12 +190,20 @@ abstract class WebTestBase extends TestBase {
|
|||
*/
|
||||
protected $customTranslations;
|
||||
|
||||
/**
|
||||
* The class loader to use for installation and initialization of setup.
|
||||
*
|
||||
* @var \Symfony\Component\Classloader\Classloader
|
||||
*/
|
||||
protected $classLoader;
|
||||
|
||||
/**
|
||||
* Constructor for \Drupal\simpletest\WebTestBase.
|
||||
*/
|
||||
function __construct($test_id = NULL) {
|
||||
parent::__construct($test_id);
|
||||
$this->skipClasses[__CLASS__] = TRUE;
|
||||
$this->classLoader = require DRUPAL_ROOT . '/autoload.php';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -621,32 +631,57 @@ abstract class WebTestBase extends TestBase {
|
|||
* being executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
// When running tests through the Simpletest UI (vs. on the command line),
|
||||
// Simpletest's batch conflicts with the installer's batch. Batch API does
|
||||
// not support the concept of nested batches (in which the nested is not
|
||||
// progressive), so we need to temporarily pretend there was no batch.
|
||||
// Backup the currently running Simpletest batch.
|
||||
$this->originalBatch = batch_get();
|
||||
// Preserve original batch for later restoration.
|
||||
$this->setBatch();
|
||||
|
||||
// Define information about the user 1 account.
|
||||
$this->rootUser = new UserSession(array(
|
||||
'uid' => 1,
|
||||
'name' => 'admin',
|
||||
'mail' => 'admin@example.com',
|
||||
'pass_raw' => $this->randomMachineName(),
|
||||
));
|
||||
|
||||
// The child site derives its session name from the database prefix when
|
||||
// running web tests.
|
||||
$this->generateSessionName($this->databasePrefix);
|
||||
|
||||
// Reset the static batch to remove Simpletest's batch operations.
|
||||
$batch = &batch_get();
|
||||
$batch = array();
|
||||
// Initialize user 1 and session name.
|
||||
$this->initUserSession();
|
||||
|
||||
// Get parameters for install_drupal() before removing global variables.
|
||||
$parameters = $this->installParameters();
|
||||
|
||||
// Prepare the child site settings.
|
||||
$this->prepareSettings();
|
||||
|
||||
// Execute the non-interactive installer.
|
||||
$this->doInstall($parameters);
|
||||
|
||||
// Import new settings.php written by the installer.
|
||||
$this->initSettings();
|
||||
|
||||
// Initialize the request and container post-install.
|
||||
$container = $this->initKernel(\Drupal::request());
|
||||
|
||||
// Initialize and override certain configurations.
|
||||
$this->initConfig($container);
|
||||
|
||||
// Collect modules to install.
|
||||
$this->installModulesFromClassProperty($container);
|
||||
|
||||
// Restore the original batch.
|
||||
$this->restoreBatch();
|
||||
|
||||
// Reset/rebuild everything.
|
||||
$this->rebuildAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the non-interactive installer.
|
||||
*
|
||||
* @param array $parameters
|
||||
* Parameters to pass to install_drupal().
|
||||
*
|
||||
* @see install_drupal()
|
||||
*/
|
||||
protected function doInstall(array $parameters = []) {
|
||||
require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
|
||||
install_drupal($this->classLoader, $this->installParameters());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares site settings and services before installation.
|
||||
*/
|
||||
protected function prepareSettings() {
|
||||
// Prepare installer settings that are not install_drupal() parameters.
|
||||
// Copy and prepare an actual settings.php, so as to resemble a regular
|
||||
// installation.
|
||||
|
@ -658,32 +693,32 @@ abstract class WebTestBase extends TestBase {
|
|||
// All file system paths are created by System module during installation.
|
||||
// @see system_requirements()
|
||||
// @see TestBase::prepareEnvironment()
|
||||
$settings['settings']['file_public_path'] = (object) array(
|
||||
$settings['settings']['file_public_path'] = (object) [
|
||||
'value' => $this->publicFilesDirectory,
|
||||
'required' => TRUE,
|
||||
);
|
||||
$settings['settings']['file_private_path'] = (object) array(
|
||||
];
|
||||
$settings['settings']['file_private_path'] = (object) [
|
||||
'value' => $this->privateFilesDirectory,
|
||||
'required' => TRUE,
|
||||
);
|
||||
];
|
||||
// Save the original site directory path, so that extensions in the
|
||||
// site-specific directory can still be discovered in the test site
|
||||
// environment.
|
||||
// @see \Drupal\Core\Extension\ExtensionDiscovery::scan()
|
||||
$settings['settings']['test_parent_site'] = (object) array(
|
||||
$settings['settings']['test_parent_site'] = (object) [
|
||||
'value' => $this->originalSite,
|
||||
'required' => TRUE,
|
||||
);
|
||||
];
|
||||
// Add the parent profile's search path to the child site's search paths.
|
||||
// @see \Drupal\Core\Extension\ExtensionDiscovery::getProfileDirectories()
|
||||
$settings['conf']['simpletest.settings']['parent_profile'] = (object) array(
|
||||
$settings['conf']['simpletest.settings']['parent_profile'] = (object) [
|
||||
'value' => $this->originalProfile,
|
||||
'required' => TRUE,
|
||||
);
|
||||
$settings['settings']['apcu_ensure_unique_prefix'] = (object) array(
|
||||
];
|
||||
$settings['settings']['apcu_ensure_unique_prefix'] = (object) [
|
||||
'value' => FALSE,
|
||||
'required' => TRUE,
|
||||
);
|
||||
];
|
||||
$this->writeSettings($settings);
|
||||
// Allow for test-specific overrides.
|
||||
$settings_testing_file = DRUPAL_ROOT . '/' . $this->originalSite . '/settings.testing.php';
|
||||
|
@ -714,15 +749,14 @@ abstract class WebTestBase extends TestBase {
|
|||
// Since Drupal is bootstrapped already, install_begin_request() will not
|
||||
// bootstrap again. Hence, we have to reload the newly written custom
|
||||
// settings.php manually.
|
||||
$class_loader = require DRUPAL_ROOT . '/autoload.php';
|
||||
Settings::initialize(DRUPAL_ROOT, $this->siteDirectory, $class_loader);
|
||||
Settings::initialize(DRUPAL_ROOT, $this->siteDirectory, $this->classLoader);
|
||||
}
|
||||
|
||||
// Execute the non-interactive installer.
|
||||
require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
|
||||
install_drupal($class_loader, $parameters);
|
||||
|
||||
// Import new settings.php written by the installer.
|
||||
Settings::initialize(DRUPAL_ROOT, $this->siteDirectory, $class_loader);
|
||||
/**
|
||||
* Initialize settings created during install.
|
||||
*/
|
||||
protected function initSettings() {
|
||||
Settings::initialize(DRUPAL_ROOT, $this->siteDirectory, $this->classLoader);
|
||||
foreach ($GLOBALS['config_directories'] as $type => $path) {
|
||||
$this->configDirectories[$type] = $path;
|
||||
}
|
||||
|
@ -733,15 +767,16 @@ abstract class WebTestBase extends TestBase {
|
|||
// directory has to be writable.
|
||||
// TestBase::restoreEnvironment() will delete the entire site directory.
|
||||
// Not using File API; a potential error must trigger a PHP warning.
|
||||
chmod($directory, 0777);
|
||||
|
||||
$request = \Drupal::request();
|
||||
$this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', TRUE);
|
||||
$this->kernel->prepareLegacyRequest($request);
|
||||
// Force the container to be built from scratch instead of loaded from the
|
||||
// disk. This forces us to not accidentally load the parent site.
|
||||
$container = $this->kernel->rebuildContainer();
|
||||
chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize various configurations post-installation.
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
|
||||
* The container.
|
||||
*/
|
||||
protected function initConfig(ContainerInterface $container) {
|
||||
$config = $container->get('config.factory');
|
||||
|
||||
// Manually create and configure private and temporary files directories.
|
||||
|
@ -773,34 +808,12 @@ abstract class WebTestBase extends TestBase {
|
|||
->set('css.preprocess', FALSE)
|
||||
->set('js.preprocess', FALSE)
|
||||
->save();
|
||||
}
|
||||
|
||||
// Collect modules to install.
|
||||
$class = get_class($this);
|
||||
$modules = array();
|
||||
while ($class) {
|
||||
if (property_exists($class, 'modules')) {
|
||||
$modules = array_merge($modules, $class::$modules);
|
||||
}
|
||||
$class = get_parent_class($class);
|
||||
}
|
||||
if ($modules) {
|
||||
$modules = array_unique($modules);
|
||||
try {
|
||||
$success = $container->get('module_installer')->install($modules, TRUE);
|
||||
$this->assertTrue($success, SafeMarkup::format('Enabled modules: %modules', array('%modules' => implode(', ', $modules))));
|
||||
}
|
||||
catch (\Drupal\Core\Extension\MissingDependencyException $e) {
|
||||
// The exception message has all the details.
|
||||
$this->fail($e->getMessage());
|
||||
}
|
||||
|
||||
$this->rebuildContainer();
|
||||
}
|
||||
|
||||
// Restore the original Simpletest batch.
|
||||
$batch = &batch_get();
|
||||
$batch = $this->originalBatch;
|
||||
|
||||
/**
|
||||
* Reset and rebuild the environment after setup.
|
||||
*/
|
||||
protected function rebuildAll() {
|
||||
// Reset/rebuild all data structures after enabling the modules, primarily
|
||||
// to synchronize all data structures and caches between the test runner and
|
||||
// the child site.
|
||||
|
@ -808,7 +821,7 @@ abstract class WebTestBase extends TestBase {
|
|||
// @todo Test-specific setUp() methods may set up further fixtures; find a
|
||||
// way to execute this after setUp() is done, or to eliminate it entirely.
|
||||
$this->resetAll();
|
||||
$this->kernel->prepareLegacyRequest($request);
|
||||
$this->kernel->prepareLegacyRequest(\Drupal::request());
|
||||
|
||||
// Explicitly call register() again on the container registered in \Drupal.
|
||||
// @todo This should already be called through
|
||||
|
@ -822,6 +835,9 @@ abstract class WebTestBase extends TestBase {
|
|||
*
|
||||
* @see install_drupal()
|
||||
* @see install_state_defaults()
|
||||
*
|
||||
* @return array
|
||||
* Array of parameters for use in install_drupal().
|
||||
*/
|
||||
protected function installParameters() {
|
||||
$connection_info = Database::getConnectionInfo();
|
||||
|
@ -879,6 +895,97 @@ abstract class WebTestBase extends TestBase {
|
|||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preserve the original batch, and instantiate the test batch.
|
||||
*/
|
||||
protected function setBatch() {
|
||||
// When running tests through the Simpletest UI (vs. on the command line),
|
||||
// Simpletest's batch conflicts with the installer's batch. Batch API does
|
||||
// not support the concept of nested batches (in which the nested is not
|
||||
// progressive), so we need to temporarily pretend there was no batch.
|
||||
// Backup the currently running Simpletest batch.
|
||||
$this->originalBatch = batch_get();
|
||||
|
||||
// Reset the static batch to remove Simpletest's batch operations.
|
||||
$batch = &batch_get();
|
||||
$batch = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the original batch.
|
||||
*
|
||||
* @see ::setBatch
|
||||
*/
|
||||
protected function restoreBatch() {
|
||||
// Restore the original Simpletest batch.
|
||||
$batch = &batch_get();
|
||||
$batch = $this->originalBatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes user 1 for the site to be installed.
|
||||
*/
|
||||
protected function initUserSession() {
|
||||
// Define information about the user 1 account.
|
||||
$this->rootUser = new UserSession(array(
|
||||
'uid' => 1,
|
||||
'name' => 'admin',
|
||||
'mail' => 'admin@example.com',
|
||||
'pass_raw' => $this->randomMachineName(),
|
||||
));
|
||||
|
||||
// The child site derives its session name from the database prefix when
|
||||
// running web tests.
|
||||
$this->generateSessionName($this->databasePrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the kernel after installation.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* Request object.
|
||||
*
|
||||
* @return \Symfony\Component\DependencyInjection\ContainerInterface
|
||||
* The container.
|
||||
*/
|
||||
protected function initKernel(Request $request) {
|
||||
$this->kernel = DrupalKernel::createFromRequest($request, $this->classLoader, 'prod', TRUE);
|
||||
$this->kernel->prepareLegacyRequest($request);
|
||||
// Force the container to be built from scratch instead of loaded from the
|
||||
// disk. This forces us to not accidentally load the parent site.
|
||||
return $this->kernel->rebuildContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Install modules defined by `static::$modules`.
|
||||
*
|
||||
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
|
||||
* The container.
|
||||
*/
|
||||
protected function installModulesFromClassProperty(ContainerInterface $container) {
|
||||
$class = get_class($this);
|
||||
$modules = [];
|
||||
while ($class) {
|
||||
if (property_exists($class, 'modules')) {
|
||||
$modules = array_merge($modules, $class::$modules);
|
||||
}
|
||||
$class = get_parent_class($class);
|
||||
}
|
||||
if ($modules) {
|
||||
$modules = array_unique($modules);
|
||||
try {
|
||||
$success = $container->get('module_installer')->install($modules, TRUE);
|
||||
$this->assertTrue($success, SafeMarkup::format('Enabled modules: %modules', ['%modules' => implode(', ', $modules)]));
|
||||
}
|
||||
catch (MissingDependencyException $e) {
|
||||
// The exception message has all the details.
|
||||
$this->fail($e->getMessage());
|
||||
}
|
||||
|
||||
$this->rebuildContainer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all supported database driver installer objects.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
<?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'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?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.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?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.');
|
||||
}
|
||||
|
||||
}
|
BIN
core/modules/system/tests/fixtures/update/drupal-8.beta11.bare.standard.php.gz
vendored
Normal file
BIN
core/modules/system/tests/fixtures/update/drupal-8.beta11.bare.standard.php.gz
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
name: 'Update test schema'
|
||||
type: module
|
||||
description: 'Support module for update testing.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,41 @@
|
|||
<?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 @@ class ToolbarCacheContextsTest extends WebTestBase {
|
|||
|
||||
// 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 @@ class ToolbarCacheContextsTest extends WebTestBase {
|
|||
* @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.
|
||||
|
|
Loading…
Reference in New Issue