Skip to content
Snippets Groups Projects
Commit 04013d23 authored by Ted Bowman's avatar Ted Bowman
Browse files

Issue #3274269 by tedbow: Ensure all installable releases are exposed

parent 61aba172
No related branches found
No related tags found
No related merge requests found
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
namespace Drupal\automatic_updates; namespace Drupal\automatic_updates;
use Composer\Semver\Comparator; use Composer\Semver\Comparator;
use Composer\Semver\Semver;
use Drupal\automatic_updates_9_3_shim\ProjectRelease; use Drupal\automatic_updates_9_3_shim\ProjectRelease;
use Drupal\Core\Extension\ExtensionVersion;
use Drupal\update\UpdateManagerInterface; use Drupal\update\UpdateManagerInterface;
/** /**
...@@ -32,6 +32,37 @@ class ProjectInfo { ...@@ -32,6 +32,37 @@ class ProjectInfo {
$this->name = $name; $this->name = $name;
} }
/**
* Determines if a release can be installed.
*
* @param \Drupal\automatic_updates_9_3_shim\ProjectRelease $release
* The project release.
* @param string[] $support_branches
* The supported branches.
*
* @return bool
* TRUE if the release is installable, otherwise FALSE. A release will be
* considered installable if it is secure, published, supported, in
* a supported branch, and newer than currently installed version.
*/
private function isInstallable(ProjectRelease $release, array $support_branches): bool {
if ($release->isInsecure() || !$release->isPublished() || $release->isUnsupported()) {
return FALSE;
}
$installed_version = $this->getInstalledVersion();
if (Comparator::lessThanOrEqualTo($release->getVersion(), $installed_version)) {
return FALSE;
}
$version = ExtensionVersion::createFromVersionString($release->getVersion());
foreach ($support_branches as $support_branch) {
$support_branch_version = ExtensionVersion::createFromSupportBranch($support_branch);
if ($support_branch_version->getMajorVersion() === $version->getMajorVersion() && $support_branch_version->getMinorVersion() === $version->getMinorVersion()) {
return TRUE;
}
}
return FALSE;
}
/** /**
* Returns up-to-date project information. * Returns up-to-date project information.
* *
...@@ -66,36 +97,34 @@ class ProjectInfo { ...@@ -66,36 +97,34 @@ class ProjectInfo {
if (!$project) { if (!$project) {
return NULL; return NULL;
} }
$installed_version = $this->getInstalledVersion(); $available_updates = update_get_available()[$this->name];
// If we were able to get available releases we should always have at least if ($available_updates['project_status'] !== 'published') {
// the current release stored. throw new \RuntimeException("The project '{$this->name}' can not be updated because its status is " . $available_updates['project_status']);
if (empty($project['releases'])) {
throw new \RuntimeException('There was a problem getting update information. Try again later.');
} }
// If we're already up-to-date, there's nothing else we need to do. // If we're already up-to-date, there's nothing else we need to do.
if ($project['status'] === UpdateManagerInterface::CURRENT) { if ($project['status'] === UpdateManagerInterface::CURRENT) {
return []; return [];
} }
elseif (empty($project['recommended'])) {
// If we don't know what to recommend they update to, time to freak out. if (empty($available_updates['releases'])) {
throw new \LogicException("The '{$this->name}' project is out of date, but the recommended version could not be determined."); // If project is not current we should always have at least one release.
throw new \RuntimeException('There was a problem getting update information. Try again later.');
} }
$installed_version = $this->getInstalledVersion();
$support_branches = explode(',', $available_updates['supported_branches']);
$installable_releases = []; $installable_releases = [];
if (Comparator::greaterThan($project['recommended'], $installed_version)) { foreach ($available_updates['releases'] as $release_info) {
$release = ProjectRelease::createFromArray($project['releases'][$project['recommended']]); $release = ProjectRelease::createFromArray($release_info);
$installable_releases[$release->getVersion()] = $release; $version = $release->getVersion();
} if (Comparator::lessThanOrEqualTo($version, $installed_version)) {
if (!empty($project['security updates'])) { break;
foreach ($project['security updates'] as $security_update) { }
$release = ProjectRelease::createFromArray($security_update); if ($this->isInstallable($release, $support_branches)) {
$version = $release->getVersion(); $installable_releases[$version] = $release;
if (Comparator::greaterThan($version, $installed_version)) {
$installable_releases[$version] = $release;
}
} }
} }
$sorted_versions = Semver::rsort(array_keys($installable_releases)); return $installable_releases;
return array_replace(array_flip($sorted_versions), $installable_releases);
} }
/** /**
......
...@@ -36,5 +36,18 @@ ...@@ -36,5 +36,18 @@
<term><name>Release type</name><value>Insecure</value></term> <term><name>Release type</name><value>Insecure</value></term>
</terms> </terms>
</release> </release>
<release>
<name>Drupal 9.8.0-alpha1</name>
<version>9.8.0-alpha1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-8-0-alpha1-release</release_link>
<download_link>http://example.com/drupal-9-8-0-alpha1-.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
<term><name>Release type</name><value>Insecure</value></term>
</terms>
</release>
</releases> </releases>
</project> </project>
<?xml version="1.0" encoding="utf-8"?>
<project xmlns:dc="http://purl.org/dc/elements/1.1/">
<title>Drupal</title>
<short_name>drupal</short_name>
<dc:creator>Drupal</dc:creator>
<supported_branches>9.7.,9.8.</supported_branches>
<project_status>published</project_status>
<link>http://example.com/project/drupal</link>
<terms>
<term><name>Projects</name><value>Drupal project</value></term>
</terms>
<releases>
<release>
<name>Drupal 9.8.2</name>
<version>9.8.2</version>
<status>published</status>
<release_link>http://example.com/drupal-9-8-2-release</release_link>
<download_link>http://example.com/drupal-9-8-2.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.8.1</name>
<version>9.8.1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-8-1-release</release_link>
<download_link>http://example.com/drupal-9-8-1.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
<term><name>Release type</name><value>Unsupported</value></term>
</terms>
</release>
<release>
<name>Drupal 9.8.0</name>
<version>9.8.0</version>
<status>unpublished</status>
<release_link>http://example.com/drupal-9-8-0-release</release_link>
<download_link>http://example.com/drupal-9-8-0.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.8.0-alpha1</name>
<version>9.8.0-alpha1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-8-0-alpha1-release</release_link>
<download_link>http://example.com/drupal-9-8-0-alpha1.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.7.1</name>
<version>9.7.1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-7-1-release</release_link>
<download_link>http://example.com/drupal-9-7-1.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.7.0</name>
<version>9.7.0</version>
<status>published</status>
<release_link>http://example.com/drupal-9-7-0-release</release_link>
<download_link>http://example.com/drupal-9-7-0.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.7.0-alpha1</name>
<version>9.7.0-alpha1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-7-0-alpha1-release</release_link>
<download_link>http://example.com/drupal-9-7-0-alpha1.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.6.1</name>
<version>9.6.1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-1-release</release_link>
<download_link>http://example.com/drupal-9-6-1.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.6.0</name>
<version>9.6.0</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-0-release</release_link>
<download_link>http://example.com/drupal-9-6-0.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.6.0-alpha1</name>
<version>9.6.0-alpha1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-0-alpha1-release</release_link>
<download_link>http://example.com/drupal-9-6-0-alpha1.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
</releases>
</project>
...@@ -94,5 +94,41 @@ ...@@ -94,5 +94,41 @@
<term><name>Release type</name><value>Bug fixes</value></term> <term><name>Release type</name><value>Bug fixes</value></term>
</terms> </terms>
</release> </release>
<release>
<name>Drupal 9.6.1</name>
<version>9.6.1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-1-release</release_link>
<download_link>http://example.com/drupal-9-6-1.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.6.0</name>
<version>9.6.0</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-0-release</release_link>
<download_link>http://example.com/drupal-9-6-0.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.6.0-alpha1</name>
<version>9.6.0-alpha1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-0-alpha1-release</release_link>
<download_link>http://example.com/drupal-9-6-0-alpha1.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
</releases> </releases>
</project> </project>
<?xml version="1.0" encoding="utf-8"?>
<project xmlns:dc="http://purl.org/dc/elements/1.1/">
<title>Drupal</title>
<short_name>drupal</short_name>
<dc:creator>Drupal</dc:creator>
<supported_branches>9.7.,9.8.</supported_branches>
<project_status>any status besides published</project_status>
<link>http://example.com/project/drupal</link>
<terms>
<term><name>Projects</name><value>Drupal project</value></term>
</terms>
<releases>
<release>
<name>Drupal 9.8.2</name>
<version>9.8.2</version>
<status>published</status>
<release_link>http://example.com/drupal-9-8-2-release</release_link>
<download_link>http://example.com/drupal-9-8-2.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.8.1</name>
<version>9.8.1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-8-1-release</release_link>
<download_link>http://example.com/drupal-9-8-1.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.8.0</name>
<version>9.8.0</version>
<status>published</status>
<release_link>http://example.com/drupal-9-8-0-release</release_link>
<download_link>http://example.com/drupal-9-8-0.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.8.0-alpha1</name>
<version>9.8.0-alpha1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-8-0-alpha1-release</release_link>
<download_link>http://example.com/drupal-9-8-0-alpha1.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.7.1</name>
<version>9.7.1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-7-1-release</release_link>
<download_link>http://example.com/drupal-9-7-1.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.7.0</name>
<version>9.7.0</version>
<status>published</status>
<release_link>http://example.com/drupal-9-7-0-release</release_link>
<download_link>http://example.com/drupal-9-7-0.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.7.0-alpha1</name>
<version>9.7.0-alpha1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-7-0-alpha1-release</release_link>
<download_link>http://example.com/drupal-9-7-0-alpha1.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.6.1</name>
<version>9.6.1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-1-release</release_link>
<download_link>http://example.com/drupal-9-6-1.tar.gz</download_link>
<date>1250425521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.6.0</name>
<version>9.6.0</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-0-release</release_link>
<download_link>http://example.com/drupal-9-6-0.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
<release>
<name>Drupal 9.6.0-alpha1</name>
<version>9.6.0-alpha1</version>
<status>published</status>
<release_link>http://example.com/drupal-9-6-0-alpha1-release</release_link>
<download_link>http://example.com/drupal-9-6-0-alpha1.tar.gz</download_link>
<date>1250424521</date>
<terms>
<term><name>Release type</name><value>New features</value></term>
<term><name>Release type</name><value>Bug fixes</value></term>
</terms>
</release>
</releases>
</project>
...@@ -110,7 +110,7 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase { ...@@ -110,7 +110,7 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase {
'enabled, normal release' => [ 'enabled, normal release' => [
CronUpdater::ALL, CronUpdater::ALL,
"$fixture_dir/drupal.9.8.2.xml", "$fixture_dir/drupal.9.8.2.xml",
FALSE, TRUE,
], ],
'enabled, security release' => [ 'enabled, security release' => [
CronUpdater::ALL, CronUpdater::ALL,
......
<?php
namespace Drupal\Tests\automatic_updates\Kernel;
use Drupal\automatic_updates\ProjectInfo;
/**
* @coversDefaultClass \Drupal\automatic_updates\ProjectInfo
*
* @group automatic_updates
*/
class ProjectInfoTest extends AutomaticUpdatesKernelTestBase {
/**
* @covers ::getInstallableReleases()
*
* @param string $fixture
* The fixture file name.
* @param string $installed_version
* The installed version core version to set.
* @param string[] $expected_versions
* The expected versions.
*
* @dataProvider providerGetInstallableReleases
*/
public function testGetInstallableReleases(string $fixture, string $installed_version, array $expected_versions) {
$this->setReleaseMetadata(__DIR__ . "/../../fixtures/release-history/$fixture");
$this->setCoreVersion($installed_version);
$project_info = new ProjectInfo('drupal');
$actual_releases = $project_info->getInstallableReleases();
// Assert that we returned the correct releases in the expected order.
$this->assertSame($expected_versions, array_keys($actual_releases));
// Assert that we version keys match the actual releases.
foreach ($actual_releases as $version => $release) {
$this->assertSame($version, $release->getVersion());
}
}
/**
* Data provider for testGetInstallableReleases().
*
* @return array[]
* The test cases.
*/
public function providerGetInstallableReleases() {
return [
'no updates' => [
'drupal.9.8.2.xml',
'9.8.2',
[],
],
'on unsupported branch, updates in multiple supported branches' => [
'drupal.9.8.2.xml',
'9.6.0-alpha1',
['9.8.2', '9.8.1', '9.8.0', '9.8.0-alpha1', '9.7.1', '9.7.0', '9.7.0-alpha1'],
],
// A test case with an unpublished release, 9.8.0, and unsupported
// release, 9.8.1, both of these releases should not be returned.
'filter out unsupported and unpublished releases' => [
'drupal.9.8.2-unsupported_unpublished.xml',
'9.6.0-alpha1',
['9.8.2', '9.8.0-alpha1', '9.7.1', '9.7.0', '9.7.0-alpha1'],
],
'supported branches before and after installed release' => [
'drupal.9.8.2.xml',
'9.8.0-alpha1',
['9.8.2', '9.8.1', '9.8.0'],
],
'one insecure release filtered out' => [
'drupal.9.8.1-security.xml',
'9.8.0-alpha1',
['9.8.1'],
],
'skip insecure releases and return secure releases' => [
'drupal.9.8.2-older-sec-release.xml',
'9.7.0-alpha1',
['9.8.2', '9.8.1', '9.8.0-alpha1', '9.7.1'],
],
];
}
/**
* Tests a project with a status other than "published".
*
* @covers ::getInstallableReleases()
*/
public function testNotPublishedProject() {
$this->setReleaseMetadata(__DIR__ . '/../../fixtures/release-history/drupal.9.8.2_unknown_status.xml');
$project_info = new ProjectInfo('drupal');
$this->expectException('RuntimeException');
$this->expectExceptionMessage("The project 'drupal' can not be updated because its status is any status besides published");
$project_info->getInstallableReleases();
}
}
...@@ -180,22 +180,25 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase { ...@@ -180,22 +180,25 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase {
* Sets of arguments to pass to the test method. * Sets of arguments to pass to the test method.
*/ */
public function providerCronUpdateTwoPatchReleasesAhead(): array { public function providerCronUpdateTwoPatchReleasesAhead(): array {
$update_disallowed = ValidationResult::createError([
'Drupal cannot be automatically updated during cron from its current version, 9.8.0, to the recommended version, 9.8.2, because Automatic Updates only supports 1 patch version update during cron.',
]);
return [ return [
'disabled' => [ 'disabled' => [
CronUpdater::DISABLED, CronUpdater::DISABLED,
[], [],
0,
], ],
'security only' => [ 'security only' => [
CronUpdater::SECURITY, CronUpdater::SECURITY,
[$update_disallowed], [
ValidationResult::createError([
'Drupal cannot be automatically updated during cron from its current version, 9.8.0, to the recommended version, 9.8.1, because 9.8.1 is not a security release.',
]),
],
0,
], ],
'all' => [ 'all' => [
CronUpdater::ALL, CronUpdater::ALL,
[$update_disallowed], [],
1,
], ],
]; ];
} }
...@@ -208,10 +211,12 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase { ...@@ -208,10 +211,12 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase {
* @param \Drupal\package_manager\ValidationResult[] $expected_results * @param \Drupal\package_manager\ValidationResult[] $expected_results
* The expected validation results, which should be logged as errors if the * The expected validation results, which should be logged as errors if the
* update is attempted during cron. * update is attempted during cron.
* @param int $expected_stage_times
* The expected number of times the update should have been staged.
* *
* @dataProvider providerCronUpdateTwoPatchReleasesAhead * @dataProvider providerCronUpdateTwoPatchReleasesAhead
*/ */
public function testCronUpdateTwoPatchReleasesAhead(string $cron_setting, array $expected_results): void { public function testCronUpdateTwoPatchReleasesAhead(string $cron_setting, array $expected_results, int $expected_stage_times): void {
$this->setCoreVersion('9.8.0'); $this->setCoreVersion('9.8.0');
$this->config('automatic_updates.settings') $this->config('automatic_updates.settings')
->set('cron', $cron_setting) ->set('cron', $cron_setting)
...@@ -219,7 +224,7 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase { ...@@ -219,7 +224,7 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase {
$this->assertCheckerResultsFromManager($expected_results, TRUE); $this->assertCheckerResultsFromManager($expected_results, TRUE);
$this->container->get('cron')->run(); $this->container->get('cron')->run();
$this->assertUpdateStagedTimes(0); $this->assertUpdateStagedTimes($expected_stage_times);
} }
/** /**
...@@ -283,10 +288,10 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase { ...@@ -283,10 +288,10 @@ class UpdateVersionValidatorTest extends AutomaticUpdatesKernelTestBase {
'Drupal cannot be automatically updated during cron from its current version, 9.8.0-alpha1, because Automatic Updates only supports updating from stable versions during cron.', 'Drupal cannot be automatically updated during cron from its current version, 9.8.0-alpha1, because Automatic Updates only supports updating from stable versions during cron.',
]); ]);
$dev_current_version = ValidationResult::createError([ $dev_current_version = ValidationResult::createError([
'Drupal cannot be automatically updated from its current version, 9.8.0-dev, to the recommended version, 9.8.2, because automatic updates from a dev version to any other version are not supported.', 'Drupal cannot be automatically updated from its current version, 9.8.0-dev, to the recommended version, 9.8.0-alpha1, because automatic updates from a dev version to any other version are not supported.',
]); ]);
$different_major_version = ValidationResult::createError([ $different_major_version = ValidationResult::createError([
'Drupal cannot be automatically updated from its current version, 8.9.1, to the recommended version, 9.8.2, because automatic updates from one major version to another are not supported.', 'Drupal cannot be automatically updated from its current version, 8.9.1, to the recommended version, 9.7.0-alpha1, because automatic updates from one major version to another are not supported.',
]); ]);
return [ return [
......
<?php
namespace Drupal\Tests\automatic_updates\Unit;
use Drupal\automatic_updates\ProjectInfo;
use Drupal\automatic_updates_9_3_shim\ProjectRelease;
use Drupal\Tests\UnitTestCase;
use Drupal\update\UpdateManagerInterface;
/**
* @coversDefaultClass \Drupal\automatic_updates\ProjectInfo
*
* @group automatic_updates
*/
class ProjectInfoTest extends UnitTestCase {
/**
* Creates release data for testing.
*
* @return string[][]
* The release information.
*/
private static function createTestReleases(): array {
$versions = ['8.2.5', '8.2.4', '8.2.3', '8.2.3-alpha'];
foreach ($versions as $version) {
$release_arrays[$version] = [
'status' => 'published',
'version' => $version,
'release_link' => "https://example.drupal.org/project/drupal/releases/$version",
];
}
return $release_arrays;
}
/**
* Data provider for testGetInstallableReleases().
*
* @return array[][]
* The test cases.
*/
public function providerGetInstallableReleases(): array {
$release_arrays = static::createTestReleases();
foreach ($release_arrays as $version => $release_array) {
$release_objects[$version] = ProjectRelease::createFromArray($release_array);
}
return [
'current' => [
[
'status' => UpdateManagerInterface::CURRENT,
'existing_version' => '1.2.3',
],
[],
],
'1 release' => [
[
'status' => UpdateManagerInterface::NOT_CURRENT,
'existing_version' => '8.2.4',
'recommended' => '8.2.5',
'releases' => [
'8.2.5' => $release_arrays['8.2.5'],
],
],
[
'8.2.5' => $release_objects['8.2.5'],
],
],
'1 releases, also security' => [
[
'status' => UpdateManagerInterface::NOT_CURRENT,
'existing_version' => '8.2.4',
'recommended' => '8.2.5',
'releases' => [
'8.2.5' => $release_arrays['8.2.5'],
],
'security updates' => [
$release_arrays['8.2.5'],
],
],
[
'8.2.5' => $release_objects['8.2.5'],
],
],
'1 release, other security' => [
[
'status' => UpdateManagerInterface::NOT_CURRENT,
'existing_version' => '8.2.2',
'recommended' => '8.2.5',
'releases' => [
'8.2.5' => $release_arrays['8.2.5'],
],
'security updates' => [
// Set out of order security releases to ensure results are sorted.
$release_arrays['8.2.3-alpha'],
$release_arrays['8.2.3'],
$release_arrays['8.2.4'],
],
],
[
'8.2.5' => $release_objects['8.2.5'],
'8.2.4' => $release_objects['8.2.4'],
'8.2.3' => $release_objects['8.2.3'],
'8.2.3-alpha' => $release_objects['8.2.3-alpha'],
],
],
'1 releases, other security lower than current version' => [
[
'status' => UpdateManagerInterface::NOT_CURRENT,
'existing_version' => '8.2.3',
'recommended' => '8.2.5',
'releases' => [
'8.2.5' => $release_arrays['8.2.5'],
],
'security updates' => [
// Set out of order security releases to ensure results are sorted.
$release_arrays['8.2.3-alpha'],
$release_arrays['8.2.3'],
$release_arrays['8.2.4'],
],
],
[
'8.2.5' => $release_objects['8.2.5'],
'8.2.4' => $release_objects['8.2.4'],
],
],
'no data' => [
NULL,
NULL,
],
];
}
/**
* @covers ::getInstallableReleases
*
* @param array|null $project_data
* The project data to return from ::getProjectInfo().
* @param \Drupal\automatic_updates_9_3_shim\ProjectRelease[]|null $expected_releases
* The expected releases.
*
* @dataProvider providerGetInstallableReleases
*/
public function testGetInstallableReleases(?array $project_data, ?array $expected_releases): void {
$project_info = $this->getMockedProjectInfo($project_data);
// If data is returned, but there are no releases, we should get an
// exception.
if (isset($project_data, $expected_releases) && empty($project_data['releases'])) {
$this->expectExceptionMessage('There was a problem getting update information. Try again later.');
}
$this->assertEqualsCanonicalizing($expected_releases, $project_info->getInstallableReleases());
}
/**
* @covers ::getInstallableReleases
*/
public function testInvalidProjectData(): void {
$release_arrays = static::createTestReleases();
$project_data = [
'status' => UpdateManagerInterface::NOT_CURRENT,
'existing_version' => '1.2.3',
'releases' => [
'8.2.5' => $release_arrays['8.2.5'],
],
'security updates' => [
$release_arrays['8.2.4'],
$release_arrays['8.2.3'],
$release_arrays['8.2.3-alpha'],
],
];
$project_info = $this->getMockedProjectInfo($project_data);
$this->expectException('LogicException');
$this->expectExceptionMessage("The 'drupal' project is out of date, but the recommended version could not be determined.");
$project_info->getInstallableReleases();
}
/**
* @covers ::getInstalledVersion
*/
public function testGetInstalledVersion(): void {
$project_info = $this->getMockedProjectInfo(['existing_version' => '1.2.3']);
$this->assertSame('1.2.3', $project_info->getInstalledVersion());
$project_info = $this->getMockedProjectInfo(NULL);
$this->assertSame(NULL, $project_info->getInstalledVersion());
}
/**
* Mocks a ProjectInfo object.
*
* @param array|null $project_data
* The project info that should be returned by the mock's ::getProjectInfo()
* method.
*
* @return \Drupal\automatic_updates\ProjectInfo
* The mocked object.
*/
private function getMockedProjectInfo(?array $project_data): ProjectInfo {
$project_info = $this->getMockBuilder(ProjectInfo::class)
->setConstructorArgs(['drupal'])
->onlyMethods(['getProjectInfo'])
->getMock();
$project_info->expects($this->any())
->method('getProjectInfo')
->willReturn($project_data);
return $project_info;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment