Skip to content
Snippets Groups Projects
Commit a623c259 authored by Kunal Sachdev's avatar Kunal Sachdev Committed by Ted Bowman
Browse files

Issue #3259810 by tedbow, kunal.sachdev: Validation errors are not logged on cron update attempts

parent 01845303
No related branches found
No related tags found
No related merge requests found
<?php
namespace Drupal\Tests\package_manager\Traits;
/**
* Common functions for testing using the package_manager_bypass module.
*/
trait PackageManagerBypassTestTrait {
/**
* Asserts the number of times an update was staged.
*
* @param int $attempted_times
* The expected number of times an update was staged.
*/
private function assertUpdateStagedTimes(int $attempted_times): void {
/** @var \Drupal\package_manager_bypass\InvocationRecorderBase $beginner */
$beginner = $this->container->get('package_manager.beginner');
$this->assertCount($attempted_times, $beginner->getInvocationArguments());
/** @var \Drupal\package_manager_bypass\InvocationRecorderBase $stager */
$stager = $this->container->get('package_manager.stager');
// If an update was attempted, then there will be two calls to the stager:
// one to change the constraints in composer.json, and another to actually
// update the installed dependencies.
$this->assertCount($attempted_times * 2, $stager->getInvocationArguments());
/** @var \Drupal\package_manager_bypass\InvocationRecorderBase $committer */
$committer = $this->container->get('package_manager.committer');
$this->assertEmpty($committer->getInvocationArguments());
}
}
...@@ -4,6 +4,7 @@ namespace Drupal\automatic_updates; ...@@ -4,6 +4,7 @@ namespace Drupal\automatic_updates;
use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\package_manager\Exception\StageValidationException;
/** /**
* Defines a service that updates via cron. * Defines a service that updates via cron.
...@@ -114,6 +115,10 @@ class CronUpdater extends Updater { ...@@ -114,6 +115,10 @@ class CronUpdater extends Updater {
$this->apply(); $this->apply();
$this->destroy(); $this->destroy();
} }
catch (StageValidationException $e) {
$this->logger->error($this->getLogMessageForValidationException($e));
return;
}
catch (\Throwable $e) { catch (\Throwable $e) {
$this->logger->error($e->getMessage()); $this->logger->error($e->getMessage());
return; return;
...@@ -128,4 +133,31 @@ class CronUpdater extends Updater { ...@@ -128,4 +133,31 @@ class CronUpdater extends Updater {
); );
} }
/**
* Generates a log message from a stage validation exception.
*
* @param \Drupal\package_manager\Exception\StageValidationException $exception
* The validation exception.
*
* @return string
* The formatted log message, including all the validation results.
*/
protected function getLogMessageForValidationException(StageValidationException $exception): string {
$log_message = '';
foreach ($exception->getResults() as $result) {
$summary = $result->getSummary();
if ($summary) {
$log_message .= "<h3>$summary</h3><ul>";
foreach ($result->getMessages() as $message) {
$log_message .= "<li>$message</li>";
}
$log_message .= "</ul>";
}
else {
$log_message .= ($log_message ? ' ' : '') . $result->getMessages()[0];
}
}
return "<h2>{$exception->getMessage()}</h2>$log_message";
}
} }
...@@ -6,6 +6,7 @@ use Drupal\automatic_updates\Event\ReadinessCheckEvent; ...@@ -6,6 +6,7 @@ use Drupal\automatic_updates\Event\ReadinessCheckEvent;
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;
use Drupal\Tests\package_manager\Traits\PackageManagerBypassTestTrait;
use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait; use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait;
/** /**
...@@ -16,6 +17,7 @@ use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait; ...@@ -16,6 +17,7 @@ use Drupal\Tests\automatic_updates\Traits\ValidationTestTrait;
class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase { class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
use ValidationTestTrait; use ValidationTestTrait;
use PackageManagerBypassTestTrait;
/** /**
* {@inheritdoc} * {@inheritdoc}
...@@ -268,27 +270,4 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase { ...@@ -268,27 +270,4 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
$assert_session->buttonExists('Continue'); $assert_session->buttonExists('Continue');
} }
/**
* Asserts the number of times an update was staged.
*
* @param int $attempted_times
* The expected number of times an update was staged.
*/
private function assertUpdateStagedTimes(int $attempted_times): void {
/** @var \Drupal\package_manager_bypass\InvocationRecorderBase $beginner */
$beginner = $this->container->get('package_manager.beginner');
$this->assertCount($attempted_times, $beginner->getInvocationArguments());
/** @var \Drupal\package_manager_bypass\InvocationRecorderBase $stager */
$stager = $this->container->get('package_manager.stager');
// If an update was attempted, then there will be two calls to the stager:
// one to change the constraints in composer.json, and another to actually
// update the installed dependencies.
$this->assertCount($attempted_times * 2, $stager->getInvocationArguments());
/** @var \Drupal\package_manager_bypass\InvocationRecorderBase $committer */
$committer = $this->container->get('package_manager.committer');
$this->assertEmpty($committer->getInvocationArguments());
}
} }
...@@ -3,8 +3,14 @@ ...@@ -3,8 +3,14 @@
namespace Drupal\Tests\automatic_updates\Kernel; namespace Drupal\Tests\automatic_updates\Kernel;
use Drupal\automatic_updates\CronUpdater; use Drupal\automatic_updates\CronUpdater;
use Drupal\automatic_updates_test\ReadinessChecker\TestChecker1;
use Drupal\Core\Form\FormState; use Drupal\Core\Form\FormState;
use Drupal\Core\Logger\RfcLogLevel;
use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\ValidationResult;
use Drupal\Tests\package_manager\Traits\PackageManagerBypassTestTrait;
use Drupal\update\UpdateSettingsForm; use Drupal\update\UpdateSettingsForm;
use Psr\Log\Test\TestLogger;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
...@@ -15,6 +21,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; ...@@ -15,6 +21,8 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
*/ */
class CronUpdaterTest extends AutomaticUpdatesKernelTestBase { class CronUpdaterTest extends AutomaticUpdatesKernelTestBase {
use PackageManagerBypassTestTrait;
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -22,6 +30,7 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase { ...@@ -22,6 +30,7 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase {
'automatic_updates', 'automatic_updates',
'package_manager', 'package_manager',
'package_manager_bypass', 'package_manager_bypass',
'automatic_updates_test',
]; ];
/** /**
...@@ -117,4 +126,67 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase { ...@@ -117,4 +126,67 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase {
$this->assertCount($will_update, $this->container->get('package_manager.committer')->getInvocationArguments()); $this->assertCount($will_update, $this->container->get('package_manager.committer')->getInvocationArguments());
} }
/**
* Data provider for testErrors().
*
* @return array[]
* The test cases for testErrors().
*/
public function providerErrors(): array {
$messages = [
'Precreate Event Error',
'Precreate Event Error 2',
];
$summary = 'There were errors in updates';
$result_no_summary = ValidationResult::createError([$messages[0]]);
$result_with_summary = ValidationResult::createError($messages, t($summary));
$result_with_summary_message = "<h3>{$summary}</h3><ul><li>{$messages[0]}</li><li>{$messages[1]}</li></ul>";
return [
'1 result with summary' => [
[$result_with_summary],
$result_with_summary_message,
],
'2 results with summary' => [
[$result_with_summary, $result_with_summary],
"$result_with_summary_message$result_with_summary_message",
],
'1 result without summary' => [
[$result_no_summary],
$messages[0],
],
'2 results without summary' => [
[$result_no_summary, $result_no_summary],
$messages[0] . ' ' . $messages[0],
],
'1 result with summary, 1 result without summary' => [
[$result_with_summary, $result_no_summary],
$result_with_summary_message . ' ' . $messages[0],
],
];
}
/**
* Tests errors during a cron update attempt.
*
* @param \Drupal\package_manager\ValidationResult[] $validation_results
* The expected validation results which should be logged.
* @param string $expected_log_message
* The error message should be logged.
*
* @dataProvider providerErrors
*/
public function testErrors(array $validation_results, string $expected_log_message): void {
TestChecker1::setTestResult($validation_results, PreCreateEvent::class);
$logger = new TestLogger();
$this->container->get('logger.factory')
->get('automatic_updates')
->addLogger($logger);
$this->container->get('cron')->run();
$this->assertUpdateStagedTimes(0);
$this->assertTrue($logger->hasRecord("<h2>Unable to complete the update because of errors.</h2>$expected_log_message", RfcLogLevel::ERROR));
}
} }
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