Skip to content

Commit

Permalink
Fix serialization of ComparisionFailure with PDO in stacktrace.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
DomBlack committed Mar 8, 2018
1 parent 34369da commit 5266136
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/ComparisonFailure.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
}
}
20 changes: 20 additions & 0 deletions tests/ComparisonFailureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}
}
20 changes: 20 additions & 0 deletions tests/_fixture/NonSerializableClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
/*
* This file is part of sebastian/comparator.
*
* (c) Sebastian Bergmann <[email protected]>
*
* 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) {}
}

0 comments on commit 5266136

Please sign in to comment.