Query/tests/simpletest/exceptions.php

226 lines
7.0 KiB
PHP

<?php
/**
* base include file for SimpleTest
* @package SimpleTest
* @subpackage UnitTester
* @version $Id: exceptions.php 1882 2009-07-01 14:30:05Z lastcraft $
*/
/**#@+
* Include required SimpleTest files
*/
require_once dirname(__FILE__) . '/invoker.php';
require_once dirname(__FILE__) . '/expectation.php';
/**#@-*/
/**
* Extension that traps exceptions and turns them into
* an error message. PHP5 only.
* @package SimpleTest
* @subpackage UnitTester
*/
class SimpleExceptionTrappingInvoker extends SimpleInvokerDecorator {
/**
* Stores the invoker to be wrapped.
* @param SimpleInvoker $invoker Test method runner.
*/
function __construct($invoker) {
parent::__construct($invoker);
}
/**
* Invokes a test method whilst trapping expected
* exceptions. Any left over unthrown exceptions
* are then reported as failures.
* @param string $method Test method to call.
*/
function invoke($method) {
$trap = SimpleTest::getContext()->get('SimpleExceptionTrap');
$trap->clear();
try {
$has_thrown = false;
parent::invoke($method);
} catch (Exception $exception) {
$has_thrown = true;
if (! $trap->isExpected($this->getTestCase(), $exception)) {
$this->getTestCase()->exception($exception);
}
$trap->clear();
}
if ($message = $trap->getOutstanding()) {
$this->getTestCase()->fail($message);
}
if ($has_thrown) {
try {
parent::getTestCase()->tearDown();
} catch (Exception $e) { }
}
}
}
/**
* Tests exceptions either by type or the exact
* exception. This could be improved to accept
* a pattern expectation to test the error
* message, but that will have to come later.
* @package SimpleTest
* @subpackage UnitTester
*/
class ExceptionExpectation extends SimpleExpectation {
private $expected;
/**
* Sets up the conditions to test against.
* If the expected value is a string, then
* it will act as a test of the class name.
* An exception as the comparison will
* trigger an identical match. Writing this
* down now makes it look doubly dumb. I hope
* come up with a better scheme later.
* @param mixed $expected A class name or an actual
* exception to compare with.
* @param string $message Message to display.
*/
function __construct($expected, $message = '%s') {
$this->expected = $expected;
parent::__construct($message);
}
/**
* Carry out the test.
* @param Exception $compare Value to check.
* @return boolean True if matched.
*/
function test($compare) {
if (is_string($this->expected)) {
return ($compare instanceof $this->expected);
}
if (get_class($compare) != get_class($this->expected)) {
return false;
}
return $compare->getMessage() == $this->expected->getMessage();
}
/**
* Create the message to display describing the test.
* @param Exception $compare Exception to match.
* @return string Final message.
*/
function testMessage($compare) {
if (is_string($this->expected)) {
return "Exception [" . $this->describeException($compare) .
"] should be type [" . $this->expected . "]";
}
return "Exception [" . $this->describeException($compare) .
"] should match [" .
$this->describeException($this->expected) . "]";
}
/**
* Summary of an Exception object.
* @param Exception $compare Exception to describe.
* @return string Text description.
*/
protected function describeException($exception) {
return get_class($exception) . ": " . $exception->getMessage();
}
}
/**
* Stores expected exceptions for when they
* get thrown. Saves the irritating try...catch
* block.
* @package SimpleTest
* @subpackage UnitTester
*/
class SimpleExceptionTrap {
private $expected;
private $ignored;
private $message;
/**
* Clears down the queue ready for action.
*/
function __construct() {
$this->clear();
}
/**
* Sets up an expectation of an exception.
* This has the effect of intercepting an
* exception that matches.
* @param SimpleExpectation $expected Expected exception to match.
* @param string $message Message to display.
* @access public
*/
function expectException($expected = false, $message = '%s') {
$this->expected = $this->coerceToExpectation($expected);
$this->message = $message;
}
/**
* Adds an exception to the ignore list. This is the list
* of exceptions that when thrown do not affect the test.
* @param SimpleExpectation $ignored Exception to skip.
* @access public
*/
function ignoreException($ignored) {
$this->ignored[] = $this->coerceToExpectation($ignored);
}
/**
* Compares the expected exception with any
* in the queue. Issues a pass or fail and
* returns the state of the test.
* @param SimpleTestCase $test Test case to send messages to.
* @param Exception $exception Exception to compare.
* @return boolean False on no match.
*/
function isExpected($test, $exception) {
if ($this->expected) {
return $test->assert($this->expected, $exception, $this->message);
}
foreach ($this->ignored as $ignored) {
if ($ignored->test($exception)) {
return true;
}
}
return false;
}
/**
* Turns an expected exception into a SimpleExpectation object.
* @param mixed $exception Exception, expectation or
* class name of exception.
* @return SimpleExpectation Expectation that will match the
* exception.
*/
private function coerceToExpectation($exception) {
if ($exception === false) {
return new AnythingExpectation();
}
if (! SimpleExpectation::isExpectation($exception)) {
return new ExceptionExpectation($exception);
}
return $exception;
}
/**
* Tests for any left over exception.
* @return string/false The failure message or false if none.
*/
function getOutstanding() {
return sprintf($this->message, 'Failed to trap exception');
}
/**
* Discards the contents of the error queue.
*/
function clear() {
$this->expected = false;
$this->message = false;
$this->ignored = array();
}
}
?>