- <?php
- * @file
- * This file contains tests for the Update Manager module.
- *
- * The overarching methodology of these tests is we need to compare a given
- * state of installed modules, themes, and layouts (e.g., version, project grouping,
- * timestamps, etc) against a current state of what the release history XML
- * files we fetch say is available. We have dummy XML files (in the
- * modules/update/tests directory) that describe various scenarios of what's
- * available for different test projects, and we have dummy .info file data
- * (specified via hook_system_info_alter() in the update_test helper module)
- * describing what's currently installed. Each test case defines a set of
- * projects to install, their current state (via the 'update_test_system_info'
- * state value) and the desired available update data (via the
- * 'update_test_xml_map' state value), and then performs a series of assertions
- * that the report matches our expectations given the specific initial state and
- * availability scenario.
- */
-
- * Defines some shared functions used by all update tests.
- */
- class UpdateTestHelper extends BackdropWebTestCase {
- protected $profile = 'testing';
-
-
- * Refreshes the update status based on the desired available update scenario.
- *
- * @param $xml_map
- * Array that maps project names to availability scenarios to fetch. The key
- * '#all' is used if a project-specific mapping is not defined.
- * @param $url
- * (optional) A string containing the URL to fetch update data from.
- * Defaults to 'update-test'.
- *
- * @see update_test_mock_page()
- */
- protected function refreshUpdateStatus($xml_map, $url = 'update-test') {
- $config = config('update.settings');
-
-
- $config->set('update_url', url($url, array('absolute' => TRUE)))->save();
-
- state_set('update_test_xml_map', $xml_map);
-
- $this->backdropGet('admin/reports/updates/check');
- }
-
-
- * Runs a series of assertions that are applicable to all update statuses.
- */
- protected function assertStandardTests() {
- $this->assertRaw('<h3>' . t('Backdrop CMS') . '</h3>');
- $this->assertRaw(l(t('Backdrop CMS'), 'http://example.com/project/backdrop'), 'Link to the Backdrop CMS project appears.');
- $this->assertNoText(t('No available releases found'));
- }
-
- }
-
- class UpdateCoreTestCase extends UpdateTestHelper {
- function setUp() {
- parent::setUp(array('update_test', 'update'));
- $admin_user = $this->backdropCreateUser(array(
- 'administer site configuration',
- 'administer modules',
- 'access site reports',
- ));
- $this->backdropLogin($admin_user);
- }
-
-
- * Tests the Update Manager module when no updates are available.
- */
- function testNoUpdatesAvailable() {
- $this->setSystemInfo1_0();
- $this->refreshUpdateStatus(array('backdrop' => '0'));
- $this->assertText(t('Up to date'));
- $this->assertNoText(t('Update available'));
- $this->assertNoText(t('Security update required!'));
- }
-
-
- * Tests the Update Manager module when one normal update is available.
- */
- function testNormalUpdateAvailable() {
- $this->setSystemInfo1_0();
- $this->refreshUpdateStatus(array('backdrop' => '1'));
- $this->assertStandardTests();
- $this->assertNoText(t('Up to date'));
- $this->assertText(t('Update available'));
- $this->assertNoText(t('Security update required!'));
- $this->assertRaw(l('1.1', 'http://example.com/backdrop-1-1-release'), 'Link to release appears.');
- $this->assertRaw(l(t('Download'), 'http://example.com/backdrop-1-1.tar.gz'), 'Link to download appears.');
- $this->assertRaw(l(t('Release notes'), 'http://example.com/backdrop-1-1-release'), 'Link to release notes appears.');
- }
-
-
- * Tests the Update Manager module when a security update is available.
- */
- function testSecurityUpdateAvailable() {
- $this->setSystemInfo1_0();
- $this->refreshUpdateStatus(array('backdrop' => '2-sec'));
- $this->assertStandardTests();
- $this->assertNoText(t('Up to date'));
- $this->assertNoText(t('Update available'));
- $this->assertText(t('Security update required!'));
- $this->assertRaw(l('1.2', 'http://example.com/backdrop-1-2-release'), 'Link to release appears.');
- $this->assertRaw(l(t('Download'), 'http://example.com/backdrop-1-2.tar.gz'), 'Link to download appears.');
- $this->assertRaw(l(t('Release notes'), 'http://example.com/backdrop-1-2-release'), 'Link to release notes appears.');
- }
-
-
- * Ensures proper results where there are date mismatches among modules.
- */
- function testDatestampMismatch() {
- $system_info = array(
- '#all' => array(
-
- 'version' => '1.0-dev',
- 'datestamp' => time(),
- ),
- 'block' => array(
-
- 'datestamp' => '1000000000',
- ),
- );
- state_set('update_test_system_info', $system_info);
- $this->refreshUpdateStatus(array('backdrop' => 'dev'));
- $this->assertNoText(t('2001-Sep-'));
- $this->assertText(t('Up to date'));
- $this->assertNoText(t('Update available'));
- $this->assertNoText(t('Security update required!'));
- }
-
-
- * Checks that running cron updates the list of available updates.
- */
- function testModulePageRunCron() {
- $config = config('update.settings');
- $this->setSystemInfo1_0();
- $config->set('update_url', url('update-test', array('absolute' => TRUE)))->save();
- state_set('update_test_xml_map', array('backdrop' => '0'));
-
- $this->cronRun();
- $this->backdropGet('admin/modules');
- $this->assertNoText(t('No update information available.'));
- }
-
-
- * Checks the messages at admin/modules when the site is up to date.
- */
- function testModulePageUpToDate() {
- $this->setSystemInfo1_0();
- $config = config('update.settings');
-
- $config->set('update_url', url('update-test', array('absolute' => TRUE)))->save();
- state_set('update_test_xml_map', array('backdrop' => '0'));
-
- $this->backdropGet('admin/reports/updates');
- $this->clickLink(t('Check manually'));
- $this->assertText(t('Checked available update data for one project.'));
- $this->backdropGet('admin/modules');
- $this->assertNoText(t('There are updates available for your version of Backdrop.'));
- $this->assertNoText(t('There is a security update available for your version of Backdrop.'));
- }
-
-
- * Tests the Update Manager module when the update server returns 503 errors.
- */
- function testServiceUnavailable() {
- $this->refreshUpdateStatus(array(), '503-error');
-
- $this->assertNoText('SimpleXMLElement');
- $this->assertUniqueText(t('Failed to get available update data for one project.'));
- }
-
-
- * Tests that exactly one fetch task per project is created and not more.
- */
- function testFetchTasks() {
- $project_a = array(
- 'name' => 'aaa_update_test',
- );
- $project_b = array(
- 'name' => 'bbb_update_test',
- );
- $queue = BackdropQueue::get('update_fetch_tasks');
- $this->assertEqual($queue->numberOfItems(), 0, 'Queue is empty');
- update_create_fetch_task($project_a);
- $this->assertEqual($queue->numberOfItems(), 1, 'Queue contains one item');
- update_create_fetch_task($project_b);
- $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
-
- update_create_fetch_task($project_a);
- $this->assertEqual($queue->numberOfItems(), 2, 'Queue still contains two items');
-
-
- _update_cache_clear();
- backdrop_static_reset('_update_create_fetch_task');
- update_create_fetch_task($project_a);
- $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
- }
-
-
- * Tests _update_checking_enabled() returns the expected value during tests.
- */
- function testUpdateCheckingEnabled() {
- $config = config('update.settings');
- $this->assertEqual($config->get('update_url'), '', 'No update server specified in the default installation.');
- $this->assertFalse(_update_checking_enabled(), 'Update checking is not enabled when using the default server.');
-
- $this->backdropGet('admin/reports/updates/check');
- $this->assertText(t('Update checking is disabled on this site.'));
-
- $config->set('update_url', url('update-test', array('absolute' => TRUE)))->save();
- $config->save();
-
- $this->assertTrue(_update_checking_enabled(), 'Update checking enabled during tests when using a local host update URL.');
-
- $this->backdropGet('admin/reports/updates/check');
- $this->assertNoText(t('Update checking is disabled on this site.'));
- }
-
-
- * Test that getUpdaterFromDirectory() gets the right class for core updates.
- */
- function testGetUpdaterFromDirectory() {
- module_load_include('inc', 'installer', 'installer.manager');
-
- $extract_directory = _installer_manager_extract_directory();
- $file = backdrop_get_path('module', 'update') . '/tests/backdrop-sample.zip';
- $archive = installer_manager_archive_extract($file, $extract_directory);
- $realpath = backdrop_realpath($extract_directory . '/backdrop');
-
-
-
- $updater = Updater::factory($realpath);
- $updater_class = $updater->getUpdaterFromDirectory($realpath);
- $success = $this->assertEqual($updater_class, 'CoreUpdater', 'Determine "CoreUpdater" as updater class for core.');
- if (!$success) {
- $this->verbose("Failed to determine correct class, <em>$updater_class</em> was picked instead.");
- }
- }
-
-
- * Sets the version to 1.0 when no project-specific mapping is defined.
- */
- protected function setSystemInfo1_0() {
- $setting = array(
- '#all' => array(
- 'version' => '1.0',
- ),
- );
- state_set('update_test_system_info', $setting);
- }
-
- }
-
- class UpdateTestContribCase extends UpdateTestHelper {
- function setUp() {
- parent::setUp(array('update_test', 'update', 'aaa_update_test', 'bbb_update_test', 'ccc_update_test'));
- $admin_user = $this->backdropCreateUser(array(
- 'administer site configuration',
- 'access site reports',
- ));
- $this->backdropLogin($admin_user);
- }
-
-
- * Tests when there is no available release data for a contrib module.
- */
- function testNoReleasesAvailable() {
- $system_info = array(
- '#all' => array(
- 'version' => '1.0',
- ),
- 'aaa_update_test' => array(
- 'project' => 'aaa_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- );
- state_set('update_test_system_info', $system_info);
- $this->refreshUpdateStatus(array('backdrop' => '0', 'aaa_update_test' => 'no-releases'));
- $this->backdropGet('admin/reports/updates');
-
-
- $this->assertRaw('<h3>' . t('Backdrop CMS') . '</h3>');
- $this->assertRaw(l(t('Backdrop CMS'), 'http://example.com/project/backdrop'));
- $this->assertText(t('Up to date'));
- $this->assertRaw('<h3>' . t('Modules') . '</h3>');
- $this->assertNoText(t('Update available'));
- $this->assertText(t('No available releases found'));
- $this->assertNoRaw(l(t('AAA Update test'), 'http://example.com/project/aaa_update_test'));
- }
-
-
- * Tests the basic functionality of a contrib module on the status report.
- */
- function testUpdateContribBasic() {
- $system_info = array(
- '#all' => array(
- 'version' => '1.0',
- ),
- 'aaa_update_test' => array(
- 'project' => 'aaa_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- );
- state_set('update_test_system_info', $system_info);
- $this->refreshUpdateStatus(
- array(
- 'backdrop' => '0',
- 'aaa_update_test' => '1_0',
- )
- );
- $this->assertStandardTests();
- $this->assertText(t('Up to date'));
- $this->assertRaw('<h3>' . t('Modules') . '</h3>');
- $this->assertNoText(t('Update available'));
- $this->assertRaw(l(t('AAA Update test'), 'http://example.com/project/aaa_update_test'), 'Link to aaa_update_test project appears.');
- }
-
-
- * Tests that contrib projects are ordered by project name.
- *
- * If a project contains multiple modules, we want to make sure that the
- * available updates report is sorted by the parent project names, not by the
- * names of the modules included in each project. In this test case, we have
- * two contrib projects, "BBB Update test" and "CCC Update test". However, we
- * have a module called "aaa_update_test" that's part of the "CCC Update test"
- * project. We need to make sure that we see the "BBB" project before the
- * "CCC" project, even though "CCC" includes a module that's processed first
- * if you sort alphabetically by module name (which is the order we see things
- * inside system_rebuild_module_data() for example).
- */
- function testUpdateContribOrder() {
-
- $system_info = array(
- '#all' => array(
- 'version' => '1.0',
- ),
-
-
-
-
-
- 'aaa_update_test' => array(
- 'project' => 'ccc_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
-
-
- 'bbb_update_test' => array(
- 'project' => 'bbb_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
-
-
-
- 'ccc_update_test' => array(
- 'project' => 'ccc_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- );
- state_set('update_test_system_info', $system_info);
- $this->refreshUpdateStatus(array('backdrop' => '0', '#all' => '1_0'));
-
- $this->assertText(t('Up to date'));
- $this->assertNoText(t('Update available'));
-
-
- $this->assertText(t('AAA Update test'));
- $this->assertText(t('BBB Update test'));
- $this->assertText(t('CCC Update test'));
-
-
- $this->assertNoRaw(l(t('AAA Update test'), 'http://example.com/project/aaa_update_test'), 'Link to aaa_update_test project does not appear.');
-
- $this->assertRaw(l(t('BBB Update test'), 'http://example.com/project/bbb_update_test'), 'Link to bbb_update_test project appears.');
- $this->assertRaw(l(t('CCC Update test'), 'http://example.com/project/ccc_update_test'), 'Link to bbb_update_test project appears.');
-
-
-
-
-
- $bbb_project_link = '<div class="project"><a href="http://example.com/project/bbb_update_test">BBB Update test</a>';
- $ccc_project_link = '<div class="project"><a href="http://example.com/project/ccc_update_test">CCC Update test</a>';
- $this->assertTrue(strpos($this->backdropGetContent(), $bbb_project_link) < strpos($this->backdropGetContent(), $ccc_project_link), "'BBB Update test' project is listed before the 'CCC Update test' project");
- }
-
-
- * Tests that subthemes are notified about security updates for base themes.
- */
- function testUpdateBaseThemeSecurityUpdate() {
-
- db_update('system')
- ->fields(array('status' => 1))
- ->condition('type', 'theme')
- ->condition('name', 'update_test_subtheme')
- ->execute();
-
-
- $system_info = array(
-
- '#all' => array(
- 'version' => '1.0',
- ),
-
- 'update_test_basetheme' => array(
- 'project' => 'update_test_basetheme',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
-
- 'update_test_subtheme' => array(
- 'project' => 'update_test_subtheme',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- );
- state_set('update_test_system_info', $system_info);
- $xml_mapping = array(
- 'backdrop' => '0',
- 'update_test_subtheme' => '1_0',
- 'update_test_basetheme' => '1_1-sec',
- );
- $this->refreshUpdateStatus($xml_mapping);
- $this->assertText(t('Security update required!'));
- $this->assertRaw(l(t('Update test base theme'), 'http://example.com/project/update_test_basetheme'), 'Link to the Update test base theme project appears.');
- }
-
-
- * Tests that the admin theme is always notified about security updates.
- */
- function testUpdateAdminThemeSecurityUpdate() {
-
- db_update('system')
- ->fields(array('status' => 0))
- ->condition('type', 'theme')
- ->condition('name', 'update_test_%', 'LIKE')
- ->execute();
-
- config_set('system.core', 'admin_theme', 'update_test_admintheme');
-
-
- $system_info = array(
- '#all' => array(
- 'version' => '1.0',
- ),
- 'update_test_admintheme' => array(
- 'project' => 'update_test_admintheme',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- 'update_test_basetheme' => array(
- 'project' => 'update_test_basetheme',
- 'version' => '1.x-1.1',
- 'hidden' => FALSE,
- ),
- 'update_test_subtheme' => array(
- 'project' => 'update_test_subtheme',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- );
- state_set('update_test_system_info', $system_info);
- config_set('update.settings', 'update_check_disabled', FALSE);
- $xml_mapping = array(
-
-
- 'backdrop' => '0',
- );
- $this->refreshUpdateStatus($xml_mapping);
-
- $this->assertText('update_test_admintheme', "The admin theme is checked for update even if it's disabled");
-
- $this->assertNoText('update_test_basetheme', 'Disabled theme is not checked for update in the list.');
- $this->assertNoText('update_test_subtheme', 'Disabled theme is not checked for update in the list.');
- }
-
-
- * Tests that disabled themes are only shown when desired.
- */
- function testUpdateShowDisabledThemes() {
- $config = config('update.settings');
-
- db_update('system')
- ->fields(array('status' => 0))
- ->condition('type', 'theme')
- ->condition('name', 'update_test_%', 'LIKE')
- ->execute();
-
-
- $system_info = array(
-
- '#all' => array(
- 'version' => '1.0',
- ),
-
- 'update_test_basetheme' => array(
- 'project' => 'update_test_basetheme',
- 'version' => '1.x-1.1',
- 'hidden' => FALSE,
- ),
-
- 'update_test_subtheme' => array(
- 'project' => 'update_test_subtheme',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- );
-
-
-
-
- $config->set('update_max_attempts', 99999)->save();
- state_set('update_test_system_info', $system_info);
- $xml_mapping = array(
- 'backdrop' => '0',
- 'update_test_subtheme' => '1_0',
- 'update_test_basetheme' => '1_1-sec',
- );
- $base_theme_project_link = l(t('Update test base theme'), 'http://example.com/project/update_test_basetheme');
- $sub_theme_project_link = l(t('Update test subtheme'), 'http://example.com/project/update_test_subtheme');
- foreach (array(TRUE, FALSE) as $check_disabled) {
- $config->set('update_disabled_extensions', $check_disabled)->save();
- $this->refreshUpdateStatus($xml_mapping);
- if ($check_disabled) {
- $this->assertText(t('Themes'));
- $this->assertRaw($base_theme_project_link, 'Link to the Update test base theme project appears.');
- $this->assertRaw($sub_theme_project_link, 'Link to the Update test subtheme project appears.');
- }
- else {
- $this->assertNoText(t('Themes'));
- $this->assertNoRaw($base_theme_project_link, 'Link to the Update test base theme project does not appear.');
- $this->assertNoRaw($sub_theme_project_link, 'Link to the Update test subtheme project does not appear.');
- }
- }
- }
-
-
- * Makes sure that if we fetch from a broken URL, sane things happen.
- */
- function testUpdateBrokenFetchURL() {
- $system_info = array(
- '#all' => array(
- 'version' => '1.0',
- ),
- 'aaa_update_test' => array(
- 'project' => 'aaa_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- 'bbb_update_test' => array(
- 'project' => 'bbb_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- 'ccc_update_test' => array(
- 'project' => 'ccc_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- );
- state_set('update_test_system_info', $system_info);
-
- $xml_mapping = array(
- 'backdrop' => '0',
- 'aaa_update_test' => '1_0',
- 'bbb_update_test' => 'does-not-exist',
- 'ccc_update_test' => '1_0',
- );
- $this->refreshUpdateStatus($xml_mapping);
-
- $this->assertText(t('Up to date'));
-
-
- $this->assertNoUniqueText(t('Up to date'));
-
- $this->assertNoText(t('Update available'));
-
-
-
-
- $this->assertRaw('<div class="version-status">' . t('Failed to get available update data'));
-
-
- $this->assertUniqueText(t('Checked available update data for 3 projects.'));
- $this->assertUniqueText(t('Failed to get available update data for one project.'));
-
-
- $this->assertRaw(l(t('AAA Update test'), 'http://example.com/project/aaa_update_test'), 'Link to aaa_update_test project appears.');
- $this->assertNoRaw(l(t('BBB Update test'), 'http://example.com/project/bbb_update_test'), 'Link to bbb_update_test project does not appear.');
- $this->assertRaw(l(t('CCC Update test'), 'http://example.com/project/ccc_update_test'), 'Link to bbb_update_test project appears.');
- }
-
-
- * Check that hook_update_status_alter() works to change a status.
- *
- * We provide the same external data as if aaa_update_test 1.x-1.0 were
- * installed and that was the latest release. Then we use
- * hook_update_status_alter() to try to mark this as missing a security
- * update, then assert if we see the appropriate warnings on the right pages.
- */
- function testHookUpdateStatusAlter() {
- $GLOBALS['settings']['allow_authorize_operations'] = TRUE;
- $config = config('update.settings');
- $update_admin_user = $this->backdropCreateUser(array(
- 'administer site configuration',
- 'administer software updates',
- 'access site reports',
- ));
- $this->backdropLogin($update_admin_user);
-
- $system_info = array(
- '#all' => array(
- 'version' => '1.0',
- ),
- 'aaa_update_test' => array(
- 'project' => 'aaa_update_test',
- 'version' => '1.x-1.0',
- 'hidden' => FALSE,
- ),
- );
- state_set('update_test_system_info', $system_info);
- $update_status = array(
- 'aaa_update_test' => array(
- 'status' => UPDATE_NOT_SECURE,
- ),
- );
- $config->set('update_status', $update_status)->save();
- $this->refreshUpdateStatus(
- array(
- 'backdrop' => '0',
- 'aaa_update_test' => '1_0',
- )
- );
- $this->backdropGet('admin/reports/updates');
- $this->assertRaw('<h3>' . t('Modules') . '</h3>');
- $this->assertText(t('Security update required!'));
- $this->assertRaw(l(t('AAA Update test'), 'http://example.com/project/aaa_update_test'), 'Link to aaa_update_test project appears.');
-
-
-
- $config->set('update_status', array())->save();
- $this->backdropGet('admin/reports/updates');
- $this->assertRaw('<h3>' . t('Modules') . '</h3>');
- $this->assertNoText(t('Security update required!'));
- $this->assertRaw(l(t('AAA Update test'), 'http://example.com/project/aaa_update_test'), 'Link to aaa_update_test project appears.');
- }
-
- }
-
- * Tests update functionality unrelated to the database.
- */
- class UpdateCoreUnitTestCase extends BackdropUnitTestCase {
- function setUp() {
- parent::setUp(array('update'));
- module_load_include('inc', 'update', 'update.fetch');
- }
-
-
- * Tests that _update_build_fetch_url() builds the URL correctly.
- */
- function testUpdateBuildFetchUrl() {
-
- $project['name'] = 'update_test';
- $project['project_type'] = '';
- $project['info']['version'] = '';
- $project['info']['project status url'] = 'http://www.example.com';
- $project['includes'] = array('module1' => 'Module 1', 'module2' => 'Module 2');
- $site_key = '';
- $expected = 'http://www.example.com/' . $project['name'] . '/' . BACKDROP_CORE_COMPATIBILITY;
- $url = _update_build_fetch_url($project, $site_key);
- $this->assertEqual($url, $expected, "'$url' when no site_key provided should be '$expected'.");
-
-
- $site_key = 'site_key';
- $project['project_type'] = 'disabled';
- $expected = 'http://www.example.com/' . $project['name'] . '/' . BACKDROP_CORE_COMPATIBILITY;
- $url = _update_build_fetch_url($project, $site_key);
- $this->assertEqual($url, $expected, "'$url' should be '$expected' for disabled projects.");
-
-
- $project['project_type'] = '';
- $expected = 'http://www.example.com/' . $project['name'] . '/' . BACKDROP_CORE_COMPATIBILITY;
- $expected .= '?site_key=site_key';
- $expected .= '&list=' . rawurlencode('module1,module2');
- $url = _update_build_fetch_url($project, $site_key);
- $this->assertEqual($url, $expected, "When site_key provided, '$url' should be '$expected'.");
-
-
-
- $project['info']['project status url'] = 'http://www.example.com/?project=';
- $expected = 'http://www.example.com/?project=/' . $project['name'] . '/' . BACKDROP_CORE_COMPATIBILITY;
- $expected .= '&site_key=site_key';
- $expected .= '&list=' . rawurlencode('module1,module2');
- $url = _update_build_fetch_url($project, $site_key);
- $this->assertEqual($url, $expected, "When ? is present, '$url' should be '$expected'.");
-
- }
- }