diff --git a/core/modules/update/src/Tests/FileTransferAuthorizeFormTest.php b/core/modules/update/src/Tests/FileTransferAuthorizeFormTest.php deleted file mode 100644 index 9d1819f..0000000 --- a/core/modules/update/src/Tests/FileTransferAuthorizeFormTest.php +++ /dev/null @@ -1,58 +0,0 @@ -drupalCreateUser(['administer modules', 'administer software updates', 'administer site configuration']); - $this->drupalLogin($admin_user); - - // Create a local cache so the module is not downloaded from drupal.org. - $cache_directory = _update_manager_cache_directory(TRUE); - $validArchiveFile = __DIR__ . '/../../tests/update_test_new_module/8.x-1.0/update_test_new_module.tar.gz'; - copy($validArchiveFile, $cache_directory . '/update_test_new_module.tar.gz'); - } - - /** - * Tests the Update Manager module upload via authorize.php functionality. - */ - public function testViaAuthorize() { - // Ensure the that we can select which file transfer backend to use. - \Drupal::state()->set('test_uploaders_via_prompt', TRUE); - - // Ensure the module does not already exist. - $this->drupalGet('admin/modules'); - $this->assertNoText('Update test new module'); - - $edit = [ - // This project has been cached in the test's setUp() method. - 'project_url' => 'https://ftp.drupal.org/files/projects/update_test_new_module.tar.gz', - ]; - $this->drupalPostForm('admin/modules/install', $edit, t('Install')); - $edit = [ - 'connection_settings[authorize_filetransfer_default]' => 'system_test', - 'connection_settings[system_test][update_test_username]' => $this->randomMachineName(), - ]; - $this->drupalPostForm(NULL, $edit, t('Continue')); - $this->assertText(t('Installation was completed successfully.')); - - // Ensure the module is available to install. - $this->drupalGet('admin/modules'); - $this->assertText('Update test new module'); - } - -} diff --git a/core/modules/update/src/Tests/UpdateContribTest.php b/core/modules/update/src/Tests/UpdateContribTest.php deleted file mode 100644 index 81f7117..0000000 --- a/core/modules/update/src/Tests/UpdateContribTest.php +++ /dev/null @@ -1,441 +0,0 @@ -drupalCreateUser(['administer site configuration']); - $this->drupalLogin($admin_user); - } - - /** - * Tests when there is no available release data for a contrib module. - */ - public function testNoReleasesAvailable() { - $system_info = [ - '#all' => [ - 'version' => '8.0.0', - ], - 'aaa_update_test' => [ - 'project' => 'aaa_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - ]; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $this->refreshUpdateStatus(['drupal' => '0.0', 'aaa_update_test' => 'no-releases']); - $this->drupalGet('admin/reports/updates'); - // Cannot use $this->standardTests() because we need to check for the - // 'No available releases found' string. - $this->assertRaw('

' . t('Drupal core') . '

'); - $this->assertRaw(\Drupal::l(t('Drupal'), Url::fromUri('http://example.com/project/drupal'))); - $this->assertText(t('Up to date')); - $this->assertRaw('

' . t('Modules') . '

