From 5266136b3ad3d294a6c9c99874ff336d58e44ebe Mon Sep 17 00:00:00 2001 From: Dominic Black Date: Thu, 8 Mar 2018 12:19:42 +0000 Subject: [PATCH] Fix serialization of ComparisionFailure with PDO in stacktrace. This fix implements a custom serialize/deserialize method on the ComparisionFailure class, which means it loses the stack trace during serialization. This allows PHPUnit to run in process isolation mode when the stack trace may contain references to non-serializable objects such as the PDO. --- src/ComparisonFailure.php | 24 +++++++++++++++++++++++- tests/ComparisonFailureTest.php | 20 ++++++++++++++++++++ tests/_fixture/NonSerializableClass.php | 20 ++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/_fixture/NonSerializableClass.php diff --git a/src/ComparisonFailure.php b/src/ComparisonFailure.php index 6973d475..4f8d7093 100644 --- a/src/ComparisonFailure.php +++ b/src/ComparisonFailure.php @@ -16,7 +16,7 @@ /** * Thrown when an assertion for string equality failed. */ -class ComparisonFailure extends \RuntimeException +class ComparisonFailure extends \RuntimeException implements \Serializable { /** * Expected value of the retrieval which does not match $actual. @@ -132,4 +132,26 @@ public function toString() { return $this->message . $this->getDiff(); } + + /** + * Serialises all parts of the comparison failure, apart from the stacktrace which might contain references to + * objects which cannot be serialised. + * + * @return string + */ + public function serialize() + { + return serialize(array( + $this->expected, $this->actual, $this->expectedAsString, $this->actualAsString, + $this->identical, $this->message, $this->file, $this->line + )); + } + + public function unserialize($serialized) + { + list( + $this->expected, $this->actual, $this->expectedAsString, $this->actualAsString, + $this->identical, $this->message, $this->file, $this->line + ) = unserialize($serialized); + } } diff --git a/tests/ComparisonFailureTest.php b/tests/ComparisonFailureTest.php index 4198054b..66bcf1dd 100644 --- a/tests/ComparisonFailureTest.php +++ b/tests/ComparisonFailureTest.php @@ -55,4 +55,24 @@ public function testDiffNotPossible() $this->assertSame('', $failure->getDiff()); $this->assertSame('test', $failure->toString()); } + + public function testSerializesWithoutStackTrace() + { + $instance = new NonSerializableClass; + + $failure = $this->functionWithNonSerializableParam($instance); + + $serialised = serialize($failure); + $deserialised = unserialize($serialised); + + $this->assertSame($failure->getActual(), $deserialised->getActual()); + $this->assertSame($failure->getExpected(), $deserialised->getExpected()); + $this->assertSame($failure->getActualAsString(), $deserialised->getActualAsString()); + $this->assertSame($failure->getExpectedAsString(), $deserialised->getExpectedAsString()); + $this->assertSame($failure->toString(), $deserialised->toString()); + } + + private function functionWithNonSerializableParam(NonSerializableClass $instance) { + return new ComparisonFailure('a', 'b', 'a', 'b', false, 'test'); + } } diff --git a/tests/_fixture/NonSerializableClass.php b/tests/_fixture/NonSerializableClass.php new file mode 100644 index 00000000..6d91c75c --- /dev/null +++ b/tests/_fixture/NonSerializableClass.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\Comparator; + +class NonSerializableClass implements \Serializable { + public function serialize() + { + throw new \Error('This class cannot be serialized'); + } + + public function unserialize($serialized) {} +}