Skip to content

Commit

Permalink
[Messenger] Fix JSON deserialization of ErrorDetailsStamp and normali…
Browse files Browse the repository at this point in the history
…zation of FlattenException::$statusText
  • Loading branch information
Jean85 authored and fabpot committed Nov 10, 2020
1 parent cb600f9 commit ae14385
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 17 deletions.
2 changes: 1 addition & 1 deletion EventListener/AddErrorDetailsStampListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ final class AddErrorDetailsStampListener implements EventSubscriberInterface
{
public function onMessageFailed(WorkerMessageFailedEvent $event): void
{
$stamp = new ErrorDetailsStamp($event->getThrowable());
$stamp = ErrorDetailsStamp::create($event->getThrowable());
$previousStamp = $event->getEnvelope()->last(ErrorDetailsStamp::class);

// Do not append duplicate information
Expand Down
22 changes: 16 additions & 6 deletions Stamp/ErrorDetailsStamp.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,29 @@ final class ErrorDetailsStamp implements StampInterface
/** @var FlattenException|null */
private $flattenException;

public function __construct(Throwable $throwable)
/**
* @param int|mixed $exceptionCode
*/
public function __construct(string $exceptionClass, $exceptionCode, string $exceptionMessage, FlattenException $flattenException = null)
{
$this->exceptionClass = $exceptionClass;
$this->exceptionCode = $exceptionCode;
$this->exceptionMessage = $exceptionMessage;
$this->flattenException = $flattenException;
}

public static function create(Throwable $throwable): self
{
if ($throwable instanceof HandlerFailedException) {
$throwable = $throwable->getPrevious();
}

$this->exceptionClass = \get_class($throwable);
$this->exceptionCode = $throwable->getCode();
$this->exceptionMessage = $throwable->getMessage();

$flattenException = null;
if (class_exists(FlattenException::class)) {
$this->flattenException = FlattenException::createFromThrowable($throwable);
$flattenException = FlattenException::createFromThrowable($throwable);
}

return new self(\get_class($throwable), $throwable->getCode(), $throwable->getMessage(), $flattenException);
}

public function getExceptionClass(): string
Expand Down
10 changes: 5 additions & 5 deletions Tests/Command/FailedMessagesShowCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function testBasicRun()
{
$sentToFailureStamp = new SentToFailureTransportStamp('async');
$redeliveryStamp = new RedeliveryStamp(0);
$errorStamp = new ErrorDetailsStamp(new \Exception('Things are bad!', 123));
$errorStamp = ErrorDetailsStamp::create(new \Exception('Things are bad!', 123));
$envelope = new Envelope(new \stdClass(), [
new TransportMessageIdStamp(15),
$sentToFailureStamp,
Expand Down Expand Up @@ -69,7 +69,7 @@ public function testMultipleRedeliveryFails()
{
$sentToFailureStamp = new SentToFailureTransportStamp('async');
$redeliveryStamp1 = new RedeliveryStamp(0);
$errorStamp = new ErrorDetailsStamp(new \Exception('Things are bad!', 123));
$errorStamp = ErrorDetailsStamp::create(new \Exception('Things are bad!', 123));
$redeliveryStamp2 = new RedeliveryStamp(0);
$envelope = new Envelope(new \stdClass(), [
new TransportMessageIdStamp(15),
Expand Down Expand Up @@ -154,7 +154,7 @@ public function testListMessages()
{
$sentToFailureStamp = new SentToFailureTransportStamp('async');
$redeliveryStamp = new RedeliveryStamp(0);
$errorStamp = new ErrorDetailsStamp(new \RuntimeException('Things are bad!'));
$errorStamp = ErrorDetailsStamp::create(new \RuntimeException('Things are bad!'));
$envelope = new Envelope(new \stdClass(), [
new TransportMessageIdStamp(15),
$sentToFailureStamp,
Expand Down Expand Up @@ -201,7 +201,7 @@ public function testListMessagesReturnsPaginatedMessages()
new TransportMessageIdStamp(15),
$sentToFailureStamp,
new RedeliveryStamp(0),
new ErrorDetailsStamp(new \RuntimeException('Things are bad!')),
ErrorDetailsStamp::create(new \RuntimeException('Things are bad!')),
]);
$receiver = $this->createMock(ListableReceiverInterface::class);
$receiver->expects($this->once())->method('all')->with()->willReturn([$envelope]);
Expand Down Expand Up @@ -244,7 +244,7 @@ public function testVeryVerboseOutputForSingleMessageContainsExceptionWithTrace(
new TransportMessageIdStamp(15),
new SentToFailureTransportStamp('async'),
new RedeliveryStamp(0),
new ErrorDetailsStamp($exception),
ErrorDetailsStamp::create($exception),
]);
$receiver = $this->createMock(ListableReceiverInterface::class);
$receiver->expects($this->once())->method('find')->with(42)->willReturn($envelope);
Expand Down
6 changes: 3 additions & 3 deletions Tests/EventListener/AddErrorDetailsStampListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function testExceptionDetailsAreAdded(): void
$envelope = new Envelope(new \stdClass());
$exception = new \Exception('It failed!');
$event = new WorkerMessageFailedEvent($envelope, 'my_receiver', $exception);
$expectedStamp = new ErrorDetailsStamp($exception);
$expectedStamp = ErrorDetailsStamp::create($exception);

$listener->onMessageFailed($event);

Expand All @@ -29,12 +29,12 @@ public function testWorkerAddsNewErrorDetailsStampOnFailure()
$listener = new AddErrorDetailsStampListener();

$envelope = new Envelope(new \stdClass(), [
new ErrorDetailsStamp(new \InvalidArgumentException('First error!')),
ErrorDetailsStamp::create(new \InvalidArgumentException('First error!')),
]);

$exception = new \Exception('Second error!');
$event = new WorkerMessageFailedEvent($envelope, 'my_receiver', $exception);
$expectedStamp = new ErrorDetailsStamp($exception);
$expectedStamp = ErrorDetailsStamp::create($exception);

$listener->onMessageFailed($event);

Expand Down
29 changes: 27 additions & 2 deletions Tests/Stamp/ErrorDetailsStampTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\HandlerFailedException;
use Symfony\Component\Messenger\Stamp\ErrorDetailsStamp;
use Symfony\Component\Messenger\Transport\Serialization\Normalizer\FlattenExceptionNormalizer;
use Symfony\Component\Messenger\Transport\Serialization\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer as SymfonySerializer;

class ErrorDetailsStampTest extends TestCase
{
Expand All @@ -24,7 +30,7 @@ public function testGetters(): void
$exception = new \Exception('exception message');
$flattenException = FlattenException::createFromThrowable($exception);

$stamp = new ErrorDetailsStamp($exception);
$stamp = ErrorDetailsStamp::create($exception);

$this->assertSame(\Exception::class, $stamp->getExceptionClass());
$this->assertSame('exception message', $stamp->getExceptionMessage());
Expand All @@ -38,11 +44,30 @@ public function testUnwrappingHandlerFailedException(): void
$exception = new HandlerFailedException($envelope, [$wrappedException]);
$flattenException = FlattenException::createFromThrowable($wrappedException);

$stamp = new ErrorDetailsStamp($exception);
$stamp = ErrorDetailsStamp::create($exception);

$this->assertSame(\Exception::class, $stamp->getExceptionClass());
$this->assertSame('I am inside', $stamp->getExceptionMessage());
$this->assertSame(123, $stamp->getExceptionCode());
$this->assertEquals($flattenException, $stamp->getFlattenException());
}

public function testDeserialization(): void
{
$exception = new \Exception('exception message');
$stamp = ErrorDetailsStamp::create($exception);
$serializer = new Serializer(
new SymfonySerializer([
new ArrayDenormalizer(),
new FlattenExceptionNormalizer(),
new ObjectNormalizer(),
], [new JsonEncoder()])
);

$deserializedEnvelope = $serializer->decode($serializer->encode(new Envelope(new \stdClass(), [$stamp])));

$deserializedStamp = $deserializedEnvelope->last(ErrorDetailsStamp::class);
$this->assertInstanceOf(ErrorDetailsStamp::class, $deserializedStamp);
$this->assertEquals($stamp, $deserializedStamp);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public function testNormalize(FlattenException $exception)
$this->assertSame($previous, $normalized['previous']);
$this->assertSame($exception->getTrace(), $normalized['trace']);
$this->assertSame($exception->getTraceAsString(), $normalized['trace_as_string']);
$this->assertSame($exception->getStatusText(), $normalized['status_text']);
}

public function provideFlattenException(): array
Expand Down Expand Up @@ -95,6 +96,7 @@ public function testDenormalizeValidData()
'file' => 'foo.php',
'line' => 123,
'headers' => ['Content-Type' => 'application/json'],
'status_text' => 'Whoops, looks like something went wrong.',
'trace' => [
[
'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123, 'args' => [],
Expand All @@ -108,6 +110,7 @@ public function testDenormalizeValidData()
],
],
'trace_as_string' => '#0 foo.php(123): foo()'.\PHP_EOL.'#1 bar.php(456): bar()',
'status_text' => 'Whoops, looks like something went wrong.',
];
$exception = $this->normalizer->denormalize($normalized, FlattenException::class);

Expand All @@ -121,10 +124,12 @@ public function testDenormalizeValidData()
$this->assertSame($normalized['line'], $exception->getLine());
$this->assertSame($normalized['trace'], $exception->getTrace());
$this->assertSame($normalized['trace_as_string'], $exception->getTraceAsString());
$this->assertSame($normalized['status_text'], $exception->getStatusText());

$this->assertInstanceOf(FlattenException::class, $previous = $exception->getPrevious());
$this->assertSame($normalized['previous']['message'], $previous->getMessage());
$this->assertSame($normalized['previous']['code'], $previous->getCode());
$this->assertSame($normalized['previous']['status_text'], $previous->getStatusText());
}

private function getMessengerContext(): array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function normalize($object, $format = null, array $context = [])
'file' => $object->getFile(),
'line' => $object->getLine(),
'previous' => null === $object->getPrevious() ? null : $this->normalize($object->getPrevious(), $format, $context),
'status_text' => $object->getStatusText(),
'trace' => $object->getTrace(),
'trace_as_string' => $object->getTraceAsString(),
];
Expand Down Expand Up @@ -73,6 +74,7 @@ public function denormalize($data, $type, $format = null, array $context = [])
$object->setClass($data['class']);
$object->setFile($data['file']);
$object->setLine($data['line']);
$object->setStatusText($data['status_text']);
$object->setHeaders((array) $data['headers']);

if (isset($data['previous'])) {
Expand Down

0 comments on commit ae14385

Please sign in to comment.