'); - $this->assertNoText(t('Update available')); - $this->assertText(t('No available releases found')); - $this->assertNoRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test'))); - - $available = update_get_available(); - $this->assertFalse(isset($available['aaa_update_test']['fetch_status']), 'Results are cached even if no releases are available.'); - } - - /** - * Tests the basic functionality of a contrib module on the status report. - */ - public function testUpdateContribBasic() { - $project_link = \Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')); - $system_info = [ - '#all' => [ - 'version' => '8.0.0', - ], - 'aaa_update_test' => [ - 'project' => 'aaa_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - ]; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $this->refreshUpdateStatus( - [ - 'drupal' => '0.0', - 'aaa_update_test' => '1_0', - ] - ); - $this->standardTests(); - $this->assertText(t('Up to date')); - $this->assertRaw('

' . t('Modules') . '

'); - $this->assertNoText(t('Update available')); - $this->assertRaw($project_link, 'Link to aaa_update_test project appears.'); - - // Since aaa_update_test is installed the fact it is hidden and in the - // Testing package means it should not appear. - $system_info['aaa_update_test']['hidden'] = TRUE; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $this->refreshUpdateStatus( - [ - 'drupal' => '0.0', - 'aaa_update_test' => '1_0', - ] - ); - $this->assertNoRaw($project_link, 'Link to aaa_update_test project does not appear.'); - - // A hidden and installed project not in the Testing package should appear. - $system_info['aaa_update_test']['package'] = 'aaa_update_test'; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $this->refreshUpdateStatus( - [ - 'drupal' => '0.0', - 'aaa_update_test' => '1_0', - ] - ); - $this->assertRaw($project_link, '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). - */ - public function testUpdateContribOrder() { - // We want core to be version 8.0.0. - $system_info = [ - '#all' => [ - 'version' => '8.0.0', - ], - // All the rest should be visible as contrib modules at version 8.x-1.0. - - // aaa_update_test needs to be part of the "CCC Update test" project, - // which would throw off the report if we weren't properly sorting by - // the project names. - 'aaa_update_test' => [ - 'project' => 'ccc_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - - // This should be its own project, and listed first on the report. - 'bbb_update_test' => [ - 'project' => 'bbb_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - - // This will contain both aaa_update_test and ccc_update_test, and - // should come after the bbb_update_test project. - 'ccc_update_test' => [ - 'project' => 'ccc_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - ]; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $this->refreshUpdateStatus(['drupal' => '0.0', '#all' => '1_0']); - $this->standardTests(); - // We're expecting the report to say all projects are up to date. - $this->assertText(t('Up to date')); - $this->assertNoText(t('Update available')); - // We want to see all 3 module names listed, since they'll show up either - // as project names or as modules under the "Includes" listing. - $this->assertText(t('AAA Update test')); - $this->assertText(t('BBB Update test')); - $this->assertText(t('CCC Update test')); - // We want aaa_update_test included in the ccc_update_test project, not as - // its own project on the report. - $this->assertNoRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project does not appear.'); - // The other two should be listed as projects. - $this->assertRaw(\Drupal::l(t('BBB Update test'), Url::fromUri('http://example.com/project/bbb_update_test')), 'Link to bbb_update_test project appears.'); - $this->assertRaw(\Drupal::l(t('CCC Update test'), Url::fromUri('http://example.com/project/ccc_update_test')), 'Link to bbb_update_test project appears.'); - - // We want to make sure we see the BBB project before the CCC project. - // Instead of just searching for 'BBB Update test' or something, we want - // to use the full markup that starts the project entry itself, so that - // we're really testing that the project listings are in the right order. - $bbb_project_link = '
BBB Update test'; - $ccc_project_link = '
CCC Update test'; - $this->assertTrue(strpos($this->getRawContent(), $bbb_project_link) < strpos($this->getRawContent(), $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. - */ - public function testUpdateBaseThemeSecurityUpdate() { - // @todo https://www.drupal.org/node/2338175 base themes have to be - // installed. - // Only install the subtheme, not the base theme. - \Drupal::service('theme_handler')->install(['update_test_subtheme']); - - // Define the initial state for core and the subtheme. - $system_info = [ - // We want core to be version 8.0.0. - '#all' => [ - 'version' => '8.0.0', - ], - // Show the update_test_basetheme - 'update_test_basetheme' => [ - 'project' => 'update_test_basetheme', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - // Show the update_test_subtheme - 'update_test_subtheme' => [ - 'project' => 'update_test_subtheme', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - ]; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $xml_mapping = [ - 'drupal' => '0.0', - 'update_test_subtheme' => '1_0', - 'update_test_basetheme' => '1_1-sec', - ]; - $this->refreshUpdateStatus($xml_mapping); - $this->assertText(t('Security update required!')); - $this->assertRaw(\Drupal::l(t('Update test base theme'), Url::fromUri('http://example.com/project/update_test_basetheme')), 'Link to the Update test base theme project appears.'); - } - - /** - * Tests that disabled themes are only shown when desired. - * - * @todo https://www.drupal.org/node/2338175 extensions can not be hidden and - * base themes have to be installed. - */ - public function testUpdateShowDisabledThemes() { - $update_settings = $this->config('update.settings'); - // Make sure all the update_test_* themes are disabled. - $extension_config = $this->config('core.extension'); - foreach ($extension_config->get('theme') as $theme => $weight) { - if (preg_match('/^update_test_/', $theme)) { - $extension_config->clear("theme.$theme"); - } - } - $extension_config->save(); - - // Define the initial state for core and the test contrib themes. - $system_info = [ - // We want core to be version 8.0.0. - '#all' => [ - 'version' => '8.0.0', - ], - // The update_test_basetheme should be visible and up to date. - 'update_test_basetheme' => [ - 'project' => 'update_test_basetheme', - 'version' => '8.x-1.1', - 'hidden' => FALSE, - ], - // The update_test_subtheme should be visible and up to date. - 'update_test_subtheme' => [ - 'project' => 'update_test_subtheme', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - ]; - // When there are contributed modules in the site's file system, the - // total number of attempts made in the test may exceed the default value - // of update_max_fetch_attempts. Therefore this variable is set very high - // to avoid test failures in those cases. - $update_settings->set('fetch.max_attempts', 99999)->save(); - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $xml_mapping = [ - 'drupal' => '0.0', - 'update_test_subtheme' => '1_0', - 'update_test_basetheme' => '1_1-sec', - ]; - $base_theme_project_link = \Drupal::l(t('Update test base theme'), Url::fromUri('http://example.com/project/update_test_basetheme')); - $sub_theme_project_link = \Drupal::l(t('Update test subtheme'), Url::fromUri('http://example.com/project/update_test_subtheme')); - foreach ([TRUE, FALSE] as $check_disabled) { - $update_settings->set('check.disabled_extensions', $check_disabled)->save(); - $this->refreshUpdateStatus($xml_mapping); - // In neither case should we see the "Themes" heading for installed - // themes. - $this->assertNoText(t('Themes')); - if ($check_disabled) { - $this->assertText(t('Uninstalled 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('Uninstalled 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.'); - } - } - } - - /** - * Tests updates with a hidden base theme. - */ - public function testUpdateHiddenBaseTheme() { - module_load_include('compare.inc', 'update'); - - // Install the subtheme. - \Drupal::service('theme_handler')->install(['update_test_subtheme']); - - // Add a project and initial state for base theme and subtheme. - $system_info = [ - // Hide the update_test_basetheme. - 'update_test_basetheme' => [ - 'project' => 'update_test_basetheme', - 'hidden' => TRUE, - ], - // Show the update_test_subtheme. - 'update_test_subtheme' => [ - 'project' => 'update_test_subtheme', - 'hidden' => FALSE, - ], - ]; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $projects = \Drupal::service('update.manager')->getProjects(); - $theme_data = \Drupal::service('theme_handler')->rebuildThemeData(); - $project_info = new ProjectInfo(); - $project_info->processInfoList($projects, $theme_data, 'theme', TRUE); - - $this->assertTrue(!empty($projects['update_test_basetheme']), 'Valid base theme (update_test_basetheme) was found.'); - } - - /** - * Makes sure that if we fetch from a broken URL, sane things happen. - */ - public function testUpdateBrokenFetchURL() { - $system_info = [ - '#all' => [ - 'version' => '8.0.0', - ], - 'aaa_update_test' => [ - 'project' => 'aaa_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - 'bbb_update_test' => [ - 'project' => 'bbb_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - 'ccc_update_test' => [ - 'project' => 'ccc_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - ]; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - - // Ensure that the update information is correct before testing. - $this->drupalGet('admin/reports/updates'); - - $xml_mapping = [ - 'drupal' => '0.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')); - // We're expecting the report to say most projects are up to date, so we - // hope that 'Up to date' is not unique. - $this->assertNoUniqueText(t('Up to date')); - // It should say we failed to get data, not that we're missing an update. - $this->assertNoText(t('Update available')); - - // We need to check that this string is found as part of a project row, not - // just in the "Failed to get available update data" message at the top of - // the page. - $this->assertRaw('
' . t('Failed to get available update data')); - - // We should see the output messages from fetching manually. - $this->assertUniqueText(t('Checked available update data for 3 projects.')); - $this->assertUniqueText(t('Failed to get available update data for one project.')); - - // The other two should be listed as projects. - $this->assertRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project appears.'); - $this->assertNoRaw(\Drupal::l(t('BBB Update test'), Url::fromUri('http://example.com/project/bbb_update_test')), 'Link to bbb_update_test project does not appear.'); - $this->assertRaw(\Drupal::l(t('CCC Update test'), Url::fromUri('http://example.com/project/ccc_update_test')), 'Link to bbb_update_test project appears.'); - } - - /** - * Checks that hook_update_status_alter() works to change a status. - * - * We provide the same external data as if aaa_update_test 8.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. - */ - public function testHookUpdateStatusAlter() { - $update_test_config = $this->config('update_test.settings'); - $update_admin_user = $this->drupalCreateUser(['administer site configuration', 'administer software updates']); - $this->drupalLogin($update_admin_user); - - $system_info = [ - '#all' => [ - 'version' => '8.0.0', - ], - 'aaa_update_test' => [ - 'project' => 'aaa_update_test', - 'version' => '8.x-1.0', - 'hidden' => FALSE, - ], - ]; - $update_test_config->set('system_info', $system_info)->save(); - $update_status = [ - 'aaa_update_test' => [ - 'status' => UPDATE_NOT_SECURE, - ], - ]; - $update_test_config->set('update_status', $update_status)->save(); - $this->refreshUpdateStatus( - [ - 'drupal' => '0.0', - 'aaa_update_test' => '1_0', - ] - ); - $this->drupalGet('admin/reports/updates'); - $this->assertRaw('

' . t('Modules') . '

'); - $this->assertText(t('Security update required!')); - $this->assertRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project appears.'); - - // Visit the reports page again without the altering and make sure the - // status is back to normal. - $update_test_config->set('update_status', [])->save(); - $this->drupalGet('admin/reports/updates'); - $this->assertRaw('

' . t('Modules') . '

'); - $this->assertNoText(t('Security update required!')); - $this->assertRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project appears.'); - - // Turn the altering back on and visit the Update manager UI. - $update_test_config->set('update_status', $update_status)->save(); - $this->drupalGet('admin/modules/update'); - $this->assertText(t('Security update')); - - // Turn the altering back off and visit the Update manager UI. - $update_test_config->set('update_status', [])->save(); - $this->drupalGet('admin/modules/update'); - $this->assertNoText(t('Security update')); - } - -} diff --git a/core/modules/update/src/Tests/UpdateCoreTest.php b/core/modules/update/src/Tests/UpdateCoreTest.php deleted file mode 100644 index b6287c7..0000000 --- a/core/modules/update/src/Tests/UpdateCoreTest.php +++ /dev/null @@ -1,368 +0,0 @@ -drupalCreateUser(['administer site configuration', 'administer modules', 'administer themes']); - $this->drupalLogin($admin_user); - $this->drupalPlaceBlock('local_actions_block'); - } - - /** - * Sets the version to x.x.x when no project-specific mapping is defined. - * - * @param string $version - * The version. - */ - protected function setSystemInfo($version) { - $setting = [ - '#all' => [ - 'version' => $version, - ], - ]; - $this->config('update_test.settings')->set('system_info', $setting)->save(); - } - - /** - * Tests the Update Manager module when no updates are available. - */ - public function testNoUpdatesAvailable() { - foreach ([0, 1] as $minor_version) { - foreach ([0, 1] as $patch_version) { - foreach (['-alpha1', '-beta1', ''] as $extra_version) { - $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version); - $this->refreshUpdateStatus(['drupal' => "$minor_version.$patch_version" . $extra_version]); - $this->standardTests(); - $this->assertText(t('Up to date')); - $this->assertNoText(t('Update available')); - $this->assertNoText(t('Security update required!')); - $this->assertRaw('check.svg', 'Check icon was found.'); - } - } - } - } - - /** - * Tests the Update Manager module when one normal update is available. - */ - public function testNormalUpdateAvailable() { - $this->setSystemInfo('8.0.0'); - - // Ensure that the update check requires a token. - $this->drupalGet('admin/reports/updates/check'); - $this->assertResponse(403, 'Accessing admin/reports/updates/check without a CSRF token results in access denied.'); - - foreach ([0, 1] as $minor_version) { - foreach (['-alpha1', '-beta1', ''] as $extra_version) { - $this->refreshUpdateStatus(['drupal' => "$minor_version.1" . $extra_version]); - $this->standardTests(); - $this->drupalGet('admin/reports/updates'); - $this->clickLink(t('Check manually')); - $this->assertNoText(t('Security update required!')); - $this->assertRaw(\Drupal::l("8.$minor_version.1" . $extra_version, Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release appears.'); - $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version.tar.gz")), 'Link to download appears.'); - $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release notes appears.'); - - switch ($minor_version) { - case 0: - // Both stable and unstable releases are available. - // A stable release is the latest. - if ($extra_version == '') { - $this->assertNoText(t('Up to date')); - $this->assertText(t('Update available')); - $this->assertText(t('Recommended version:')); - $this->assertNoText(t('Latest version:')); - $this->assertRaw('warning.svg', 'Warning icon was found.'); - } - // Only unstable releases are available. - // An unstable release is the latest. - else { - $this->assertText(t('Up to date')); - $this->assertNoText(t('Update available')); - $this->assertNoText(t('Recommended version:')); - $this->assertText(t('Latest version:')); - $this->assertRaw('check.svg', 'Check icon was found.'); - } - break; - case 1: - // Both stable and unstable releases are available. - // A stable release is the latest. - if ($extra_version == '') { - $this->assertNoText(t('Up to date')); - $this->assertText(t('Update available')); - $this->assertText(t('Recommended version:')); - $this->assertNoText(t('Latest version:')); - $this->assertRaw('warning.svg', 'Warning icon was found.'); - } - // Both stable and unstable releases are available. - // An unstable release is the latest. - else { - $this->assertNoText(t('Up to date')); - $this->assertText(t('Update available')); - $this->assertText(t('Recommended version:')); - $this->assertText(t('Latest version:')); - $this->assertRaw('warning.svg', 'Warning icon was found.'); - } - break; - } - } - } - } - - /** - * Tests the Update Manager module when a major update is available. - */ - public function testMajorUpdateAvailable() { - foreach ([0, 1] as $minor_version) { - foreach ([0, 1] as $patch_version) { - foreach (['-alpha1', '-beta1', ''] as $extra_version) { - $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version); - $this->refreshUpdateStatus(['drupal' => '9']); - $this->standardTests(); - $this->drupalGet('admin/reports/updates'); - $this->clickLink(t('Check manually')); - $this->assertNoText(t('Security update required!')); - $this->assertRaw(\Drupal::l('9.0.0', Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release appears.'); - $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-9-0-0.tar.gz")), 'Link to download appears.'); - $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release notes appears.'); - $this->assertNoText(t('Up to date')); - $this->assertText(t('Not supported!')); - $this->assertText(t('Recommended version:')); - $this->assertNoText(t('Latest version:')); - $this->assertRaw('error.svg', 'Error icon was found.'); - } - } - } - } - - /** - * Tests the Update Manager module when a security update is available. - */ - public function testSecurityUpdateAvailable() { - foreach ([0, 1] as $minor_version) { - $this->setSystemInfo("8.$minor_version.0"); - $this->refreshUpdateStatus(['drupal' => "$minor_version.2-sec"]); - $this->standardTests(); - $this->assertNoText(t('Up to date')); - $this->assertNoText(t('Update available')); - $this->assertText(t('Security update required!')); - $this->assertRaw(\Drupal::l("8.$minor_version.2", Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release appears.'); - $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-2.tar.gz")), 'Link to download appears.'); - $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release notes appears.'); - $this->assertRaw('error.svg', 'Error icon was found.'); - } - } - - /** - * Ensures proper results where there are date mismatches among modules. - */ - public function testDatestampMismatch() { - $system_info = [ - '#all' => [ - // We need to think we're running a -dev snapshot to see dates. - 'version' => '8.1.0-dev', - 'datestamp' => time(), - ], - 'block' => [ - // This is 2001-09-09 01:46:40 GMT, so test for "2001-Sep-". - 'datestamp' => '1000000000', - ], - ]; - $this->config('update_test.settings')->set('system_info', $system_info)->save(); - $this->refreshUpdateStatus(['drupal' => '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. - */ - public function testModulePageRunCron() { - $this->setSystemInfo('8.0.0'); - $this->config('update.settings') - ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) - ->save(); - $this->config('update_test.settings') - ->set('xml_map', ['drupal' => '0.0']) - ->save(); - - $this->cronRun(); - $this->drupalGet('admin/modules'); - $this->assertNoText(t('No update information available.')); - } - - /** - * Checks the messages at admin/modules when the site is up to date. - */ - public function testModulePageUpToDate() { - $this->setSystemInfo('8.0.0'); - // Instead of using refreshUpdateStatus(), set these manually. - $this->config('update.settings') - ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) - ->save(); - $this->config('update_test.settings') - ->set('xml_map', ['drupal' => '0.0']) - ->save(); - - $this->drupalGet('admin/reports/updates'); - $this->clickLink(t('Check manually')); - $this->assertText(t('Checked available update data for one project.')); - $this->drupalGet('admin/modules'); - $this->assertNoText(t('There are updates available for your version of Drupal.')); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - } - - /** - * Checks the messages at admin/modules when an update is missing. - */ - public function testModulePageRegularUpdate() { - $this->setSystemInfo('8.0.0'); - // Instead of using refreshUpdateStatus(), set these manually. - $this->config('update.settings') - ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) - ->save(); - $this->config('update_test.settings') - ->set('xml_map', ['drupal' => '0.1']) - ->save(); - - $this->drupalGet('admin/reports/updates'); - $this->clickLink(t('Check manually')); - $this->assertText(t('Checked available update data for one project.')); - $this->drupalGet('admin/modules'); - $this->assertText(t('There are updates available for your version of Drupal.')); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - } - - /** - * Checks the messages at admin/modules when a security update is missing. - */ - public function testModulePageSecurityUpdate() { - $this->setSystemInfo('8.0.0'); - // Instead of using refreshUpdateStatus(), set these manually. - $this->config('update.settings') - ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) - ->save(); - $this->config('update_test.settings') - ->set('xml_map', ['drupal' => '0.2-sec']) - ->save(); - - $this->drupalGet('admin/reports/updates'); - $this->clickLink(t('Check manually')); - $this->assertText(t('Checked available update data for one project.')); - $this->drupalGet('admin/modules'); - $this->assertNoText(t('There are updates available for your version of Drupal.')); - $this->assertText(t('There is a security update available for your version of Drupal.')); - - // Make sure admin/appearance warns you you're missing a security update. - $this->drupalGet('admin/appearance'); - $this->assertNoText(t('There are updates available for your version of Drupal.')); - $this->assertText(t('There is a security update available for your version of Drupal.')); - - // Make sure duplicate messages don't appear on Update status pages. - $this->drupalGet('admin/reports/status'); - // We're expecting "There is a security update..." inside the status report - // itself, but the drupal_set_message() appears as an li so we can prefix - // with that and search for the raw HTML. - $this->assertNoRaw('
  • ' . t('There is a security update available for your version of Drupal.')); - - $this->drupalGet('admin/reports/updates'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - - $this->drupalGet('admin/reports/updates/settings'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - } - - /** - * Tests the Update Manager module when the update server returns 503 errors. - */ - public function testServiceUnavailable() { - $this->refreshUpdateStatus([], '503-error'); - // Ensure that no "Warning: SimpleXMLElement..." parse errors are found. - $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. - */ - public function testFetchTasks() { - $projecta = [ - 'name' => 'aaa_update_test', - ]; - $projectb = [ - 'name' => 'bbb_update_test', - ]; - $queue = \Drupal::queue('update_fetch_tasks'); - $this->assertEqual($queue->numberOfItems(), 0, 'Queue is empty'); - update_create_fetch_task($projecta); - $this->assertEqual($queue->numberOfItems(), 1, 'Queue contains one item'); - update_create_fetch_task($projectb); - $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items'); - // Try to add project a again. - update_create_fetch_task($projecta); - $this->assertEqual($queue->numberOfItems(), 2, 'Queue still contains two items'); - - // Clear storage and try again. - update_storage_clear(); - update_create_fetch_task($projecta); - $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items'); - } - - /** - * Checks language module in core package at admin/reports/updates. - */ - public function testLanguageModuleUpdate() { - $this->setSystemInfo('8.0.0'); - // Instead of using refreshUpdateStatus(), set these manually. - $this->config('update.settings') - ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) - ->save(); - $this->config('update_test.settings') - ->set('xml_map', ['drupal' => '0.1']) - ->save(); - - $this->drupalGet('admin/reports/updates'); - $this->assertText(t('Language')); - } - - /** - * Ensures that the local actions appear. - */ - public function testLocalActions() { - $admin_user = $this->drupalCreateUser(['administer site configuration', 'administer modules', 'administer software updates', 'administer themes']); - $this->drupalLogin($admin_user); - - $this->drupalGet('admin/modules'); - $this->clickLink(t('Install new module')); - $this->assertUrl('admin/modules/install'); - - $this->drupalGet('admin/appearance'); - $this->clickLink(t('Install new theme')); - $this->assertUrl('admin/theme/install'); - - $this->drupalGet('admin/reports/updates'); - $this->clickLink(t('Install new module or theme')); - $this->assertUrl('admin/reports/updates/install'); - } - -} diff --git a/core/modules/update/src/Tests/UpdateDeleteFileIfStaleTest.php b/core/modules/update/src/Tests/UpdateDeleteFileIfStaleTest.php deleted file mode 100644 index 99499d7..0000000 --- a/core/modules/update/src/Tests/UpdateDeleteFileIfStaleTest.php +++ /dev/null @@ -1,47 +0,0 @@ -randomMachineName()); - $this->assertNotNull($file_name); - - // During testing the file change and the stale checking occurs in the same - // request, so the beginning of request will be before the file changes and - // REQUEST_TIME - $filectime is negative. Set the maximum age to a number - // even smaller than that. - $this->config('system.file') - ->set('temporary_maximum_age', -100000) - ->save(); - - $file_path = drupal_realpath($file_name); - update_delete_file_if_stale($file_path); - - $this->assertFalse(is_file($file_path)); - } - -} diff --git a/core/modules/update/src/Tests/UpdateTestBase.php b/core/modules/update/src/Tests/UpdateTestBase.php deleted file mode 100644 index fc39d1a..0000000 --- a/core/modules/update/src/Tests/UpdateTestBase.php +++ /dev/null @@ -1,83 +0,0 @@ -container->get('update.root') . '/' . DrupalKernel::findSitePath($request); - $this->container->set('update.root', $update_root); - \Drupal::setContainer($this->container); - - // Create the directories within the root path within which the Update - // Manager will install projects. - foreach (drupal_get_updaters() as $updater_info) { - $updater = $updater_info['class']; - $install_directory = $update_root . '/' . $updater::getRootDirectoryRelativePath(); - if (!is_dir($install_directory)) { - mkdir($install_directory); - } - } - } - - /** - * 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 Drupal\update_test\Controller\UpdateTestController::updateTest() - */ - protected function refreshUpdateStatus($xml_map, $url = 'update-test') { - // Tell the Update Manager module to fetch from the URL provided by - // update_test module. - $this->config('update.settings')->set('fetch.url', Url::fromUri('base:' . $url, ['absolute' => TRUE])->toString())->save(); - // Save the map for UpdateTestController::updateTest() to use. - $this->config('update_test.settings')->set('xml_map', $xml_map)->save(); - // Manually check the update status. - $this->drupalGet('admin/reports/updates'); - $this->clickLink(t('Check manually')); - } - - /** - * Runs a series of assertions that are applicable to all update statuses. - */ - protected function standardTests() { - $this->assertRaw('

    ' . t('Drupal core') . '

    '); - $this->assertRaw(\Drupal::l(t('Drupal'), Url::fromUri('http://example.com/project/drupal')), 'Link to the Drupal project appears.'); - $this->assertNoText(t('No available releases found')); - } - -} diff --git a/core/modules/update/src/Tests/UpdateUploadTest.php b/core/modules/update/src/Tests/UpdateUploadTest.php deleted file mode 100644 index 80d3f15..0000000 --- a/core/modules/update/src/Tests/UpdateUploadTest.php +++ /dev/null @@ -1,195 +0,0 @@ -drupalCreateUser(['administer modules', 'administer software updates', 'administer site configuration']); - $this->drupalLogin($admin_user); - } - - /** - * Tests upload, extraction, and update of a module. - */ - public function testUploadModule() { - // Ensure that the update information is correct before testing. - update_get_available(TRUE); - - // Images are not valid archives, so get one and try to install it. We - // need an extra variable to store the result of drupalGetTestFiles() - // since reset() takes an argument by reference and passing in a constant - // emits a notice in strict mode. - $imageTestFiles = $this->drupalGetTestFiles('image'); - $invalidArchiveFile = reset($imageTestFiles); - $edit = [ - 'files[project_upload]' => $invalidArchiveFile->uri, - ]; - // This also checks that the correct archive extensions are allowed. - $this->drupalPostForm('admin/modules/install', $edit, t('Install')); - $this->assertText(t('Only files with the following extensions are allowed: @archive_extensions.', ['@archive_extensions' => archiver_get_extensions()]), 'Only valid archives can be uploaded.'); - $this->assertUrl('admin/modules/install'); - - // Check to ensure an existing module can't be reinstalled. Also checks that - // the archive was extracted since we can't know if the module is already - // installed until after extraction. - $validArchiveFile = __DIR__ . '/../../tests/aaa_update_test.tar.gz'; - $edit = [ - 'files[project_upload]' => $validArchiveFile, - ]; - $this->drupalPostForm('admin/modules/install', $edit, t('Install')); - $this->assertText(t('@module_name is already installed.', ['@module_name' => 'AAA Update test']), 'Existing module was extracted and not reinstalled.'); - $this->assertUrl('admin/modules/install'); - - // Ensure that a new module can be extracted and installed. - $updaters = drupal_get_updaters(); - $moduleUpdater = $updaters['module']['class']; - $installedInfoFilePath = $this->container->get('update.root') . '/' . $moduleUpdater::getRootDirectoryRelativePath() . '/update_test_new_module/update_test_new_module.info.yml'; - $this->assertFalse(file_exists($installedInfoFilePath), 'The new module does not exist in the filesystem before it is installed with the Update Manager.'); - $validArchiveFile = __DIR__ . '/../../tests/update_test_new_module/8.x-1.0/update_test_new_module.tar.gz'; - $edit = [ - 'files[project_upload]' => $validArchiveFile, - ]; - $this->drupalPostForm('admin/modules/install', $edit, t('Install')); - // Check that submitting the form takes the user to authorize.php. - $this->assertUrl('core/authorize.php'); - $this->assertTitle('Update manager | Drupal'); - // Check for a success message on the page, and check that the installed - // module now exists in the expected place in the filesystem. - $this->assertRaw(t('Installed %project_name successfully', ['%project_name' => 'update_test_new_module'])); - $this->assertTrue(file_exists($installedInfoFilePath), 'The new module exists in the filesystem after it is installed with the Update Manager.'); - // Ensure the links are relative to the site root and not - // core/authorize.php. - $this->assertLink(t('Install another module')); - $this->assertLinkByHref(Url::fromRoute('update.module_install')->toString()); - $this->assertLink(t('Enable newly added modules')); - $this->assertLinkByHref(Url::fromRoute('system.modules_list')->toString()); - $this->assertLink(t('Administration pages')); - $this->assertLinkByHref(Url::fromRoute('system.admin')->toString()); - // Ensure we can reach the "Install another module" link. - $this->clickLink(t('Install another module')); - $this->assertResponse(200); - $this->assertUrl('admin/modules/install'); - - // Check that the module has the correct version before trying to update - // it. Since the module is installed in sites/simpletest, which only the - // child site has access to, standard module API functions won't find it - // when called here. To get the version, the info file must be parsed - // directly instead. - $info_parser = new InfoParserDynamic(); - $info = $info_parser->parse($installedInfoFilePath); - $this->assertEqual($info['version'], '8.x-1.0'); - - // Enable the module. - $this->drupalPostForm('admin/modules', ['modules[update_test_new_module][enable]' => TRUE], t('Install')); - - // Define the update XML such that the new module downloaded above needs an - // update from 8.x-1.0 to 8.x-1.1. - $update_test_config = $this->config('update_test.settings'); - $system_info = [ - 'update_test_new_module' => [ - 'project' => 'update_test_new_module', - ], - ]; - $update_test_config->set('system_info', $system_info)->save(); - $xml_mapping = [ - 'update_test_new_module' => '1_1', - ]; - $this->refreshUpdateStatus($xml_mapping); - - // Run the updates for the new module. - $this->drupalPostForm('admin/reports/updates/update', ['projects[update_test_new_module]' => TRUE], t('Download these updates')); - $this->drupalPostForm(NULL, ['maintenance_mode' => FALSE], t('Continue')); - $this->assertText(t('Update was completed successfully.')); - $this->assertRaw(t('Installed %project_name successfully', ['%project_name' => 'update_test_new_module'])); - - // Parse the info file again to check that the module has been updated to - // 8.x-1.1. - $info = $info_parser->parse($installedInfoFilePath); - $this->assertEqual($info['version'], '8.x-1.1'); - } - - /** - * Ensures that archiver extensions are properly merged in the UI. - */ - public function testFileNameExtensionMerging() { - $this->drupalGet('admin/modules/install'); - // Make sure the bogus extension supported by update_test.module is there. - $this->assertPattern('/file extensions are supported:.*update-test-extension/', "Found 'update-test-extension' extension."); - // Make sure it didn't clobber the first option from core. - $this->assertPattern('/file extensions are supported:.*tar/', "Found 'tar' extension."); - } - - /** - * Checks the messages on update manager pages when missing a security update. - */ - public function testUpdateManagerCoreSecurityUpdateMessages() { - $setting = [ - '#all' => [ - 'version' => '8.0.0', - ], - ]; - $this->config('update_test.settings') - ->set('system_info', $setting) - ->set('xml_map', ['drupal' => '0.2-sec']) - ->save(); - $this->config('update.settings') - ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) - ->save(); - // Initialize the update status. - $this->drupalGet('admin/reports/updates'); - - // Now, make sure none of the Update manager pages have duplicate messages - // about core missing a security update. - - $this->drupalGet('admin/modules/install'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - - $this->drupalGet('admin/modules/update'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - - $this->drupalGet('admin/appearance/install'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - - $this->drupalGet('admin/appearance/update'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - - $this->drupalGet('admin/reports/updates/install'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - - $this->drupalGet('admin/reports/updates/update'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - - $this->drupalGet('admin/update/ready'); - $this->assertNoText(t('There is a security update available for your version of Drupal.')); - } - - /** - * Tests only an *.info.yml file are detected without supporting files. - */ - public function testUpdateDirectory() { - $type = Updater::getUpdaterFromDirectory(\Drupal::root() . '/core/modules/update/tests/modules/aaa_update_test'); - $this->assertEqual($type, 'Drupal\\Core\\Updater\\Module', 'Detected a Module'); - - $type = Updater::getUpdaterFromDirectory(\Drupal::root() . '/core/modules/update/tests/themes/update_test_basetheme'); - $this->assertEqual($type, 'Drupal\\Core\\Updater\\Theme', 'Detected a Theme.'); - } - -} diff --git a/core/modules/update/tests/src/Functional/FileTransferAuthorizeFormTest.php b/core/modules/update/tests/src/Functional/FileTransferAuthorizeFormTest.php new file mode 100644 index 0000000..c314dd5 --- /dev/null +++ b/core/modules/update/tests/src/Functional/FileTransferAuthorizeFormTest.php @@ -0,0 +1,58 @@ +drupalCreateUser(['administer modules', 'administer software updates', 'administer site configuration']); + $this->drupalLogin($admin_user); + + // Create a local cache so the module is not downloaded from drupal.org. + $cache_directory = _update_manager_cache_directory(TRUE); + $validArchiveFile = __DIR__ . '/../../tests/update_test_new_module/8.x-1.0/update_test_new_module.tar.gz'; + copy($validArchiveFile, $cache_directory . '/update_test_new_module.tar.gz'); + } + + /** + * Tests the Update Manager module upload via authorize.php functionality. + */ + public function testViaAuthorize() { + // Ensure the that we can select which file transfer backend to use. + \Drupal::state()->set('test_uploaders_via_prompt', TRUE); + + // Ensure the module does not already exist. + $this->drupalGet('admin/modules'); + $this->assertNoText('Update test new module'); + + $edit = [ + // This project has been cached in the test's setUp() method. + 'project_url' => 'https://ftp.drupal.org/files/projects/update_test_new_module.tar.gz', + ]; + $this->drupalPostForm('admin/modules/install', $edit, t('Install')); + $edit = [ + 'connection_settings[authorize_filetransfer_default]' => 'system_test', + 'connection_settings[system_test][update_test_username]' => $this->randomMachineName(), + ]; + $this->drupalPostForm(NULL, $edit, t('Continue')); + $this->assertText(t('Installation was completed successfully.')); + + // Ensure the module is available to install. + $this->drupalGet('admin/modules'); + $this->assertText('Update test new module'); + } + +} diff --git a/core/modules/update/tests/src/Functional/UpdateContribTest.php b/core/modules/update/tests/src/Functional/UpdateContribTest.php new file mode 100644 index 0000000..20d397c --- /dev/null +++ b/core/modules/update/tests/src/Functional/UpdateContribTest.php @@ -0,0 +1,441 @@ +drupalCreateUser(['administer site configuration']); + $this->drupalLogin($admin_user); + } + + /** + * Tests when there is no available release data for a contrib module. + */ + public function testNoReleasesAvailable() { + $system_info = [ + '#all' => [ + 'version' => '8.0.0', + ], + 'aaa_update_test' => [ + 'project' => 'aaa_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + ]; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $this->refreshUpdateStatus(['drupal' => '0.0', 'aaa_update_test' => 'no-releases']); + $this->drupalGet('admin/reports/updates'); + // Cannot use $this->standardTests() because we need to check for the + // 'No available releases found' string. + $this->assertRaw('

    ' . t('Drupal core') . '

    '); + $this->assertRaw(\Drupal::l(t('Drupal'), Url::fromUri('http://example.com/project/drupal'))); + $this->assertText(t('Up to date')); + $this->assertRaw('

    ' . t('Modules') . '

    '); + $this->assertNoText(t('Update available')); + $this->assertText(t('No available releases found')); + $this->assertNoRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test'))); + + $available = update_get_available(); + $this->assertFalse(isset($available['aaa_update_test']['fetch_status']), 'Results are cached even if no releases are available.'); + } + + /** + * Tests the basic functionality of a contrib module on the status report. + */ + public function testUpdateContribBasic() { + $project_link = \Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')); + $system_info = [ + '#all' => [ + 'version' => '8.0.0', + ], + 'aaa_update_test' => [ + 'project' => 'aaa_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + ]; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $this->refreshUpdateStatus( + [ + 'drupal' => '0.0', + 'aaa_update_test' => '1_0', + ] + ); + $this->standardTests(); + $this->assertText(t('Up to date')); + $this->assertRaw('

    ' . t('Modules') . '

    '); + $this->assertNoText(t('Update available')); + $this->assertRaw($project_link, 'Link to aaa_update_test project appears.'); + + // Since aaa_update_test is installed the fact it is hidden and in the + // Testing package means it should not appear. + $system_info['aaa_update_test']['hidden'] = TRUE; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $this->refreshUpdateStatus( + [ + 'drupal' => '0.0', + 'aaa_update_test' => '1_0', + ] + ); + $this->assertNoRaw($project_link, 'Link to aaa_update_test project does not appear.'); + + // A hidden and installed project not in the Testing package should appear. + $system_info['aaa_update_test']['package'] = 'aaa_update_test'; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $this->refreshUpdateStatus( + [ + 'drupal' => '0.0', + 'aaa_update_test' => '1_0', + ] + ); + $this->assertRaw($project_link, '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). + */ + public function testUpdateContribOrder() { + // We want core to be version 8.0.0. + $system_info = [ + '#all' => [ + 'version' => '8.0.0', + ], + // All the rest should be visible as contrib modules at version 8.x-1.0. + + // aaa_update_test needs to be part of the "CCC Update test" project, + // which would throw off the report if we weren't properly sorting by + // the project names. + 'aaa_update_test' => [ + 'project' => 'ccc_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + + // This should be its own project, and listed first on the report. + 'bbb_update_test' => [ + 'project' => 'bbb_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + + // This will contain both aaa_update_test and ccc_update_test, and + // should come after the bbb_update_test project. + 'ccc_update_test' => [ + 'project' => 'ccc_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + ]; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $this->refreshUpdateStatus(['drupal' => '0.0', '#all' => '1_0']); + $this->standardTests(); + // We're expecting the report to say all projects are up to date. + $this->assertText(t('Up to date')); + $this->assertNoText(t('Update available')); + // We want to see all 3 module names listed, since they'll show up either + // as project names or as modules under the "Includes" listing. + $this->assertText(t('AAA Update test')); + $this->assertText(t('BBB Update test')); + $this->assertText(t('CCC Update test')); + // We want aaa_update_test included in the ccc_update_test project, not as + // its own project on the report. + $this->assertNoRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project does not appear.'); + // The other two should be listed as projects. + $this->assertRaw(\Drupal::l(t('BBB Update test'), Url::fromUri('http://example.com/project/bbb_update_test')), 'Link to bbb_update_test project appears.'); + $this->assertRaw(\Drupal::l(t('CCC Update test'), Url::fromUri('http://example.com/project/ccc_update_test')), 'Link to bbb_update_test project appears.'); + + // We want to make sure we see the BBB project before the CCC project. + // Instead of just searching for 'BBB Update test' or something, we want + // to use the full markup that starts the project entry itself, so that + // we're really testing that the project listings are in the right order. + $bbb_project_link = '
    BBB Update test'; + $ccc_project_link = '
    CCC Update test'; + $this->assertTrue(strpos($this->getRawContent(), $bbb_project_link) < strpos($this->getRawContent(), $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. + */ + public function testUpdateBaseThemeSecurityUpdate() { + // @todo https://www.drupal.org/node/2338175 base themes have to be + // installed. + // Only install the subtheme, not the base theme. + \Drupal::service('theme_handler')->install(['update_test_subtheme']); + + // Define the initial state for core and the subtheme. + $system_info = [ + // We want core to be version 8.0.0. + '#all' => [ + 'version' => '8.0.0', + ], + // Show the update_test_basetheme + 'update_test_basetheme' => [ + 'project' => 'update_test_basetheme', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + // Show the update_test_subtheme + 'update_test_subtheme' => [ + 'project' => 'update_test_subtheme', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + ]; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $xml_mapping = [ + 'drupal' => '0.0', + 'update_test_subtheme' => '1_0', + 'update_test_basetheme' => '1_1-sec', + ]; + $this->refreshUpdateStatus($xml_mapping); + $this->assertText(t('Security update required!')); + $this->assertRaw(\Drupal::l(t('Update test base theme'), Url::fromUri('http://example.com/project/update_test_basetheme')), 'Link to the Update test base theme project appears.'); + } + + /** + * Tests that disabled themes are only shown when desired. + * + * @todo https://www.drupal.org/node/2338175 extensions can not be hidden and + * base themes have to be installed. + */ + public function testUpdateShowDisabledThemes() { + $update_settings = $this->config('update.settings'); + // Make sure all the update_test_* themes are disabled. + $extension_config = $this->config('core.extension'); + foreach ($extension_config->get('theme') as $theme => $weight) { + if (preg_match('/^update_test_/', $theme)) { + $extension_config->clear("theme.$theme"); + } + } + $extension_config->save(); + + // Define the initial state for core and the test contrib themes. + $system_info = [ + // We want core to be version 8.0.0. + '#all' => [ + 'version' => '8.0.0', + ], + // The update_test_basetheme should be visible and up to date. + 'update_test_basetheme' => [ + 'project' => 'update_test_basetheme', + 'version' => '8.x-1.1', + 'hidden' => FALSE, + ], + // The update_test_subtheme should be visible and up to date. + 'update_test_subtheme' => [ + 'project' => 'update_test_subtheme', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + ]; + // When there are contributed modules in the site's file system, the + // total number of attempts made in the test may exceed the default value + // of update_max_fetch_attempts. Therefore this variable is set very high + // to avoid test failures in those cases. + $update_settings->set('fetch.max_attempts', 99999)->save(); + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $xml_mapping = [ + 'drupal' => '0.0', + 'update_test_subtheme' => '1_0', + 'update_test_basetheme' => '1_1-sec', + ]; + $base_theme_project_link = \Drupal::l(t('Update test base theme'), Url::fromUri('http://example.com/project/update_test_basetheme')); + $sub_theme_project_link = \Drupal::l(t('Update test subtheme'), Url::fromUri('http://example.com/project/update_test_subtheme')); + foreach ([TRUE, FALSE] as $check_disabled) { + $update_settings->set('check.disabled_extensions', $check_disabled)->save(); + $this->refreshUpdateStatus($xml_mapping); + // In neither case should we see the "Themes" heading for installed + // themes. + $this->assertNoText(t('Themes')); + if ($check_disabled) { + $this->assertText(t('Uninstalled 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('Uninstalled 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.'); + } + } + } + + /** + * Tests updates with a hidden base theme. + */ + public function testUpdateHiddenBaseTheme() { + module_load_include('compare.inc', 'update'); + + // Install the subtheme. + \Drupal::service('theme_handler')->install(['update_test_subtheme']); + + // Add a project and initial state for base theme and subtheme. + $system_info = [ + // Hide the update_test_basetheme. + 'update_test_basetheme' => [ + 'project' => 'update_test_basetheme', + 'hidden' => TRUE, + ], + // Show the update_test_subtheme. + 'update_test_subtheme' => [ + 'project' => 'update_test_subtheme', + 'hidden' => FALSE, + ], + ]; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $projects = \Drupal::service('update.manager')->getProjects(); + $theme_data = \Drupal::service('theme_handler')->rebuildThemeData(); + $project_info = new ProjectInfo(); + $project_info->processInfoList($projects, $theme_data, 'theme', TRUE); + + $this->assertTrue(!empty($projects['update_test_basetheme']), 'Valid base theme (update_test_basetheme) was found.'); + } + + /** + * Makes sure that if we fetch from a broken URL, sane things happen. + */ + public function testUpdateBrokenFetchURL() { + $system_info = [ + '#all' => [ + 'version' => '8.0.0', + ], + 'aaa_update_test' => [ + 'project' => 'aaa_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + 'bbb_update_test' => [ + 'project' => 'bbb_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + 'ccc_update_test' => [ + 'project' => 'ccc_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + ]; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + + // Ensure that the update information is correct before testing. + $this->drupalGet('admin/reports/updates'); + + $xml_mapping = [ + 'drupal' => '0.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')); + // We're expecting the report to say most projects are up to date, so we + // hope that 'Up to date' is not unique. + $this->assertNoUniqueText(t('Up to date')); + // It should say we failed to get data, not that we're missing an update. + $this->assertNoText(t('Update available')); + + // We need to check that this string is found as part of a project row, not + // just in the "Failed to get available update data" message at the top of + // the page. + $this->assertRaw('
    ' . t('Failed to get available update data')); + + // We should see the output messages from fetching manually. + $this->assertUniqueText(t('Checked available update data for 3 projects.')); + $this->assertUniqueText(t('Failed to get available update data for one project.')); + + // The other two should be listed as projects. + $this->assertRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project appears.'); + $this->assertNoRaw(\Drupal::l(t('BBB Update test'), Url::fromUri('http://example.com/project/bbb_update_test')), 'Link to bbb_update_test project does not appear.'); + $this->assertRaw(\Drupal::l(t('CCC Update test'), Url::fromUri('http://example.com/project/ccc_update_test')), 'Link to bbb_update_test project appears.'); + } + + /** + * Checks that hook_update_status_alter() works to change a status. + * + * We provide the same external data as if aaa_update_test 8.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. + */ + public function testHookUpdateStatusAlter() { + $update_test_config = $this->config('update_test.settings'); + $update_admin_user = $this->drupalCreateUser(['administer site configuration', 'administer software updates']); + $this->drupalLogin($update_admin_user); + + $system_info = [ + '#all' => [ + 'version' => '8.0.0', + ], + 'aaa_update_test' => [ + 'project' => 'aaa_update_test', + 'version' => '8.x-1.0', + 'hidden' => FALSE, + ], + ]; + $update_test_config->set('system_info', $system_info)->save(); + $update_status = [ + 'aaa_update_test' => [ + 'status' => UPDATE_NOT_SECURE, + ], + ]; + $update_test_config->set('update_status', $update_status)->save(); + $this->refreshUpdateStatus( + [ + 'drupal' => '0.0', + 'aaa_update_test' => '1_0', + ] + ); + $this->drupalGet('admin/reports/updates'); + $this->assertRaw('

    ' . t('Modules') . '

    '); + $this->assertText(t('Security update required!')); + $this->assertRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project appears.'); + + // Visit the reports page again without the altering and make sure the + // status is back to normal. + $update_test_config->set('update_status', [])->save(); + $this->drupalGet('admin/reports/updates'); + $this->assertRaw('

    ' . t('Modules') . '

    '); + $this->assertNoText(t('Security update required!')); + $this->assertRaw(\Drupal::l(t('AAA Update test'), Url::fromUri('http://example.com/project/aaa_update_test')), 'Link to aaa_update_test project appears.'); + + // Turn the altering back on and visit the Update manager UI. + $update_test_config->set('update_status', $update_status)->save(); + $this->drupalGet('admin/modules/update'); + $this->assertText(t('Security update')); + + // Turn the altering back off and visit the Update manager UI. + $update_test_config->set('update_status', [])->save(); + $this->drupalGet('admin/modules/update'); + $this->assertNoText(t('Security update')); + } + +} diff --git a/core/modules/update/tests/src/Functional/UpdateCoreTest.php b/core/modules/update/tests/src/Functional/UpdateCoreTest.php new file mode 100644 index 0000000..a693153 --- /dev/null +++ b/core/modules/update/tests/src/Functional/UpdateCoreTest.php @@ -0,0 +1,368 @@ +drupalCreateUser(['administer site configuration', 'administer modules', 'administer themes']); + $this->drupalLogin($admin_user); + $this->drupalPlaceBlock('local_actions_block'); + } + + /** + * Sets the version to x.x.x when no project-specific mapping is defined. + * + * @param string $version + * The version. + */ + protected function setSystemInfo($version) { + $setting = [ + '#all' => [ + 'version' => $version, + ], + ]; + $this->config('update_test.settings')->set('system_info', $setting)->save(); + } + + /** + * Tests the Update Manager module when no updates are available. + */ + public function testNoUpdatesAvailable() { + foreach ([0, 1] as $minor_version) { + foreach ([0, 1] as $patch_version) { + foreach (['-alpha1', '-beta1', ''] as $extra_version) { + $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version); + $this->refreshUpdateStatus(['drupal' => "$minor_version.$patch_version" . $extra_version]); + $this->standardTests(); + $this->assertText(t('Up to date')); + $this->assertNoText(t('Update available')); + $this->assertNoText(t('Security update required!')); + $this->assertRaw('check.svg', 'Check icon was found.'); + } + } + } + } + + /** + * Tests the Update Manager module when one normal update is available. + */ + public function testNormalUpdateAvailable() { + $this->setSystemInfo('8.0.0'); + + // Ensure that the update check requires a token. + $this->drupalGet('admin/reports/updates/check'); + $this->assertResponse(403, 'Accessing admin/reports/updates/check without a CSRF token results in access denied.'); + + foreach ([0, 1] as $minor_version) { + foreach (['-alpha1', '-beta1', ''] as $extra_version) { + $this->refreshUpdateStatus(['drupal' => "$minor_version.1" . $extra_version]); + $this->standardTests(); + $this->drupalGet('admin/reports/updates'); + $this->clickLink(t('Check manually')); + $this->assertNoText(t('Security update required!')); + $this->assertRaw(\Drupal::l("8.$minor_version.1" . $extra_version, Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release appears.'); + $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version.tar.gz")), 'Link to download appears.'); + $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release notes appears.'); + + switch ($minor_version) { + case 0: + // Both stable and unstable releases are available. + // A stable release is the latest. + if ($extra_version == '') { + $this->assertNoText(t('Up to date')); + $this->assertText(t('Update available')); + $this->assertText(t('Recommended version:')); + $this->assertNoText(t('Latest version:')); + $this->assertRaw('warning.svg', 'Warning icon was found.'); + } + // Only unstable releases are available. + // An unstable release is the latest. + else { + $this->assertText(t('Up to date')); + $this->assertNoText(t('Update available')); + $this->assertNoText(t('Recommended version:')); + $this->assertText(t('Latest version:')); + $this->assertRaw('check.svg', 'Check icon was found.'); + } + break; + case 1: + // Both stable and unstable releases are available. + // A stable release is the latest. + if ($extra_version == '') { + $this->assertNoText(t('Up to date')); + $this->assertText(t('Update available')); + $this->assertText(t('Recommended version:')); + $this->assertNoText(t('Latest version:')); + $this->assertRaw('warning.svg', 'Warning icon was found.'); + } + // Both stable and unstable releases are available. + // An unstable release is the latest. + else { + $this->assertNoText(t('Up to date')); + $this->assertText(t('Update available')); + $this->assertText(t('Recommended version:')); + $this->assertText(t('Latest version:')); + $this->assertRaw('warning.svg', 'Warning icon was found.'); + } + break; + } + } + } + } + + /** + * Tests the Update Manager module when a major update is available. + */ + public function testMajorUpdateAvailable() { + foreach ([0, 1] as $minor_version) { + foreach ([0, 1] as $patch_version) { + foreach (['-alpha1', '-beta1', ''] as $extra_version) { + $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version); + $this->refreshUpdateStatus(['drupal' => '9']); + $this->standardTests(); + $this->drupalGet('admin/reports/updates'); + $this->clickLink(t('Check manually')); + $this->assertNoText(t('Security update required!')); + $this->assertRaw(\Drupal::l('9.0.0', Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release appears.'); + $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-9-0-0.tar.gz")), 'Link to download appears.'); + $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release notes appears.'); + $this->assertNoText(t('Up to date')); + $this->assertText(t('Not supported!')); + $this->assertText(t('Recommended version:')); + $this->assertNoText(t('Latest version:')); + $this->assertRaw('error.svg', 'Error icon was found.'); + } + } + } + } + + /** + * Tests the Update Manager module when a security update is available. + */ + public function testSecurityUpdateAvailable() { + foreach ([0, 1] as $minor_version) { + $this->setSystemInfo("8.$minor_version.0"); + $this->refreshUpdateStatus(['drupal' => "$minor_version.2-sec"]); + $this->standardTests(); + $this->assertNoText(t('Up to date')); + $this->assertNoText(t('Update available')); + $this->assertText(t('Security update required!')); + $this->assertRaw(\Drupal::l("8.$minor_version.2", Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release appears.'); + $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-2.tar.gz")), 'Link to download appears.'); + $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release notes appears.'); + $this->assertRaw('error.svg', 'Error icon was found.'); + } + } + + /** + * Ensures proper results where there are date mismatches among modules. + */ + public function testDatestampMismatch() { + $system_info = [ + '#all' => [ + // We need to think we're running a -dev snapshot to see dates. + 'version' => '8.1.0-dev', + 'datestamp' => time(), + ], + 'block' => [ + // This is 2001-09-09 01:46:40 GMT, so test for "2001-Sep-". + 'datestamp' => '1000000000', + ], + ]; + $this->config('update_test.settings')->set('system_info', $system_info)->save(); + $this->refreshUpdateStatus(['drupal' => '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. + */ + public function testModulePageRunCron() { + $this->setSystemInfo('8.0.0'); + $this->config('update.settings') + ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) + ->save(); + $this->config('update_test.settings') + ->set('xml_map', ['drupal' => '0.0']) + ->save(); + + $this->cronRun(); + $this->drupalGet('admin/modules'); + $this->assertNoText(t('No update information available.')); + } + + /** + * Checks the messages at admin/modules when the site is up to date. + */ + public function testModulePageUpToDate() { + $this->setSystemInfo('8.0.0'); + // Instead of using refreshUpdateStatus(), set these manually. + $this->config('update.settings') + ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) + ->save(); + $this->config('update_test.settings') + ->set('xml_map', ['drupal' => '0.0']) + ->save(); + + $this->drupalGet('admin/reports/updates'); + $this->clickLink(t('Check manually')); + $this->assertText(t('Checked available update data for one project.')); + $this->drupalGet('admin/modules'); + $this->assertNoText(t('There are updates available for your version of Drupal.')); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + } + + /** + * Checks the messages at admin/modules when an update is missing. + */ + public function testModulePageRegularUpdate() { + $this->setSystemInfo('8.0.0'); + // Instead of using refreshUpdateStatus(), set these manually. + $this->config('update.settings') + ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) + ->save(); + $this->config('update_test.settings') + ->set('xml_map', ['drupal' => '0.1']) + ->save(); + + $this->drupalGet('admin/reports/updates'); + $this->clickLink(t('Check manually')); + $this->assertText(t('Checked available update data for one project.')); + $this->drupalGet('admin/modules'); + $this->assertText(t('There are updates available for your version of Drupal.')); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + } + + /** + * Checks the messages at admin/modules when a security update is missing. + */ + public function testModulePageSecurityUpdate() { + $this->setSystemInfo('8.0.0'); + // Instead of using refreshUpdateStatus(), set these manually. + $this->config('update.settings') + ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) + ->save(); + $this->config('update_test.settings') + ->set('xml_map', ['drupal' => '0.2-sec']) + ->save(); + + $this->drupalGet('admin/reports/updates'); + $this->clickLink(t('Check manually')); + $this->assertText(t('Checked available update data for one project.')); + $this->drupalGet('admin/modules'); + $this->assertNoText(t('There are updates available for your version of Drupal.')); + $this->assertText(t('There is a security update available for your version of Drupal.')); + + // Make sure admin/appearance warns you you're missing a security update. + $this->drupalGet('admin/appearance'); + $this->assertNoText(t('There are updates available for your version of Drupal.')); + $this->assertText(t('There is a security update available for your version of Drupal.')); + + // Make sure duplicate messages don't appear on Update status pages. + $this->drupalGet('admin/reports/status'); + // We're expecting "There is a security update..." inside the status report + // itself, but the drupal_set_message() appears as an li so we can prefix + // with that and search for the raw HTML. + $this->assertNoRaw('
  • ' . t('There is a security update available for your version of Drupal.')); + + $this->drupalGet('admin/reports/updates'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + + $this->drupalGet('admin/reports/updates/settings'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + } + + /** + * Tests the Update Manager module when the update server returns 503 errors. + */ + public function testServiceUnavailable() { + $this->refreshUpdateStatus([], '503-error'); + // Ensure that no "Warning: SimpleXMLElement..." parse errors are found. + $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. + */ + public function testFetchTasks() { + $projecta = [ + 'name' => 'aaa_update_test', + ]; + $projectb = [ + 'name' => 'bbb_update_test', + ]; + $queue = \Drupal::queue('update_fetch_tasks'); + $this->assertEqual($queue->numberOfItems(), 0, 'Queue is empty'); + update_create_fetch_task($projecta); + $this->assertEqual($queue->numberOfItems(), 1, 'Queue contains one item'); + update_create_fetch_task($projectb); + $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items'); + // Try to add project a again. + update_create_fetch_task($projecta); + $this->assertEqual($queue->numberOfItems(), 2, 'Queue still contains two items'); + + // Clear storage and try again. + update_storage_clear(); + update_create_fetch_task($projecta); + $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items'); + } + + /** + * Checks language module in core package at admin/reports/updates. + */ + public function testLanguageModuleUpdate() { + $this->setSystemInfo('8.0.0'); + // Instead of using refreshUpdateStatus(), set these manually. + $this->config('update.settings') + ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) + ->save(); + $this->config('update_test.settings') + ->set('xml_map', ['drupal' => '0.1']) + ->save(); + + $this->drupalGet('admin/reports/updates'); + $this->assertText(t('Language')); + } + + /** + * Ensures that the local actions appear. + */ + public function testLocalActions() { + $admin_user = $this->drupalCreateUser(['administer site configuration', 'administer modules', 'administer software updates', 'administer themes']); + $this->drupalLogin($admin_user); + + $this->drupalGet('admin/modules'); + $this->clickLink(t('Install new module')); + $this->assertUrl('admin/modules/install'); + + $this->drupalGet('admin/appearance'); + $this->clickLink(t('Install new theme')); + $this->assertUrl('admin/theme/install'); + + $this->drupalGet('admin/reports/updates'); + $this->clickLink(t('Install new module or theme')); + $this->assertUrl('admin/reports/updates/install'); + } + +} diff --git a/core/modules/update/tests/src/Functional/UpdateDeleteFileIfStaleTest.php b/core/modules/update/tests/src/Functional/UpdateDeleteFileIfStaleTest.php new file mode 100644 index 0000000..601a6cc --- /dev/null +++ b/core/modules/update/tests/src/Functional/UpdateDeleteFileIfStaleTest.php @@ -0,0 +1,47 @@ +randomMachineName()); + $this->assertNotNull($file_name); + + // During testing the file change and the stale checking occurs in the same + // request, so the beginning of request will be before the file changes and + // REQUEST_TIME - $filectime is negative. Set the maximum age to a number + // even smaller than that. + $this->config('system.file') + ->set('temporary_maximum_age', -100000) + ->save(); + + $file_path = drupal_realpath($file_name); + update_delete_file_if_stale($file_path); + + $this->assertFalse(is_file($file_path)); + } + +} diff --git a/core/modules/update/tests/src/Functional/UpdateTestBase.php b/core/modules/update/tests/src/Functional/UpdateTestBase.php new file mode 100644 index 0000000..97860ff --- /dev/null +++ b/core/modules/update/tests/src/Functional/UpdateTestBase.php @@ -0,0 +1,83 @@ +container->get('update.root') . '/' . DrupalKernel::findSitePath($request); + $this->container->set('update.root', $update_root); + \Drupal::setContainer($this->container); + + // Create the directories within the root path within which the Update + // Manager will install projects. + foreach (drupal_get_updaters() as $updater_info) { + $updater = $updater_info['class']; + $install_directory = $update_root . '/' . $updater::getRootDirectoryRelativePath(); + if (!is_dir($install_directory)) { + mkdir($install_directory); + } + } + } + + /** + * 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 Drupal\update_test\Controller\UpdateTestController::updateTest() + */ + protected function refreshUpdateStatus($xml_map, $url = 'update-test') { + // Tell the Update Manager module to fetch from the URL provided by + // update_test module. + $this->config('update.settings')->set('fetch.url', Url::fromUri('base:' . $url, ['absolute' => TRUE])->toString())->save(); + // Save the map for UpdateTestController::updateTest() to use. + $this->config('update_test.settings')->set('xml_map', $xml_map)->save(); + // Manually check the update status. + $this->drupalGet('admin/reports/updates'); + $this->clickLink(t('Check manually')); + } + + /** + * Runs a series of assertions that are applicable to all update statuses. + */ + protected function standardTests() { + $this->assertRaw('

    ' . t('Drupal core') . '

    '); + $this->assertRaw(\Drupal::l(t('Drupal'), Url::fromUri('http://example.com/project/drupal')), 'Link to the Drupal project appears.'); + $this->assertNoText(t('No available releases found')); + } + +} diff --git a/core/modules/update/tests/src/Functional/UpdateUploadTest.php b/core/modules/update/tests/src/Functional/UpdateUploadTest.php new file mode 100644 index 0000000..fca76b2 --- /dev/null +++ b/core/modules/update/tests/src/Functional/UpdateUploadTest.php @@ -0,0 +1,195 @@ +drupalCreateUser(['administer modules', 'administer software updates', 'administer site configuration']); + $this->drupalLogin($admin_user); + } + + /** + * Tests upload, extraction, and update of a module. + */ + public function testUploadModule() { + // Ensure that the update information is correct before testing. + update_get_available(TRUE); + + // Images are not valid archives, so get one and try to install it. We + // need an extra variable to store the result of drupalGetTestFiles() + // since reset() takes an argument by reference and passing in a constant + // emits a notice in strict mode. + $imageTestFiles = $this->drupalGetTestFiles('image'); + $invalidArchiveFile = reset($imageTestFiles); + $edit = [ + 'files[project_upload]' => $invalidArchiveFile->uri, + ]; + // This also checks that the correct archive extensions are allowed. + $this->drupalPostForm('admin/modules/install', $edit, t('Install')); + $this->assertText(t('Only files with the following extensions are allowed: @archive_extensions.', ['@archive_extensions' => archiver_get_extensions()]), 'Only valid archives can be uploaded.'); + $this->assertUrl('admin/modules/install'); + + // Check to ensure an existing module can't be reinstalled. Also checks that + // the archive was extracted since we can't know if the module is already + // installed until after extraction. + $validArchiveFile = __DIR__ . '/../../tests/aaa_update_test.tar.gz'; + $edit = [ + 'files[project_upload]' => $validArchiveFile, + ]; + $this->drupalPostForm('admin/modules/install', $edit, t('Install')); + $this->assertText(t('@module_name is already installed.', ['@module_name' => 'AAA Update test']), 'Existing module was extracted and not reinstalled.'); + $this->assertUrl('admin/modules/install'); + + // Ensure that a new module can be extracted and installed. + $updaters = drupal_get_updaters(); + $moduleUpdater = $updaters['module']['class']; + $installedInfoFilePath = $this->container->get('update.root') . '/' . $moduleUpdater::getRootDirectoryRelativePath() . '/update_test_new_module/update_test_new_module.info.yml'; + $this->assertFalse(file_exists($installedInfoFilePath), 'The new module does not exist in the filesystem before it is installed with the Update Manager.'); + $validArchiveFile = __DIR__ . '/../../tests/update_test_new_module/8.x-1.0/update_test_new_module.tar.gz'; + $edit = [ + 'files[project_upload]' => $validArchiveFile, + ]; + $this->drupalPostForm('admin/modules/install', $edit, t('Install')); + // Check that submitting the form takes the user to authorize.php. + $this->assertUrl('core/authorize.php'); + $this->assertTitle('Update manager | Drupal'); + // Check for a success message on the page, and check that the installed + // module now exists in the expected place in the filesystem. + $this->assertRaw(t('Installed %project_name successfully', ['%project_name' => 'update_test_new_module'])); + $this->assertTrue(file_exists($installedInfoFilePath), 'The new module exists in the filesystem after it is installed with the Update Manager.'); + // Ensure the links are relative to the site root and not + // core/authorize.php. + $this->assertLink(t('Install another module')); + $this->assertLinkByHref(Url::fromRoute('update.module_install')->toString()); + $this->assertLink(t('Enable newly added modules')); + $this->assertLinkByHref(Url::fromRoute('system.modules_list')->toString()); + $this->assertLink(t('Administration pages')); + $this->assertLinkByHref(Url::fromRoute('system.admin')->toString()); + // Ensure we can reach the "Install another module" link. + $this->clickLink(t('Install another module')); + $this->assertResponse(200); + $this->assertUrl('admin/modules/install'); + + // Check that the module has the correct version before trying to update + // it. Since the module is installed in sites/simpletest, which only the + // child site has access to, standard module API functions won't find it + // when called here. To get the version, the info file must be parsed + // directly instead. + $info_parser = new InfoParserDynamic(); + $info = $info_parser->parse($installedInfoFilePath); + $this->assertEqual($info['version'], '8.x-1.0'); + + // Enable the module. + $this->drupalPostForm('admin/modules', ['modules[update_test_new_module][enable]' => TRUE], t('Install')); + + // Define the update XML such that the new module downloaded above needs an + // update from 8.x-1.0 to 8.x-1.1. + $update_test_config = $this->config('update_test.settings'); + $system_info = [ + 'update_test_new_module' => [ + 'project' => 'update_test_new_module', + ], + ]; + $update_test_config->set('system_info', $system_info)->save(); + $xml_mapping = [ + 'update_test_new_module' => '1_1', + ]; + $this->refreshUpdateStatus($xml_mapping); + + // Run the updates for the new module. + $this->drupalPostForm('admin/reports/updates/update', ['projects[update_test_new_module]' => TRUE], t('Download these updates')); + $this->drupalPostForm(NULL, ['maintenance_mode' => FALSE], t('Continue')); + $this->assertText(t('Update was completed successfully.')); + $this->assertRaw(t('Installed %project_name successfully', ['%project_name' => 'update_test_new_module'])); + + // Parse the info file again to check that the module has been updated to + // 8.x-1.1. + $info = $info_parser->parse($installedInfoFilePath); + $this->assertEqual($info['version'], '8.x-1.1'); + } + + /** + * Ensures that archiver extensions are properly merged in the UI. + */ + public function testFileNameExtensionMerging() { + $this->drupalGet('admin/modules/install'); + // Make sure the bogus extension supported by update_test.module is there. + $this->assertPattern('/file extensions are supported:.*update-test-extension/', "Found 'update-test-extension' extension."); + // Make sure it didn't clobber the first option from core. + $this->assertPattern('/file extensions are supported:.*tar/', "Found 'tar' extension."); + } + + /** + * Checks the messages on update manager pages when missing a security update. + */ + public function testUpdateManagerCoreSecurityUpdateMessages() { + $setting = [ + '#all' => [ + 'version' => '8.0.0', + ], + ]; + $this->config('update_test.settings') + ->set('system_info', $setting) + ->set('xml_map', ['drupal' => '0.2-sec']) + ->save(); + $this->config('update.settings') + ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString()) + ->save(); + // Initialize the update status. + $this->drupalGet('admin/reports/updates'); + + // Now, make sure none of the Update manager pages have duplicate messages + // about core missing a security update. + + $this->drupalGet('admin/modules/install'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + + $this->drupalGet('admin/modules/update'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + + $this->drupalGet('admin/appearance/install'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + + $this->drupalGet('admin/appearance/update'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + + $this->drupalGet('admin/reports/updates/install'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + + $this->drupalGet('admin/reports/updates/update'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + + $this->drupalGet('admin/update/ready'); + $this->assertNoText(t('There is a security update available for your version of Drupal.')); + } + + /** + * Tests only an *.info.yml file are detected without supporting files. + */ + public function testUpdateDirectory() { + $type = Updater::getUpdaterFromDirectory(\Drupal::root() . '/core/modules/update/tests/modules/aaa_update_test'); + $this->assertEqual($type, 'Drupal\\Core\\Updater\\Module', 'Detected a Module'); + + $type = Updater::getUpdaterFromDirectory(\Drupal::root() . '/core/modules/update/tests/themes/update_test_basetheme'); + $this->assertEqual($type, 'Drupal\\Core\\Updater\\Theme', 'Detected a Theme.'); + } + +}