391 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			391 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  *  Global state for SimpleTest and kicker script in future versions.
 | |
|  *  @package    SimpleTest
 | |
|  *  @subpackage UnitTester
 | |
|  *  @version    $Id: simpletest.php 2011 2011-04-29 08:22:48Z pp11 $
 | |
|  */
 | |
| 
 | |
| /**#@+
 | |
|  * include SimpleTest files
 | |
|  */
 | |
| require_once(dirname(__FILE__) . '/reflection_php5.php');
 | |
| require_once(dirname(__FILE__) . '/default_reporter.php');
 | |
| require_once(dirname(__FILE__) . '/compatibility.php');
 | |
| /**#@-*/
 | |
| 
 | |
| /**
 | |
|  *    Registry and test context. Includes a few
 | |
|  *    global options that I'm slowly getting rid of.
 | |
|  *    @package  SimpleTest
 | |
|  *    @subpackage   UnitTester
 | |
|  */
 | |
| class SimpleTest {
 | |
| 
 | |
|     /**
 | |
|      *    Reads the SimpleTest version from the release file.
 | |
|      *    @return string        Version string.
 | |
|      */
 | |
|     static function getVersion() {
 | |
|         $content = file(dirname(__FILE__) . '/VERSION');
 | |
|         return trim($content[0]);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Sets the name of a test case to ignore, usually
 | |
|      *    because the class is an abstract case that should
 | |
|      *    @param string $class        Add a class to ignore.
 | |
|      */
 | |
|     static function ignore($class) {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         $registry['IgnoreList'][strtolower($class)] = true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Scans the now complete ignore list, and adds
 | |
|      *    all parent classes to the list. If a class
 | |
|      *    is not a runnable test case, then it's parents
 | |
|      *    wouldn't be either. This is syntactic sugar
 | |
|      *    to cut down on ommissions of ignore()'s or
 | |
|      *    missing abstract declarations. This cannot
 | |
|      *    be done whilst loading classes wiithout forcing
 | |
|      *    a particular order on the class declarations and
 | |
|      *    the ignore() calls. It's just nice to have the ignore()
 | |
|      *    calls at the top of the file before the actual declarations.
 | |
|      *    @param array $classes     Class names of interest.
 | |
|      */
 | |
|     static function ignoreParentsIfIgnored($classes) {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         foreach ($classes as $class) {
 | |
|             if (SimpleTest::isIgnored($class)) {
 | |
|                 $reflection = new SimpleReflection($class);
 | |
|                 if ($parent = $reflection->getParent()) {
 | |
|                     SimpleTest::ignore($parent);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *   Puts the object to the global pool of 'preferred' objects
 | |
|      *   which can be retrieved with SimpleTest :: preferred() method.
 | |
|      *   Instances of the same class are overwritten.
 | |
|      *   @param object $object      Preferred object
 | |
|      *   @see preferred()
 | |
|      */
 | |
|     static function prefer($object) {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         $registry['Preferred'][] = $object;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *   Retrieves 'preferred' objects from global pool. Class filter
 | |
|      *   can be applied in order to retrieve the object of the specific
 | |
|      *   class
 | |
|      *   @param array|string $classes       Allowed classes or interfaces.
 | |
|      *   @return array|object|null
 | |
|      *   @see prefer()
 | |
|      */
 | |
|     static function preferred($classes) {
 | |
|         if (! is_array($classes)) {
 | |
|             $classes = array($classes);
 | |
|         }
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         for ($i = count($registry['Preferred']) - 1; $i >= 0; $i--) {
 | |
|             foreach ($classes as $class) {
 | |
|                 if (SimpleTestCompatibility::isA($registry['Preferred'][$i], $class)) {
 | |
|                     return $registry['Preferred'][$i];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Test to see if a test case is in the ignore
 | |
|      *    list. Quite obviously the ignore list should
 | |
|      *    be a separate object and will be one day.
 | |
|      *    This method is internal to SimpleTest. Don't
 | |
|      *    use it.
 | |
|      *    @param string $class        Class name to test.
 | |
|      *    @return boolean             True if should not be run.
 | |
|      */
 | |
|     static function isIgnored($class) {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         return isset($registry['IgnoreList'][strtolower($class)]);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Sets proxy to use on all requests for when
 | |
|      *    testing from behind a firewall. Set host
 | |
|      *    to false to disable. This will take effect
 | |
|      *    if there are no other proxy settings.
 | |
|      *    @param string $proxy     Proxy host as URL.
 | |
|      *    @param string $username  Proxy username for authentication.
 | |
|      *    @param string $password  Proxy password for authentication.
 | |
|      */
 | |
|     static function useProxy($proxy, $username = false, $password = false) {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         $registry['DefaultProxy'] = $proxy;
 | |
|         $registry['DefaultProxyUsername'] = $username;
 | |
|         $registry['DefaultProxyPassword'] = $password;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for default proxy host.
 | |
|      *    @return string       Proxy URL.
 | |
|      */
 | |
|     static function getDefaultProxy() {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         return $registry['DefaultProxy'];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for default proxy username.
 | |
|      *    @return string    Proxy username for authentication.
 | |
|      */
 | |
|     static function getDefaultProxyUsername() {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         return $registry['DefaultProxyUsername'];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for default proxy password.
 | |
|      *    @return string    Proxy password for authentication.
 | |
|      */
 | |
|     static function getDefaultProxyPassword() {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         return $registry['DefaultProxyPassword'];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for default HTML parsers.
 | |
|      *    @return array     List of parsers to try in
 | |
|      *                      order until one responds true
 | |
|      *                      to can().
 | |
|      */
 | |
|     static function getParsers() {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         return $registry['Parsers'];
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Set the list of HTML parsers to attempt to use by default.
 | |
|      *    @param array $parsers    List of parsers to try in
 | |
|      *                             order until one responds true
 | |
|      *                             to can().
 | |
|      */
 | |
|     static function setParsers($parsers) {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         $registry['Parsers'] = $parsers;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for global registry of options.
 | |
|      *    @return hash           All stored values.
 | |
|      */
 | |
|     protected static function &getRegistry() {
 | |
|         static $registry = false;
 | |
|         if (! $registry) {
 | |
|             $registry = SimpleTest::getDefaults();
 | |
|         }
 | |
|         return $registry;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for the context of the current
 | |
|      *    test run.
 | |
|      *    @return SimpleTestContext    Current test run.
 | |
|      */
 | |
|     static function getContext() {
 | |
|         static $context = false;
 | |
|         if (! $context) {
 | |
|             $context = new SimpleTestContext();
 | |
|         }
 | |
|         return $context;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Constant default values.
 | |
|      *    @return hash       All registry defaults.
 | |
|      */
 | |
|     protected static function getDefaults() {
 | |
|         return array(
 | |
|                 'Parsers' => false,
 | |
|                 'MockBaseClass' => 'SimpleMock',
 | |
|                 'IgnoreList' => array(),
 | |
|                 'DefaultProxy' => false,
 | |
|                 'DefaultProxyUsername' => false,
 | |
|                 'DefaultProxyPassword' => false,
 | |
|                 'Preferred' => array(new HtmlReporter(), new TextReporter(), new XmlReporter()));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    @deprecated
 | |
|      */
 | |
|     static function setMockBaseClass($mock_base) {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         $registry['MockBaseClass'] = $mock_base;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    @deprecated
 | |
|      */
 | |
|     static function getMockBaseClass() {
 | |
|         $registry = &SimpleTest::getRegistry();
 | |
|         return $registry['MockBaseClass'];
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  *    Container for all components for a specific
 | |
|  *    test run. Makes things like error queues
 | |
|  *    available to PHP event handlers, and also
 | |
|  *    gets around some nasty reference issues in
 | |
|  *    the mocks.
 | |
|  *    @package  SimpleTest
 | |
|  */
 | |
| class SimpleTestContext {
 | |
|     private $test;
 | |
|     private $reporter;
 | |
|     private $resources;
 | |
| 
 | |
|     /**
 | |
|      *    Clears down the current context.
 | |
|      *    @access public
 | |
|      */
 | |
|     function clear() {
 | |
|         $this->resources = array();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Sets the current test case instance. This
 | |
|      *    global instance can be used by the mock objects
 | |
|      *    to send message to the test cases.
 | |
|      *    @param SimpleTestCase $test        Test case to register.
 | |
|      */
 | |
|     function setTest($test) {
 | |
|         $this->clear();
 | |
|         $this->test = $test;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for currently running test case.
 | |
|      *    @return SimpleTestCase    Current test.
 | |
|      */
 | |
|     function getTest() {
 | |
|         return $this->test;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Sets the current reporter. This
 | |
|      *    global instance can be used by the mock objects
 | |
|      *    to send messages.
 | |
|      *    @param SimpleReporter $reporter     Reporter to register.
 | |
|      */
 | |
|     function setReporter($reporter) {
 | |
|         $this->clear();
 | |
|         $this->reporter = $reporter;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for current reporter.
 | |
|      *    @return SimpleReporter    Current reporter.
 | |
|      */
 | |
|     function getReporter() {
 | |
|         return $this->reporter;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Accessor for the Singleton resource.
 | |
|      *    @return object       Global resource.
 | |
|      */
 | |
|     function get($resource) {
 | |
|         if (! isset($this->resources[$resource])) {
 | |
|             $this->resources[$resource] = new $resource();
 | |
|         }
 | |
|         return $this->resources[$resource];
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  *    Interrogates the stack trace to recover the
 | |
|  *    failure point.
 | |
|  *    @package SimpleTest
 | |
|  *    @subpackage UnitTester
 | |
|  */
 | |
| class SimpleStackTrace {
 | |
|     private $prefixes;
 | |
| 
 | |
|     /**
 | |
|      *    Stashes the list of target prefixes.
 | |
|      *    @param array $prefixes      List of method prefixes
 | |
|      *                                to search for.
 | |
|      */
 | |
|     function __construct($prefixes) {
 | |
|         $this->prefixes = $prefixes;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Extracts the last method name that was not within
 | |
|      *    Simpletest itself. Captures a stack trace if none given.
 | |
|      *    @param array $stack      List of stack frames.
 | |
|      *    @return string           Snippet of test report with line
 | |
|      *                             number and file.
 | |
|      */
 | |
|     function traceMethod($stack = false) {
 | |
|         $stack = $stack ? $stack : $this->captureTrace();
 | |
|         foreach ($stack as $frame) {
 | |
|             if ($this->frameLiesWithinSimpleTestFolder($frame)) {
 | |
|                 continue;
 | |
|             }
 | |
|             if ($this->frameMatchesPrefix($frame)) {
 | |
|                 return ' at [' . $frame['file'] . ' line ' . $frame['line'] . ']';
 | |
|             }
 | |
|         }
 | |
|         return '';
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Test to see if error is generated by SimpleTest itself.
 | |
|      *    @param array $frame     PHP stack frame.
 | |
|      *    @return boolean         True if a SimpleTest file.
 | |
|      */
 | |
|     protected function frameLiesWithinSimpleTestFolder($frame) {
 | |
|         if (isset($frame['file'])) {
 | |
|             $path = substr(SIMPLE_TEST, 0, -1);
 | |
|             if (strpos($frame['file'], $path) === 0) {
 | |
|                 if (dirname($frame['file']) == $path) {
 | |
|                     return true;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Tries to determine if the method call is an assert, etc.
 | |
|      *    @param array $frame     PHP stack frame.
 | |
|      *    @return boolean         True if matches a target.
 | |
|      */
 | |
|     protected function frameMatchesPrefix($frame) {
 | |
|         foreach ($this->prefixes as $prefix) {
 | |
|             if (strncmp($frame['function'], $prefix, strlen($prefix)) == 0) {
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      *    Grabs a current stack trace.
 | |
|      *    @return array        Fulle trace.
 | |
|      */
 | |
|     protected function captureTrace() {
 | |
|         if (function_exists('debug_backtrace')) {
 | |
|             return array_reverse(debug_backtrace());
 | |
|         }
 | |
|         return array();
 | |
|     }
 | |
| }
 | |
| ?>
 |