security update for contrib modules
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Shared functionality to make the rest of the tests simpler.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for testing a module's custom tags.
|
||||
*/
|
||||
abstract class BmTestBase extends DrupalWebTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp(array $modules = array()) {
|
||||
$modules[] = 'backup_migrate';
|
||||
parent::setUp($modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log in as user 1.
|
||||
*
|
||||
* The benefit of doing this is that it ignores permissions entirely, so the
|
||||
* raw functionality can be tested.
|
||||
*/
|
||||
protected function loginUser1() {
|
||||
// Load user 1.
|
||||
$account = user_load(1, TRUE);
|
||||
|
||||
// Reset the password.
|
||||
$password = user_password();
|
||||
$edit = array(
|
||||
'pass' => $password,
|
||||
);
|
||||
user_save($account, $edit);
|
||||
$account->pass_raw = $password;
|
||||
|
||||
// Login.
|
||||
$this->drupalLogin($account);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function verbose($message, $title = NULL) {
|
||||
// Handle arrays, objects, etc.
|
||||
if (!is_string($message)) {
|
||||
$message = "<pre>\n" . print_r($message, TRUE) . "\n</pre>\n";
|
||||
}
|
||||
|
||||
// Optional title to go before the output.
|
||||
if (!empty($title)) {
|
||||
$title = '<h2>' . check_plain($title) . "</h2>\n";
|
||||
}
|
||||
|
||||
parent::verbose($title . $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that a selector has the expected items.
|
||||
*/
|
||||
protected function assertSelectOptions($select_id, array $options, $message = '') {
|
||||
$elements = $this
|
||||
->xpath('//select[@id=:id]//option', array(
|
||||
':id' => $select_id,
|
||||
));
|
||||
$results = $this->assertEqual(count($elements), count($options), t('The same number of items were found as were requested'));
|
||||
$this->verbose($elements);
|
||||
|
||||
foreach ($options as $option) {
|
||||
$elements = $this
|
||||
->xpath('//select[@id=:id]//option[@value=:option]', array(
|
||||
':id' => $select_id,
|
||||
':option' => $option,
|
||||
));
|
||||
$this->verbose($elements);
|
||||
$results *= $this->assertTrue(isset($elements[0]), $message ? $message : t('Option @option for field @id is present.', array(
|
||||
'@option' => $option,
|
||||
'@id' => $select_id,
|
||||
)), t('Browser'));
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that a specific selector does not have items selected.
|
||||
*/
|
||||
protected function assertNoOptionsSelected($id, $message = '') {
|
||||
$elements = $this
|
||||
->xpath('//select[@id=:id]//option[@selected="selected"]', array(
|
||||
':id' => $id,
|
||||
));
|
||||
return $this
|
||||
->assertTrue(!isset($elements[0]), $message ? $message : t('Field @id does not have any selected items.', array(
|
||||
'@id' => $id,
|
||||
)), t('Browser'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out which compressor systems are supported by PHP.
|
||||
*
|
||||
* @return array
|
||||
* The list of supported compressors. Will always include the item 'none'.
|
||||
*/
|
||||
protected function supportedCompressors() {
|
||||
$items = array('none');
|
||||
|
||||
// Work out which systems are supported.
|
||||
if (@function_exists("gzencode")) {
|
||||
$items[] = 'gzip';
|
||||
}
|
||||
if (@function_exists("bzcompress")) {
|
||||
$items[] = 'bzip';
|
||||
}
|
||||
if (class_exists('ZipArchive')) {
|
||||
$items[] = 'zip';
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the files in a specific destination.
|
||||
*
|
||||
* @param string $destination_id
|
||||
* The ID of the destination to check. Defaults to the manual file path.
|
||||
*
|
||||
* @return array
|
||||
* The backup files found in the requested backup destination.
|
||||
*/
|
||||
protected function listBackupFiles($destination_id = 'manual') {
|
||||
$items = array();
|
||||
|
||||
backup_migrate_include('destinations');
|
||||
|
||||
// Load the destination object.
|
||||
$destination = backup_migrate_get_destination($destination_id);
|
||||
if (!empty($destination)) {
|
||||
$items = $destination->list_files();
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a specific backup.
|
||||
*
|
||||
* @param string $destination_id
|
||||
* The ID of the destination to check. Defaults to the manual file path.
|
||||
*/
|
||||
protected function runBackup($destination_id = 'manual') {
|
||||
$this->drupalGet(BACKUP_MIGRATE_MENU_PATH);
|
||||
$this->assertResponse(200);
|
||||
$edit = array(
|
||||
'destination_id' => $destination_id,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, 'Backup now');
|
||||
$this->assertResponse(200);
|
||||
// Confirm the response is as expected. This is split up into separate
|
||||
// pieces because it'd be more effort than is necessary right now to confirm
|
||||
// what the exact filename is.
|
||||
$this->assertText('Default Database backed up successfully');
|
||||
$this->assertText('in destination');
|
||||
$this->assertLink('download');
|
||||
$this->assertLink('restore');
|
||||
$this->assertLink('delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all of the files in a specific backup destination.
|
||||
*
|
||||
* @param string $destination_id
|
||||
* The ID of the destination to check. Defaults to the manual file path.
|
||||
*/
|
||||
protected function deleteBackups($destination_id = 'manual') {
|
||||
$destination = backup_migrate_get_destination($destination_id);
|
||||
$files = $this->listBackupFiles($destination_id);
|
||||
if (!empty($files)) {
|
||||
foreach ($files as $file_id => $file) {
|
||||
$destination->delete_file($file_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out whether a backup filename includes a timestamp.
|
||||
*
|
||||
* @param object $file
|
||||
* The backup file to examine.
|
||||
*
|
||||
* @return mixed
|
||||
* Returns 1 if found, 0 if not found, FALSE if an error occurs.
|
||||
*/
|
||||
protected function fileHasTimestamp($file) {
|
||||
// Get the default filename, this is used later.
|
||||
backup_migrate_include('files');
|
||||
$default_filename = _backup_migrate_default_filename();
|
||||
$ext = implode('.', $file->ext);
|
||||
$pattern = "/{$default_filename}-(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d)-(\d\d)-(\d\d).{$ext}/";
|
||||
|
||||
return preg_match($pattern, $file->file_info['filename']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that a backup filename includes a timestamp.
|
||||
*
|
||||
* @param object $file
|
||||
* The backup file to examine.
|
||||
*
|
||||
* @return bool
|
||||
* Indicates whether the file includes a timestamp.
|
||||
*/
|
||||
protected function assertFileTimestamp($file) {
|
||||
return $this->assertTrue($this->fileHasTimestamp($file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that a backup filename does not include a timestamp.
|
||||
*
|
||||
* @param object $file
|
||||
* The backup file to examine.
|
||||
*
|
||||
* @return bool
|
||||
* Indicates whether the file does not include a timestamp.
|
||||
*/
|
||||
protected function assertNoFileTimestamp($file) {
|
||||
return !$this->assertFalse($this->fileHasTimestamp($file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a profile.
|
||||
*
|
||||
* @param string $profile_id
|
||||
* The name of the profile to load. Defaults to 'default'.
|
||||
*
|
||||
* @return object
|
||||
* The profile object.
|
||||
*/
|
||||
protected function getProfile($profile_id = 'default') {
|
||||
backup_migrate_include('profiles');
|
||||
return backup_migrate_get_profile($profile_id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests for different parts of the Backup Migrate system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test that the front page still loads.
|
||||
*/
|
||||
class BmTestBasics extends BmTestBase {
|
||||
|
||||
/**
|
||||
* Define this test class.
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Basic tests',
|
||||
'description' => 'Run through basic scenarios and functionality.',
|
||||
'group' => 'backup_migrate',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp(array $modules = array()) {
|
||||
parent::setUp($modules);
|
||||
|
||||
// Log in as user 1, so that permissions are irrelevant.
|
||||
$this->loginUser1();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the main page has the expected functionality available.
|
||||
*/
|
||||
public function testMainPage() {
|
||||
// Load the main B&M page.
|
||||
$this->drupalGet(BACKUP_MIGRATE_MENU_PATH);
|
||||
$this->assertResponse(200);
|
||||
|
||||
// @todo Confirm each of the tabs are present.
|
||||
// @todo Confirm each of the local tasks are present.
|
||||
// Confirm the form has the expected fields.
|
||||
$this->assertFieldByName('source_id');
|
||||
$this->assertFieldByName('destination_id');
|
||||
$this->assertFieldByName('profile_id');
|
||||
$this->assertFieldByName('copy');
|
||||
$this->assertFieldByName('copy_destination_id');
|
||||
$this->assertFieldByName('description_enabled');
|
||||
// This item should not have a value "selected", it just defaults to the
|
||||
// first item being the active item.
|
||||
$items = array('db', 'files', 'archive');
|
||||
$this->assertSelectOptions('edit-source-id', $items);
|
||||
$this->assertNoOptionsSelected('edit-source-id');
|
||||
// This item should have a value "selected", not just the first item.
|
||||
$items = array('manual', 'download', 'nodesquirrel');
|
||||
$this->assertSelectOptions('edit-destination-id', $items);
|
||||
$this->assertOptionSelected('edit-destination-id', 'download');
|
||||
// This item should not have a value "selected", it just defaults to the
|
||||
// first item being the active item.
|
||||
$items = array('default');
|
||||
$this->assertSelectOptions('edit-profile-id', $items);
|
||||
$this->assertNoOptionsSelected('edit-profile-id');
|
||||
// This item should not have a value "selected", it just defaults to the
|
||||
// first item being the active item.
|
||||
$items = array('manual', 'download', 'nodesquirrel');
|
||||
$this->assertSelectOptions('edit-copy-destination-id', $items);
|
||||
$this->assertNoOptionsSelected('edit-copy-destination-id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the initial backup process works.
|
||||
*/
|
||||
public function testFirstBackup() {
|
||||
// Load the main B&M page.
|
||||
$this->drupalGet(BACKUP_MIGRATE_MENU_PATH);
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Generate a backup and confirm it was created correctly.
|
||||
$edit = array(
|
||||
'destination_id' => 'manual',
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, 'Backup now');
|
||||
$this->assertResponse(200);
|
||||
// Confirm the response is as expected. This is split up into separate
|
||||
// pieces because it'd be more effort than is necessary right now to confirm
|
||||
// what the exact filename is.
|
||||
$this->assertText('Default Database backed up successfully');
|
||||
$this->assertText('in destination Manual Backups Directory');
|
||||
$this->assertLink('download');
|
||||
$this->assertLink('restore');
|
||||
$this->assertLink('delete');
|
||||
|
||||
// Try requesting the backup file.
|
||||
$xpath = $this
|
||||
->xpath('//a[normalize-space(text())=:label]', array(
|
||||
':label' => 'download',
|
||||
));
|
||||
$this->verbose($xpath);
|
||||
$this->assertTrue(isset($xpath[0]['href']));
|
||||
$this->assertNotNull($xpath[0]['href']);
|
||||
// @todo This doesn't work on drupalci, so work out how to fix it.
|
||||
// $this->drupalGet($xpath[0]['href']);
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// @todo Test permissions.
|
||||
// @todo Test admin forms.
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests the profiles functionality.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test that the front page still loads.
|
||||
*/
|
||||
class BmTestProfiles extends BmTestBase {
|
||||
|
||||
/**
|
||||
* Define this test class.
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Destination tests',
|
||||
'description' => 'Run through basic scenarios and functionality.',
|
||||
'group' => 'backup_migrate',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp(array $modules = array()) {
|
||||
parent::setUp($modules);
|
||||
|
||||
// Log in as user 1, so that permissions are irrelevant.
|
||||
$this->loginUser1();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the profile page has the expected functionality available.
|
||||
*/
|
||||
public function testProfilePage() {
|
||||
// Load the main B&M page.
|
||||
$this->drupalGet(BACKUP_MIGRATE_MENU_PATH . '/settings');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Confirm the page has the expected settings details.
|
||||
$this->assertText('Settings Profiles');
|
||||
$this->assertText('Default Settings');
|
||||
$this->assertLink('Create a new settings profile');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm adding a new backup process works.
|
||||
*/
|
||||
public function testAddDefaultProfile() {
|
||||
// Load the main B&M page.
|
||||
$this->drupalGet(BACKUP_MIGRATE_MENU_PATH . '/settings/profile/add');
|
||||
$this->assertResponse(200);
|
||||
|
||||
backup_migrate_include('files', 'profiles');
|
||||
$filename = _backup_migrate_default_filename();
|
||||
$defaults = _backup_migrate_profile_default_profile();
|
||||
|
||||
// Verify all of the expected fields exist.
|
||||
$this->assertFieldByName('name');
|
||||
$this->assertFieldByName('name', 'Untitled Profile');
|
||||
$this->assertFieldByName('machine_name');
|
||||
$this->assertFieldByName('filename');
|
||||
$this->assertFieldByName('filename', $filename);
|
||||
// @todo Confirm all of the expected options are present.
|
||||
$this->assertFieldByName('append_timestamp');
|
||||
$this->assertFieldByName('timestamp_format');
|
||||
$this->assertFieldByName('timestamp_format', $defaults['timestamp_format']);
|
||||
$this->assertFieldByName('filters[compression]');
|
||||
$items = $this->supportedCompressors();
|
||||
$this->assertSelectOptions('edit-filters-compression', $items);
|
||||
$this->assertOptionSelected('edit-filters-compression', 'gzip');
|
||||
$this->assertFieldByName('filters[sources][db][exclude_tables][]');
|
||||
$this->assertFieldByName('filters[sources][db][nodata_tables][]');
|
||||
$this->assertFieldByName('filters[sources][db][utils_lock_tables]');
|
||||
$this->assertFieldByName('filters[sources][files][exclude_filepaths]');
|
||||
$this->assertFieldByName('filters[sources][archive][exclude_filepaths]');
|
||||
$this->assertFieldByName('filters[utils_site_offline]');
|
||||
$this->assertFieldByName('filters[utils_site_offline_message]');
|
||||
$this->assertFieldByName('filters[utils_description]');
|
||||
$this->assertFieldByName('filters[use_cli]');
|
||||
$this->assertFieldByName('filters[ignore_errors]');
|
||||
$this->assertFieldByName('filters[notify_success_enable]');
|
||||
$this->assertFieldByName('filters[notify_success_email]');
|
||||
$this->assertFieldByName('filters[notify_failure_enable]');
|
||||
$this->assertFieldByName('filters[notify_failure_email]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the backup filename processes work as expected.
|
||||
*/
|
||||
public function testFilenameOptions() {
|
||||
// Load the profile. This will be interacted with directly because otherwise
|
||||
// the number of form fields will likely make it impossible to execute
|
||||
// properly due to the max_input_vars setting defaulting to 1000.
|
||||
$profile = $this->getProfile();
|
||||
|
||||
// Run a backup.
|
||||
$this->runBackup();
|
||||
|
||||
// Confirm that there is only one file and it has a timestamp of some sort.
|
||||
$files1 = $this->listBackupFiles();
|
||||
$this->verbose($files1);
|
||||
$this->assertTrue(count($files1) === 1, 'One backup file was found.');
|
||||
$this->assertFileTimestamp(array_shift($files1));
|
||||
|
||||
// Run another backup.
|
||||
$this->runBackup();
|
||||
|
||||
// Confirm that there are two backup files.
|
||||
$files1b = $this->listBackupFiles();
|
||||
$this->verbose($files1b);
|
||||
$this->assertTrue(count($files1b) === 2, 'Two backup files were found.');
|
||||
|
||||
// Cleanup before the next test - purge existing backups.
|
||||
$this->deleteBackups();
|
||||
|
||||
// Change settings to "create separate backups".
|
||||
$profile->append_timestamp = 0;
|
||||
$profile->save();
|
||||
|
||||
// Run a backup.
|
||||
$this->runBackup();
|
||||
|
||||
// Confirm that separate files are retained.
|
||||
$files2 = $this->listBackupFiles();
|
||||
$this->verbose($files2);
|
||||
$this->assertTrue(count($files2) === 1, 'One backup file was found.');
|
||||
$this->assertNoFileTimestamp(array_shift($files2));
|
||||
|
||||
// Run another backup.
|
||||
$this->runBackup();
|
||||
|
||||
// Confirm that separate files are retained.
|
||||
$files2b = $this->listBackupFiles();
|
||||
$this->verbose($files2b);
|
||||
$this->assertTrue(count($files2b) === 2, 'Two backup files were found.');
|
||||
|
||||
// Cleanup before the next test - purge existing backups.
|
||||
$this->deleteBackups();
|
||||
|
||||
// Change settings to "overwrite".
|
||||
$profile->append_timestamp = 2;
|
||||
$profile->save();
|
||||
|
||||
// Run a backup.
|
||||
$this->runBackup();
|
||||
|
||||
// Confirm that a new file was created.
|
||||
$files3 = $this->listBackupFiles();
|
||||
$this->verbose($files3);
|
||||
$this->assertTrue(count($files3) === 1, 'One backup file was found.');
|
||||
$this->assertNoFileTimestamp(array_shift($files3));
|
||||
|
||||
// Run the backup again.
|
||||
$this->runBackup();
|
||||
|
||||
// Confirm that a new file was not created.
|
||||
$files3b = $this->listBackupFiles();
|
||||
$this->verbose($files3b);
|
||||
$this->assertTrue(count($files3b) === 1, 'One backup file was found.');
|
||||
|
||||
// Cleanup - purge all backups.
|
||||
$this->deleteBackups();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user