Skip to content

Commit

Permalink
Prepare error handler to be used in contexts other than test method e…
Browse files Browse the repository at this point in the history
…xecution (for instance data provider method execution for #5775)
  • Loading branch information
sebastianbergmann committed Apr 2, 2024
1 parent 8d485f1 commit 0370b23
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 74 deletions.
2 changes: 1 addition & 1 deletion src/Framework/TestRunner.php
Expand Up @@ -80,7 +80,7 @@ public function run(TestCase $test): void
$skipped = false;

if ($this->shouldErrorHandlerBeUsed($test)) {
ErrorHandler::instance()->enable();
ErrorHandler::instance()->enableForTest();
}

$collectCodeCoverage = CodeCoverage::instance()->isActive() &&
Expand Down
173 changes: 100 additions & 73 deletions src/Runner/ErrorHandler.php
Expand Up @@ -53,6 +53,7 @@ final class ErrorHandler
private static ?self $instance = null;
private ?Baseline $baseline = null;
private bool $enabled = false;
private bool $enabledForTest = false;
private ?int $originalErrorReportingLevel = null;
private readonly Source $source;
private readonly SourceFilter $sourceFilter;
Expand Down Expand Up @@ -92,89 +93,103 @@ public function __invoke(int $errorNumber, string $errorString, string $errorFil
switch ($errorNumber) {
case E_NOTICE:
case E_STRICT:
Event\Facade::emitter()->testTriggeredPhpNotice(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
);
if ($this->enabledForTest) {
Event\Facade::emitter()->testTriggeredPhpNotice(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
);
}

break;

case E_USER_NOTICE:
Event\Facade::emitter()->testTriggeredNotice(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
);
if ($this->enabledForTest) {
Event\Facade::emitter()->testTriggeredNotice(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
);
}

break;

case E_WARNING:
Event\Facade::emitter()->testTriggeredPhpWarning(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
);
if ($this->enabledForTest) {
Event\Facade::emitter()->testTriggeredPhpWarning(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
);
}

break;

case E_USER_WARNING:
Event\Facade::emitter()->testTriggeredWarning(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
);
if ($this->enabledForTest) {
Event\Facade::emitter()->testTriggeredWarning(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
);
}

break;

case E_DEPRECATED:
Event\Facade::emitter()->testTriggeredPhpDeprecation(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
$ignoredByTest,
$this->trigger($test, false),
);
if ($this->enabledForTest) {
Event\Facade::emitter()->testTriggeredPhpDeprecation(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
$ignoredByTest,
$this->trigger($test, false),
);
}

break;

case E_USER_DEPRECATED:
Event\Facade::emitter()->testTriggeredDeprecation(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
$ignoredByTest,
$this->trigger($test, true),
);
if ($this->enabledForTest) {
Event\Facade::emitter()->testTriggeredDeprecation(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
$ignoredByBaseline,
$ignoredByTest,
$this->trigger($test, true),
);
}

break;

case E_USER_ERROR:
Event\Facade::emitter()->testTriggeredError(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
);
if ($this->enabledForTest) {
Event\Facade::emitter()->testTriggeredError(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
);
}

throw new ErrorException('E_USER_ERROR was triggered');

Expand All @@ -185,24 +200,13 @@ public function __invoke(int $errorNumber, string $errorString, string $errorFil
return false;
}

public function enable(): void
public function enableForTest(): void
{
if ($this->enabled) {
return;
}

$oldErrorHandler = set_error_handler($this);

if ($oldErrorHandler !== null) {
restore_error_handler();

if (!$this->enable()) {
return;
}

$this->enabled = true;
$this->originalErrorReportingLevel = error_reporting();

error_reporting($this->originalErrorReportingLevel & self::UNHANDLEABLE_LEVELS);
$this->enabledForTest = true;
}

public function disable(): void
Expand All @@ -216,6 +220,7 @@ public function disable(): void
error_reporting(error_reporting() | $this->originalErrorReportingLevel);

$this->enabled = false;
$this->enabledForTest = false;
$this->originalErrorReportingLevel = null;
}

Expand All @@ -232,6 +237,28 @@ public function useDeprecationTriggers(array $deprecationTriggers): void
$this->deprecationTriggers = $deprecationTriggers;
}

private function enable(): bool
{
if ($this->enabled) {
return false;
}

$oldErrorHandler = set_error_handler($this);

if ($oldErrorHandler !== null) {
restore_error_handler();

return false;
}

$this->enabled = true;
$this->originalErrorReportingLevel = error_reporting();

error_reporting($this->originalErrorReportingLevel & self::UNHANDLEABLE_LEVELS);

return true;
}

/**
* @psalm-param non-empty-string $file
* @psalm-param positive-int $line
Expand Down

0 comments on commit 0370b23

Please sign in to comment.