<?php
// Copyright (c) 2006 Roman Neuhauser
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// $HeadURL: https://svn.sigpipe.cz/r/trunk/testilence/src/tence/main.php $
// $Id: main.php 414 2007-02-20 01:05:56Z roman $
require_once 'Testilence/reporter/iface.php';
require_once 'tence/runner.php';
class tence_util_ClassList extends ArrayIterator # {{{
{
function __construct($file) # {{{
{
$loader = new Tence_BasicLoader;
$before = get_declared_classes();
$loader->loadFile($file);
$after = get_declared_classes();
parent::__construct(array_values(array_diff($after, $before)));
} # }}}
} # }}}
class tence_util_ClassFilter # {{{
{
private $names, $rcs = array();
public function __construct(array $names) # {{{
{
$this->names = $names;
foreach ($names as $cls) {
$rc = new ReflectionClass($cls);
array_push($this->rcs, $rc->getName());
}
} # }}}
public function check(ReflectionClass $rc) # {{{
{
return
$this->isOfAnyClass($rc, $this->names)
|| $this->implementsAnyInterface($rc, $this->names)
;
} # }}}
protected function implementsAnyInterface(ReflectionClass $rc, array $ifnames) # {{{
{
return array_intersect(
array_keys($rc->getInterfaces()),
$ifnames
);
} # }}}
protected function isOfAnyClass(ReflectionClass $rc, array $clsnames) # {{{
{
$name = $rc->getName();
foreach ($clsnames as $cls) {
if (0 == strcasecmp($name, $cls) || $rc->isSubclassOf($cls)) {
return true;
}
}
return false;
} # }}}
} # }}}
class tence_util_TestFilter # {{{
{
public function __construct(array $testTypes = array('Tence_RunnableTest')) # {{{
{
$this->cf = new tence_util_ClassFilter($testTypes);
} # }}}
public function isTest(ReflectionClass $rc) # {{{
{
return $this->hasDesiredType($rc)
&& $this->isEasilyInstantiable($rc)
;
} # }}}
protected function hasDesiredType(ReflectionClass $rc) # {{{
{
return $this->cf->check($rc);
} # }}}
protected function isEasilyInstantiable(ReflectionClass $rc) # {{{
{
return $rc->isInstantiable()
&& $this->hasNullaryConstructor($rc)
;
} # }}}
protected function hasNullaryConstructor(ReflectionClass $rc) # {{{
{
$con = $rc->getConstructor();
return is_null($con)
|| 0 == $con->getNumberOfRequiredParameters()
;
} # }}}
} # }}}
class tence_util_TestFilterIterator extends FilterIterator # {{{
{
private $filter;
function __construct(Iterator $it) # {{{
{
$this->filter = new tence_util_TestFilter;
parent::__construct($it);
} # }}}
function accept() # {{{
{
return $this->filter->isTest(
new ReflectionClass($this->getInnerIterator()->current())
);
} # }}}
} # }}}
class tence_TestList # {{{
implements IteratorAggregate
{
function __construct($file) # {{{
{
$this->file = $file;
} # }}}
function getIterator() # {{{
{
return new tence_util_TestFilterIterator(
new tence_util_ClassList($this->file)
);
} # }}}
} # }}}
class tence_TestLister # {{{
{
public function list_(tence_TestList $tests) # {{{
{
$i = 0;
foreach ($tests as $test) {
++$i;
fprintf(STDOUT, "%s\n", $test);
}
return $i;
} # }}}
} # }}}
interface tence_cmdline_exitValueComputer
{
static function compute(Tence_Reporter $tr);
}
class tence_cmdline_xvc1 # {{{
implements tence_cmdline_exitValueComputer
{
const PASS = 0;
const FAILURE = 1;
const EXCEPTION = 2;
const DEFECT = 4;
public static function compute(Tence_Reporter $tr) # {{{
{
$rv = self::PASS;
if ($tr->failures()) {
$rv = self::FAILURE;
}
if ($tr->exceptions()) {
$rv |= self::EXCEPTION;
}
if ($tr->defects()) {
$rv |= self::DEFECT;
}
return $rv;
} # }}}
} # }}}
class tence_cmdline
{
private $config_t, $testlist_t, $lister_t, $runner_t, $loader_t;
private $xvc;
public function __construct( # {{{
$config_t = 'tence_cmdline_Config',
$runner_t = 'Tence_BasicRunner',
$loader_t = 'Tence_BasicLoader',
tence_cmdline_exitValueComputer $xvc = null,
$testlist_t = 'tence_TestList',
tence_TestLister $lister = null
)
{ # {{{
$this->config_t = $config_t;
$this->runner_t = $runner_t;
$this->loader_t = $loader_t;
$this->testlist_t = $testlist_t;
if (is_null($lister)) {
$lister = new tence_TestLister;
}
if (is_null($xvc)) {
$xvc = new tence_cmdline_xvc1;
}
$this->xvc = $xvc;
$this->lister = $lister;
} # }}} # }}}
protected function getConfig($argv = null) # {{{
{
return $this->instantiate($this->config_t, array($argv));
} # }}}
protected function listTests($file) # {{{
{
return $this->lister->list_(
$this->instantiate($this->testlist_t, array($file))
);
} # }}}
private function instantiate($class, array $args = array()) # {{{
{
$rc = new ReflectionClass($class);
$argc = func_num_args();
if (2 == $argc) {
return $rc->newInstanceArgs($args);
}
return $rc->newInstance();
} # }}}
protected function runTests(Tence_RunnerConfig $cfg) # {{{
{
$runner = $this->instantiate(
$this->runner_t,
array($this->instantiate($this->loader_t))
);
$runner->run($cfg);
return $this->xvc->compute($cfg->reporter());
} # }}}
protected function displayVersion($myname) # {{{
{
printf("%s %s\n", $myname, TENCE_VERSIONSTRING);
return 0;
} # }}}
public function main(array $argv) # {{{
{
$myname = basename($argv[0]);
try {
$cfg = $this->getConfig($argv);
if ($cfg->version()) {
return $this->displayVersion($myname);
}
if (null !== ($file = $cfg->testListFor())) {
return $this->listTests($file);
}
return $this->runTests($cfg);
} catch (Exception $e) {
fprintf(STDERR, "%s: %s\n", $myname, $e->getMessage());
return 99;
}
} # }}}
}
# vim: ft=php et ts=4 sts=4 sw=4 fdm=marker cms=\ #\ %s