Skip to content
Snippets Groups Projects
Commit de577fda authored by Adam G-H's avatar Adam G-H
Browse files

Issue #3246673 by phenaproxima, tedbow: Move PendingUpdatesValidator into Package Manager

parent 40028a69
No related branches found
No related tags found
No related merge requests found
Showing
with 199 additions and 122 deletions
......@@ -59,11 +59,9 @@ services:
tags:
- { name: event_subscriber }
automatic_updates.pending_updates_validator:
class: Drupal\automatic_updates\Validator\PendingUpdatesValidator
class: Drupal\automatic_updates\Validator\PackageManagerReadinessCheck
arguments:
- '%app.root%'
- '@update.post_update_registry'
- '@string_translation'
- '@package_manager.validator.pending_updates'
tags:
- { name: event_subscriber }
automatic_updates.validator.file_system_permissions:
......
......@@ -100,3 +100,11 @@ services:
- '@string_translation'
tags:
- { name: event_subscriber }
package_manager.validator.pending_updates:
class: Drupal\package_manager\EventSubscriber\PendingUpdatesValidator
arguments:
- '%app.root%'
- '@update.post_update_registry'
- '@string_translation'
tags:
- { name: event_subscriber }
<?php
namespace Drupal\automatic_updates\Validator;
namespace Drupal\package_manager\EventSubscriber;
use Drupal\automatic_updates\Event\ReadinessCheckEvent;
use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\Event\StageEvent;
use Drupal\package_manager\ValidationResult;
......@@ -10,12 +9,11 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\Update\UpdateRegistry;
use Drupal\Core\Url;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Validates that there are no pending database updates.
*/
class PendingUpdatesValidator implements EventSubscriberInterface {
class PendingUpdatesValidator implements StageValidatorInterface {
use StringTranslationTrait;
......@@ -50,12 +48,9 @@ class PendingUpdatesValidator implements EventSubscriberInterface {
}
/**
* Validates that there are no pending database updates.
*
* @param \Drupal\package_manager\Event\StageEvent $event
* The event object.
* {@inheritdoc}
*/
public function checkPendingUpdates(StageEvent $event): void {
public function validateStage(StageEvent $event): void {
require_once $this->appRoot . '/core/includes/install.inc';
require_once $this->appRoot . '/core/includes/update.inc';
......@@ -77,8 +72,7 @@ class PendingUpdatesValidator implements EventSubscriberInterface {
*/
public static function getSubscribedEvents() {
return [
PreCreateEvent::class => 'checkPendingUpdates',
ReadinessCheckEvent::class => 'checkPendingUpdates',
PreCreateEvent::class => 'validateStage',
];
}
......
......@@ -6,7 +6,9 @@
*/
/**
* Here is a fake update.
* Here is a fake update hook.
*
* The schema version is the maximum possible value for a 32-bit integer.
*/
function automatic_updates_update_50000() {
function package_manager_update_2147483647() {
}
......@@ -2,11 +2,9 @@
namespace Drupal\Tests\package_manager\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\EventSubscriber\ComposerExecutableValidator;
use Drupal\package_manager\ValidationResult;
use Drupal\Tests\package_manager\Traits\ValidationTestTrait;
use PhpTuf\ComposerStager\Exception\IOException;
use PhpTuf\ComposerStager\Infrastructure\Process\ExecutableFinderInterface;
use Prophecy\Argument;
......@@ -16,29 +14,7 @@ use Prophecy\Argument;
*
* @group package_manager
*/
class ComposerExecutableValidatorTest extends KernelTestBase {
use ValidationTestTrait;
/**
* {@inheritdoc}
*/
protected static $modules = ['package_manager'];
/**
* Runs the validator under test, and asserts its results match expectations.
*
* @param \Drupal\package_manager\ValidationResult[] $expected_results
* The expected validation results.
*/
private function assertResults(array $expected_results): void {
$stage = $this->prophesize('\Drupal\package_manager\Stage');
$event = new PreCreateEvent($stage->reveal());
$this->container->get('package_manager.validator.composer_executable')
->validateStage($event);
$this->assertValidationResultsEqual($expected_results, $event->getResults());
}
class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
/**
* Tests that an error is raised if the Composer executable isn't found.
......@@ -58,7 +34,7 @@ class ComposerExecutableValidatorTest extends KernelTestBase {
$error = ValidationResult::createError([
$exception->getMessage(),
]);
$this->assertResults([$error]);
$this->assertResults([$error], PreCreateEvent::class);
}
/**
......@@ -155,7 +131,7 @@ class ComposerExecutableValidatorTest extends KernelTestBase {
// If the validator can't find a recognized, supported version of Composer,
// it should produce errors.
$this->assertResults($expected_results);
$this->assertResults($expected_results, PreCreateEvent::class);
}
}
......@@ -2,26 +2,17 @@
namespace Drupal\Tests\package_manager\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\EventSubscriber\DiskSpaceValidator;
use Drupal\package_manager\ValidationResult;
use Drupal\Component\Utility\Bytes;
use Drupal\Tests\package_manager\Traits\ValidationTestTrait;
/**
* @covers \Drupal\package_manager\EventSubscriber\DiskSpaceValidator
*
* @group package_manager
*/
class DiskSpaceValidatorTest extends KernelTestBase {
use ValidationTestTrait;
/**
* {@inheritdoc}
*/
protected static $modules = ['package_manager'];
class DiskSpaceValidatorTest extends PackageManagerKernelTestBase {
/**
* Data provider for ::testDiskSpaceValidation().
......@@ -201,11 +192,7 @@ class DiskSpaceValidatorTest extends KernelTestBase {
$validator->sharedDisk = $shared_disk;
$validator->freeSpace = array_map([Bytes::class, 'toNumber'], $free_space);
$stage = $this->prophesize('\Drupal\package_manager\Stage');
$event = new PreCreateEvent($stage->reveal());
$validator->validateStage($event);
$this->assertValidationResultsEqual($expected_results, $event->getResults());
$this->assertResults($expected_results, PreCreateEvent::class);
}
}
<?php
namespace Drupal\Tests\package_manager\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\package_manager\Event\StageEvent;
use Drupal\package_manager\Stage;
use Drupal\package_manager\StageException;
use Drupal\Tests\package_manager\Traits\ValidationTestTrait;
/**
* Base class for kernel tests of Package Manager's functionality.
*/
abstract class PackageManagerKernelTestBase extends KernelTestBase {
use ValidationTestTrait;
/**
* {@inheritdoc}
*/
protected static $modules = [
'package_manager',
'package_manager_bypass',
];
/**
* Asserts validation results are returned from a stage life cycle event.
*
* @param \Drupal\package_manager\ValidationResult[] $expected_results
* The expected validation results.
* @param string $event_class
* The class of the event which should return the results.
*/
protected function assertResults(array $expected_results, string $event_class): void {
$stage = new TestStage(
$this->container->get('package_manager.path_locator'),
$this->container->get('package_manager.beginner'),
$this->container->get('package_manager.stager'),
$this->container->get('package_manager.committer'),
$this->container->get('package_manager.cleaner'),
$this->container->get('event_dispatcher'),
);
try {
$stage->create();
$stage->require(['drupal/core:9.8.1']);
$stage->apply();
$stage->destroy();
}
catch (StageException $e) {
$this->assertValidationResultsEqual($expected_results, $e->getResults());
// TestStage::dispatch() attaches the event object to the exception so
// that we can analyze it.
$this->assertInstanceOf($event_class, $e->event);
}
// If no errors are raised, we won't have asserted anything and the test
// will be marked as risky. To prevent that, assert an eternal truth.
$this->assertTrue(TRUE);
}
}
/**
* Defines a stage specifically for testing purposes.
*/
class TestStage extends Stage {
/**
* {@inheritdoc}
*/
protected function dispatch(StageEvent $event): void {
try {
parent::dispatch($event);
}
catch (StageException $e) {
// Attach the event object to the exception so that test code can verify
// that the exception was thrown when a specific event was dispatched.
$e->event = $event;
throw $e;
}
}
}
<?php
namespace Drupal\Tests\package_manager\Kernel;
use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\ValidationResult;
/**
* @covers \Drupal\package_manager\EventSubscriber\PendingUpdatesValidator
*
* @group package_manager
*/
class PendingUpdatesValidatorTest extends PackageManagerKernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['system'];
/**
* Registers all of the System module's post-update functions.
*
* Since kernel tests don't normally install modules and register their
* updates, this method makes sure that the validator is tested from a clean,
* fully up-to-date state.
*/
private function registerPostUpdateFunctions(): void {
$updates = $this->container->get('update.post_update_registry')
->getPendingUpdateFunctions();
$this->container->get('keyvalue')
->get('post_update')
->set('existing_updates', $updates);
}
/**
* Tests that no error is raised if there are no pending updates.
*/
public function testNoPendingUpdates(): void {
$this->registerPostUpdateFunctions();
$this->assertResults([], PreCreateEvent::class);
}
/**
* Tests that an error is raised if there are pending schema updates.
*
* @depends testNoPendingUpdates
*/
public function testPendingUpdateHook(): void {
// Register the System module's post-update functions, so that any detected
// pending updates are guaranteed to be schema updates.
$this->registerPostUpdateFunctions();
// Set the installed schema version of Package Manager to its default value
// and import an empty update hook which is numbered much higher than will
// ever exist in the real world.
$this->container->get('keyvalue')
->get('system.schema')
->set('package_manager', \Drupal::CORE_MINIMUM_SCHEMA_VERSION);
require_once __DIR__ . '/../../fixtures/db_update.php';
$result = ValidationResult::createError([
'Some modules have database schema updates to install. You should run the <a href="/update.php">database update script</a> immediately.',
]);
$this->assertResults([$result], PreCreateEvent::class);
}
/**
* Tests that an error is raised if there are pending post-updates.
*/
public function testPendingPostUpdate(): void {
// The System module's post-update functions have not been registered, so
// the update registry will think they're pending.
$result = ValidationResult::createError([
'Some modules have database schema updates to install. You should run the <a href="/update.php">database update script</a> immediately.',
]);
$this->assertResults([$result], PreCreateEvent::class);
}
}
<?php
/**
* @file
* Contains a fake post-update function for testing.
*/
/**
* Here is a fake post-update.
*/
function automatic_updates_post_update_test() {
}
......@@ -16,6 +16,7 @@ use Prophecy\Argument;
*
* @see \Drupal\Tests\package_manager\Kernel\ComposerExecutableValidatorTest
* @see \Drupal\Tests\package_manager\Kernel\DiskSpaceValidatorTest
* @see \Drupal\Tests\package_manager\Kernel\PendingUpdatesValidatorTest
*/
class PackageManagerReadinessChecksTest extends AutomaticUpdatesKernelTestBase {
......@@ -37,6 +38,7 @@ class PackageManagerReadinessChecksTest extends AutomaticUpdatesKernelTestBase {
return [
['package_manager.validator.composer_executable'],
['package_manager.validator.disk_space'],
['package_manager.validator.pending_updates'],
];
}
......
<?php
namespace Drupal\Tests\automatic_updates\Kernel\ReadinessValidation;
use Drupal\package_manager\ValidationResult;
use Drupal\Tests\automatic_updates\Kernel\AutomaticUpdatesKernelTestBase;
/**
* @covers \Drupal\automatic_updates\Validator\PendingUpdatesValidator
*
* @group automatic_updates
*/
class PendingUpdatesValidatorTest extends AutomaticUpdatesKernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'automatic_updates',
'package_manager',
];
/**
* Tests that no error is raised if there are no pending updates.
*/
public function testNoPendingUpdates(): void {
$this->assertCheckerResultsFromManager([], TRUE);
}
/**
* Tests that an error is raised if there are pending schema updates.
*/
public function testPendingUpdateHook(): void {
require __DIR__ . '/../../../fixtures/db_update.php';
$this->container->get('keyvalue')
->get('system.schema')
->set('automatic_updates', \Drupal::CORE_MINIMUM_SCHEMA_VERSION);
$result = ValidationResult::createError(['Some modules have database schema updates to install. You should run the <a href="/update.php">database update script</a> immediately.']);
$this->assertCheckerResultsFromManager([$result], TRUE);
}
/**
* Tests that an error is raised if there are pending post-updates.
*/
public function testPendingPostUpdate(): void {
require __DIR__ . '/../../../fixtures/post_update.php';
$result = ValidationResult::createError(['Some modules have database schema updates to install. You should run the <a href="/update.php">database update script</a> immediately.']);
$this->assertCheckerResultsFromManager([$result], TRUE);
}
}
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