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

Issue #3258056 by phenaproxima, tedbow: Simplify Stage::dispatch exception handling

parent 73730fb9
No related branches found
No related tags found
No related merge requests found
...@@ -4,6 +4,8 @@ namespace Drupal\package_manager\Exception; ...@@ -4,6 +4,8 @@ namespace Drupal\package_manager\Exception;
/** /**
* Base class for all exceptions related to staging operations. * Base class for all exceptions related to staging operations.
*
* Should not be thrown by external code.
*/ */
class StageException extends \RuntimeException { class StageException extends \RuntimeException {
} }
...@@ -4,6 +4,8 @@ namespace Drupal\package_manager\Exception; ...@@ -4,6 +4,8 @@ namespace Drupal\package_manager\Exception;
/** /**
* Exception thrown if a stage encounters an ownership or locking error. * Exception thrown if a stage encounters an ownership or locking error.
*
* Should not be thrown by external code.
*/ */
class StageOwnershipException extends StageException { class StageOwnershipException extends StageException {
} }
...@@ -4,6 +4,8 @@ namespace Drupal\package_manager\Exception; ...@@ -4,6 +4,8 @@ namespace Drupal\package_manager\Exception;
/** /**
* Exception thrown if a stage has validation errors. * Exception thrown if a stage has validation errors.
*
* Should not be thrown by external code.
*/ */
class StageValidationException extends StageException { class StageValidationException extends StageException {
......
...@@ -333,9 +333,8 @@ class Stage { ...@@ -333,9 +333,8 @@ class Stage {
* The event object. * The event object.
* *
* @throws \Drupal\package_manager\Exception\StageValidationException * @throws \Drupal\package_manager\Exception\StageValidationException
* If the event collects any validation errors, or a subscriber throws a * If the event collects any validation errors.
* StageValidationException directly. * @throws \Drupal\package_manager\Exception\StageException
* @throws \RuntimeException
* If any other sort of error occurs. * If any other sort of error occurs.
*/ */
protected function dispatch(StageEvent $event): void { protected function dispatch(StageEvent $event): void {
...@@ -344,25 +343,20 @@ class Stage { ...@@ -344,25 +343,20 @@ class Stage {
$results = $event->getResults(); $results = $event->getResults();
if ($results) { if ($results) {
throw new StageValidationException($results); $error = new StageValidationException($results);
} }
} }
catch (\Throwable $error) { catch (\Throwable $error) {
// @todo Simplify exception handling in https://www.drupal.org/i/3258056. $error = new StageException($error->getMessage(), $error->getCode(), $error);
// If we are not going to be able to create the staging area, mark it as }
// available.
if (isset($error)) {
// If we won't be able to create the staging area, mark it as available.
// @see ::create() // @see ::create()
if ($event instanceof PreCreateEvent) { if ($event instanceof PreCreateEvent) {
$this->markAsAvailable(); $this->markAsAvailable();
} }
throw $error;
// Wrap the exception to preserve the backtrace, and re-throw it.
if ($error instanceof StageValidationException) {
throw new StageValidationException($error->getResults(), $error->getMessage(), $error->getCode(), $error);
}
else {
throw new \RuntimeException($error->getMessage(), $error->getCode(), $error);
}
} }
} }
......
...@@ -6,6 +6,12 @@ use Drupal\package_manager\Exception\StageValidationException; ...@@ -6,6 +6,12 @@ use Drupal\package_manager\Exception\StageValidationException;
/** /**
* Defines a custom exception for a failure during an update. * Defines a custom exception for a failure during an update.
*
* Should not be thrown by external code. This is only used to identify
* validation errors that occurred during a staging operation performed by
* Automatic Updates.
*
* @see \Drupal\automatic_updates\Updater::dispatch()
*/ */
class UpdateException extends StageValidationException { class UpdateException extends StageValidationException {
} }
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
namespace Drupal\Tests\automatic_updates\Functional; namespace Drupal\Tests\automatic_updates\Functional;
use Drupal\automatic_updates\Event\ReadinessCheckEvent; use Drupal\automatic_updates\Event\ReadinessCheckEvent;
use Drupal\automatic_updates\Exception\UpdateException;
use Drupal\package_manager\Event\PreCreateEvent; use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\ValidationResult; use Drupal\package_manager\ValidationResult;
use Drupal\automatic_updates_test\ReadinessChecker\TestChecker1; use Drupal\automatic_updates_test\ReadinessChecker\TestChecker1;
...@@ -176,29 +175,29 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase { ...@@ -176,29 +175,29 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
$assert_session->pageTextNotContains((string) $message); $assert_session->pageTextNotContains((string) $message);
TestChecker1::setTestResult(NULL, ReadinessCheckEvent::class); TestChecker1::setTestResult(NULL, ReadinessCheckEvent::class);
// Repackage the validation error as an exception, so we can test what // Make the validator throw an exception during pre-create.
// happens if a validator throws once the update has started. $error = new \Exception('The update exploded.');
$error = new UpdateException($expected_results, 'The update exploded.');
TestChecker1::setException($error, PreCreateEvent::class); TestChecker1::setException($error, PreCreateEvent::class);
$session->reload(); $session->reload();
$assert_session->pageTextNotContains(static::$errorsExplanation); $assert_session->pageTextNotContains(static::$errorsExplanation);
$assert_session->pageTextNotContains(static::$warningsExplanation); $assert_session->pageTextNotContains(static::$warningsExplanation);
$page->pressButton('Update'); $page->pressButton('Update');
$this->checkForMetaRefresh(); $this->checkForMetaRefresh();
// If a validator flags an error, but doesn't throw, the update should still
// be halted.
$this->assertUpdateStagedTimes(0); $this->assertUpdateStagedTimes(0);
$assert_session->pageTextContainsOnce('An error has occurred.'); $assert_session->pageTextContainsOnce('An error has occurred.');
$page->clickLink('the error page'); $page->clickLink('the error page');
$assert_session->pageTextContainsOnce((string) $expected_results[0]->getMessages()[0]); // We should see the exception message, but not the validation result's
// Since there's only one error message, we shouldn't see the summary... // messages or summary, because exceptions thrown directly by event
// subscribers are wrapped in simple exceptions and re-thrown.
$assert_session->pageTextContainsOnce($error->getMessage());
$assert_session->pageTextNotContains((string) $expected_results[0]->getMessages()[0]);
$assert_session->pageTextNotContains($expected_results[0]->getSummary()); $assert_session->pageTextNotContains($expected_results[0]->getSummary());
// ...but we should see the exception message. // Since the error occurred during pre-create, there should be no existing
$assert_session->pageTextContainsOnce('The update exploded.'); // update to delete.
// If the error is thrown in PreCreateEvent the update stage will not have
// been created.
$assert_session->buttonNotExists('Delete existing update'); $assert_session->buttonNotExists('Delete existing update');
// If a validator flags an error, but doesn't throw, the update should still
// be halted.
TestChecker1::setTestResult($expected_results, PreCreateEvent::class); TestChecker1::setTestResult($expected_results, PreCreateEvent::class);
$page->pressButton('Update'); $page->pressButton('Update');
$this->checkForMetaRefresh(); $this->checkForMetaRefresh();
......
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