Skip to content

Commit

Permalink
feat: improves fatal exception handling
Browse files Browse the repository at this point in the history
  • Loading branch information
nunomaduro committed Jan 25, 2024
1 parent 62d8459 commit c5ce355
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 23 deletions.
2 changes: 1 addition & 1 deletion bin/pest
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;

$result = $kernel->handle($originalArguments, $arguments);

$kernel->shutdown();
$kernel->terminate();
} catch (Throwable|Error $e) {
Panic::with($e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
/**
* @internal
*/
interface Shutdownable
interface Terminable
{
/**
* Shutdowns the plugin.
* Terminates the plugin.
*/
public function shutdown(): void;
public function terminate(): void;
}
16 changes: 16 additions & 0 deletions src/Exceptions/FatalException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Pest\Exceptions;

use NunoMaduro\Collision\Contracts\RenderlessTrace;
use RuntimeException;

/**
* @internal
*/
final class FatalException extends RuntimeException implements RenderlessTrace
{
//
}
52 changes: 46 additions & 6 deletions src/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@

namespace Pest;

use NunoMaduro\Collision\Writer;
use Pest\Contracts\Bootstrapper;
use Pest\Exceptions\FatalException;
use Pest\Exceptions\NoDirtyTestsFound;
use Pest\Plugins\Actions\CallsAddsOutput;
use Pest\Plugins\Actions\CallsBoot;
use Pest\Plugins\Actions\CallsHandleArguments;
use Pest\Plugins\Actions\CallsHandleOriginalArguments;
use Pest\Plugins\Actions\CallsShutdown;
use Pest\Plugins\Actions\CallsTerminable;
use Pest\Support\Container;
use Pest\Support\Reflection;
use Pest\Support\View;
use PHPUnit\TestRunner\TestResult\Facade;
use PHPUnit\TextUI\Application;
use PHPUnit\TextUI\Configuration\Registry;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;
use Whoops\Exception\Inspector;

/**
* @internal
Expand Down Expand Up @@ -44,7 +50,7 @@ public function __construct(
private readonly Application $application,
private readonly OutputInterface $output,
) {
register_shutdown_function(fn () => $this->shutdown());
//
}

/**
Expand All @@ -65,6 +71,8 @@ public static function boot(TestSuite $testSuite, InputInterface $input, OutputI
$output,
);

register_shutdown_function(fn () => $kernel->shutdown());

foreach (self::BOOTSTRAPPERS as $bootstrapper) {
$bootstrapper = Container::getInstance()->get($bootstrapper);
assert($bootstrapper instanceof Bootstrapper);
Expand Down Expand Up @@ -110,16 +118,48 @@ public function handle(array $originalArguments, array $arguments): int
}

/**
* Shutdown the Kernel.
* Terminate the Kernel.
*/
public function shutdown(): void
public function terminate(): void
{
$preBufferOutput = Container::getInstance()->get(KernelDump::class);

assert($preBufferOutput instanceof KernelDump);

$preBufferOutput->shutdown();
$preBufferOutput->terminate();

CallsTerminable::execute();
}

CallsShutdown::execute();
/**
* Shutdowns unexpectedly the Kernel.
*/
public function shutdown(): void
{
$this->terminate();

if (is_array($error = error_get_last())) {
$message = $error['message'];
$file = $error['file'];
$line = $error['line'];

try {
$writer = new Writer(null, $this->output);

$throwable = new FatalException($message);

Reflection::setPropertyValue($throwable, 'line', $line);
Reflection::setPropertyValue($throwable, 'file', $file);

$inspector = new Inspector($throwable);

$writer->write($inspector);
} catch (Throwable) { // @phpstan-ignore-line
View::render('components.badge', [
'type' => 'ERROR',
'content' => sprintf('%s in %s:%d', $message, $file, $line),
]);
}
}
}
}
4 changes: 2 additions & 2 deletions src/KernelDump.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ public function disable(): void
}

/**
* Shutdown the output buffering.
* Terminate the output buffering.
*/
public function shutdown(): void
public function terminate(): void
{
$this->disable();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@
/**
* @internal
*/
final class CallsShutdown
final class CallsTerminable
{
/**
* Executes the Plugin action.
*
* Provides an opportunity for any plugins to shutdown.
* Provides an opportunity for any plugins to terminate.
*/
public static function execute(): void
{
$plugins = Loader::getPlugins(Plugins\Shutdownable::class);
$plugins = Loader::getPlugins(Plugins\Terminable::class);

/** @var Plugins\Shutdownable $plugin */
/** @var Plugins\Terminable $plugin */
foreach ($plugins as $plugin) {
$plugin->shutdown();
$plugin->terminate();
}
}
}
6 changes: 3 additions & 3 deletions src/Plugins/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public function handleArguments(array $arguments): array
{
if (! $this->hasArgument('--cache-directory', $arguments)) {

$cliConfiguration = (new CliConfigurationBuilder)->fromParameters([]);
$cliConfiguration = (new CliConfigurationBuilder)->fromParameters([]);
$configurationFile = (new XmlConfigurationFileFinder)->find($cliConfiguration);
$xmlConfiguration = DefaultConfiguration::create();
$xmlConfiguration = DefaultConfiguration::create();

if ($configurationFile) {
if (is_string($configurationFile)) {
$xmlConfiguration = (new Loader)->load($configurationFile);
}

Expand Down
6 changes: 3 additions & 3 deletions src/Plugins/Only.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

namespace Pest\Plugins;

use Pest\Contracts\Plugins\Shutdownable;
use Pest\Contracts\Plugins\Terminable;
use Pest\PendingCalls\TestCall;

/**
* @internal
*/
final class Only implements Shutdownable
final class Only implements Terminable
{
/**
* The temporary folder.
Expand All @@ -26,7 +26,7 @@ final class Only implements Shutdownable
/**
* {@inheritDoc}
*/
public function shutdown(): void
public function terminate(): void
{
$lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock';

Expand Down

0 comments on commit c5ce355

Please sign in to comment.