Skip to content

Commit

Permalink
Fix sebastianbergmann#1351: Isolated TestResult contains serialized t…
Browse files Browse the repository at this point in the history
…est class upon failure.
  • Loading branch information
sun committed Jul 25, 2014
1 parent bf39e30 commit 4e4a080
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 64 deletions.
183 changes: 183 additions & 0 deletions src/Framework/FlattenedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<?php
/**
* PHPUnit
*
* Copyright (c) 2001-2014, Sebastian Bergmann <sebastian@phpunit.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @package PHPUnit
* @subpackage Framework
* @author Sebastian Bergmann <sebastian@phpunit.de>
* @copyright 2001-2014 Sebastian Bergmann <sebastian@phpunit.de>
* @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
* @link http://www.phpunit.de/
* @since File available since Release 3.0.0
*/

/**
* String representation of an Exception.
*
* @see PHPUnit_Framework_TestFailure
*
* @package PHPUnit
* @subpackage Framework
* @author Daniel F. Kudwien <sun@unleashedmind.com>
* @copyright 2001-2014 Sebastian Bergmann <sebastian@phpunit.de>
* @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
* @link http://www.phpunit.de/
* @since Class available since Release 4.1.5
*/
class PHPUnit_Framework_FlattenedException
{
/**
* @var string
*/
protected $message;

/**
* @var PHPUnit_Framework_FlattenedException|null
*/
protected $previous;

/**
* @var string
*/
protected $asString;

/**
* @var string
*/
protected $trace;

/**
* @var boolean
*/
protected $isFailure;

/**
* Constructs a FlattenedException.
*
* @param Exception $e
*/
public function __construct(Exception $e)
{
$this->message = $e->getMessage();
if ($e->getPrevious()) {
$this->previous = new self($e->getPrevious());
}
$this->asString = self::toString($e);
$this->trace = PHPUnit_Util_Filter::getFilteredStacktrace($e);
$this->isFailure = $e instanceof PHPUnit_Framework_AssertionFailedError;
}

/**
* @return string
*/
public function getMessage()
{
return $this->message;
}

/**
* @return PHPUnit_Framework_FlattenedException
*/
public function getPrevious()
{
return $this->previous;
}

/**
* @return string
*/
public function getTraceAsString()
{
return $this->trace;
}

/**
* @return string
*/
public function asString()
{
return $this->asString;
}

/**
* @return string
*/
public function __toString()
{
$string = $this->asString;
if (!empty($this->trace)) {
$string .= "\n" . $this->trace;
}
return $string;
}

/**
* Returns a description for an exception.
*
* @param Exception $e
* @return string
* @since Method available since Release 4.1.5
*/
public static function toString(Exception $e)
{
if ($e instanceof PHPUnit_Framework_SelfDescribing) {
$buffer = $e->toString();

if ($e instanceof PHPUnit_Framework_ExpectationFailedException && $e->getComparisonFailure()) {
$buffer = $buffer . $e->getComparisonFailure()->getDiff();
}

if (!empty($buffer)) {
$buffer = trim($buffer) . "\n";
}
} elseif ($e instanceof PHPUnit_Framework_Error) {
$buffer = $e->getMessage() . "\n";
} else {
$buffer = get_class($e) . ': ' . $e->getMessage() . "\n";
}

return $buffer;
}

/**
* Returns whether a PHPUnit_Framework_AssertionFailedError was thrown.
*
* @return boolean
*/
public function isFailure()
{
return $this->isFailure;
}
}
57 changes: 24 additions & 33 deletions src/Framework/TestFailure.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,31 @@
class PHPUnit_Framework_TestFailure
{
/**
* @var PHPUnit_Framework_Test
* @var string
*/
protected $failedTest;
private $label;

/**
* @var Exception
* @var PHPUnit_Framework_FlattenedException
*/
protected $thrownException;

/**
* Constructs a TestFailure with the given test and exception.
*
* @param PHPUnit_Framework_Test $failedTest
* @param Exception $thrownException
* @param Exception|PHPUnit_Framework_FlattenedException $thrownException
*/
public function __construct(PHPUnit_Framework_Test $failedTest, Exception $thrownException)
public function __construct(PHPUnit_Framework_Test $failedTest, $thrownException)
{
$this->failedTest = $failedTest;
$this->thrownException = $thrownException;
$this->label = $failedTest->toString();

if ($thrownException instanceof PHPUnit_Framework_FlattenedException) {
$this->thrownException = $thrownException;
}
else {
$this->thrownException = new PHPUnit_Framework_FlattenedException($thrownException);
}
}

/**
Expand All @@ -87,8 +93,7 @@ public function toString()
{
return sprintf(
'%s: %s',

$this->failedTest->toString(),
$this->label,
$this->thrownException->getMessage()
);
}
Expand All @@ -101,7 +106,7 @@ public function toString()
*/
public function getExceptionAsString()
{
return self::exceptionToString($this->thrownException);
return $this->thrownException->asString();
}

/**
Expand All @@ -110,42 +115,28 @@ public function getExceptionAsString()
* @param Exception $e
* @return string
* @since Method available since Release 3.2.0
* @deprecated 4.1.5
* @see PHPUnit_Framework_FlattenedException
*/
public static function exceptionToString(Exception $e)
{
if ($e instanceof PHPUnit_Framework_SelfDescribing) {
$buffer = $e->toString();

if ($e instanceof PHPUnit_Framework_ExpectationFailedException && $e->getComparisonFailure()) {
$buffer = $buffer . $e->getComparisonFailure()->getDiff();
}

if (!empty($buffer)) {
$buffer = trim($buffer) . "\n";
}
} elseif ($e instanceof PHPUnit_Framework_Error) {
$buffer = $e->getMessage() . "\n";
} else {
$buffer = get_class($e) . ': ' . $e->getMessage() . "\n";
}

return $buffer;
return PHPUnit_Framework_FlattenedException::toString($e);
}

/**
* Gets the failed test.
* Returns the label of the failing test (including data set, if any).
*
* @return PHPUnit_Framework_Test
* @return string
*/
public function failedTest()
public function getTestLabel()
{
return $this->failedTest;
return $this->label;
}

/**
* Gets the thrown exception.
*
* @return Exception
* @return PHPUnit_Framework_FlattenedException
*/
public function thrownException()
{
Expand All @@ -170,6 +161,6 @@ public function exceptionMessage()
*/
public function isFailure()
{
return ($this->thrownException() instanceof PHPUnit_Framework_AssertionFailedError);
return $this->thrownException->isFailure();
}
}
26 changes: 24 additions & 2 deletions src/Framework/TestResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,10 +284,10 @@ public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
* The passed in exception caused the failure.
*
* @param PHPUnit_Framework_Test $test
* @param PHPUnit_Framework_AssertionFailedError $e
* @param PHPUnit_Framework_AssertionFailedError|PHPUnit_Framework_FlattenedException $e
* @param float $time
*/
public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
public function addFailure(PHPUnit_Framework_Test $test, $e, $time)
{
if ($e instanceof PHPUnit_Framework_RiskyTest) {
$this->risky[] = new PHPUnit_Framework_TestFailure(
Expand Down Expand Up @@ -316,6 +316,13 @@ public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_Asser
if ($this->stopOnSkipped) {
$this->stop();
}
// } elseif ($e instanceof PHPUnit_Framework_TestFailure) {
// $this->failures[] = $e;
// $notifyMethod = 'addFailure';
//
// if ($this->stopOnFailure) {
// $this->stop();
// }
} else {
$this->failures[] = new PHPUnit_Framework_TestFailure($test, $e);
$notifyMethod = 'addFailure';
Expand All @@ -325,6 +332,21 @@ public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_Asser
}
}

// @todo Excessive test result processing recursion:
// PHPUnit_Util_PHP::processChildResult() === TestFailure
// -> PHPUnit_Util_PHP::getException()
// -> FlattenedException
// self::addFailure(, FlattenedException)
// ^^ -> new TestFailure
// -> FlattenedException
// PHPUnit_Framework_FlattenedException <---|
//
// 1. -> TestResult::add(TestResult $result)
// 2. PHPUnit_Util_Printer expects AssertionFailedError... :-|
if ($e instanceof PHPUnit_Framework_FlattenedException) {
$e = new PHPUnit_Framework_AssertionFailedError($e->getMessage());
}

foreach ($this->listeners as $listener) {
$listener->$notifyMethod($test, $e, $time);
}
Expand Down
Loading

0 comments on commit 4e4a080

Please sign in to comment.