diff --git a/admin/tool/unittest/coveragefile.php b/admin/tool/unittest/coveragefile.php deleted file mode 100644 index d3c8737a4e8..00000000000 --- a/admin/tool/unittest/coveragefile.php +++ /dev/null @@ -1,71 +0,0 @@ -. - -/** - * This script serves files from dataroot/codecoverage - * - * Syntax: coveragefile.php/path/to/file/file.html - * coveragefile.php?file=path/to/file/file.html - * - * @package tool - * @subpackage unittest - * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -// disable moodle specific debug messages and any errors in output -define('NO_DEBUG_DISPLAY', true); - -require(dirname(__FILE__) . '/../../../config.php'); -require_once($CFG->libdir . '/filelib.php'); - -// basic security, require login + require site config cap -require_login(); -require_capability('tool/unittest:execute', get_context_instance(CONTEXT_SYSTEM)); - -// get file requested -$relativepath = get_file_argument(); - -// basic check, start by slash -if (!$relativepath) { - print_error('invalidargorconf'); -} else if ($relativepath{0} != '/') { - print_error('pathdoesnotstartslash'); -} - -// determine which disk file is going to be served -// and how it's going to be named -$filepath = $CFG->dataroot . '/codecoverage' . $relativepath; -$filename = basename($filepath); - -// extract relative path components -$args = explode('/', ltrim($relativepath, '/')); - -// only serve from some controlled subdirs -$alloweddirs = array('dbtest', 'unittest'); -if (!isset($args[0]) || !in_array($args[0], $alloweddirs)) { - print_error('invalidarguments'); -} - -// only serve some controlled extensions/mimetypes -if (!file_extension_in_typegroup($filepath, array('web_file', 'web_image'), true)) { - print_error('invalidarguments'); -} - -// arrived here, send the file -session_get_instance()->write_close(); // unlock session during fileserving -send_file($filepath, $filename, 0, false); - diff --git a/admin/tool/unittest/db/access.php b/admin/tool/unittest/db/access.php deleted file mode 100644 index 73d07dc1f6f..00000000000 --- a/admin/tool/unittest/db/access.php +++ /dev/null @@ -1,38 +0,0 @@ -. - -/** - * Unitest caps. - * - * @package tool_unittest - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$capabilities = array( - - // Note: do not add managers here, unittests are dangerous and not intended for production sites!!! - - 'tool/unittest:execute' => array( - 'riskbitmask' => RISK_DATALOSS, - 'captype' => 'write', // it writes into database, really! - 'contextlevel' => CONTEXT_SYSTEM, - 'archetypes' => array( - ) - ) -); diff --git a/admin/tool/unittest/db/install.php b/admin/tool/unittest/db/install.php deleted file mode 100644 index 1923960d282..00000000000 --- a/admin/tool/unittest/db/install.php +++ /dev/null @@ -1,31 +0,0 @@ -. - -/** - * Post installation and migration code. - * - * @package tool - * @subpackage unittest - * @copyright 2011 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die; - -function xmldb_tool_unittest_install() { - global $CFG; - -} diff --git a/admin/tool/unittest/ex_reporter.php b/admin/tool/unittest/ex_reporter.php deleted file mode 100644 index 01476d29329..00000000000 --- a/admin/tool/unittest/ex_reporter.php +++ /dev/null @@ -1,297 +0,0 @@ -. - -/** - * A SimpleTest report format for Moodle. - * - * @package tool - * @subpackage unittest - * @copyright © 2006 The Open University - * @author N.D.Freear@open.ac.uk, T.J.Hunt@open.ac.uk - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -if (!defined('MOODLE_INTERNAL')) { - die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page -} - -require_once($CFG->libdir . '/simpletestlib/reporter.php'); - -/** - * Extended in-browser test displayer. HtmlReporter generates - * only failure messages and a pass count. ExHtmlReporter also - * generates pass messages and a time-stamp. - * - * @package SimpleTestEx - */ -class ExHtmlReporter extends HtmlReporter { - - // Options set when the class is created. - var $showpasses; - - // Lang strings. Set in the constructor. - var $strrunonlyfolder; - var $strrunonlyfile; - - var $strseparator; - - var $timestart; - - /** - * Constructor. - * - * @param bool $showpasses Whether this reporter should output anything for passes. - */ - function __construct($showpasses) { - parent::__construct('UTF-8'); - $this->showpasses = $showpasses; - - $this->strrunonlyfolder = $this->get_string('runonlyfolder'); - $this->strrunonlyfile = $this->get_string('runonlyfile'); - $this->strseparator = get_separator(); - } - - /** - * Called when a pass needs to be output. - */ - function paintPass($message) { - //(Implicitly call grandparent, as parent not implemented.) - parent::paintPass($message); - if ($this->showpasses) { - $this->_paintPassFail('pass', $message); - } - } - - /** - * Called when a fail needs to be output. - */ - function paintFail($message) { - // Explicitly call grandparent, not parent::paintFail. - SimpleScorer::paintFail($message); - $this->_paintPassFail('fail', $message, debug_backtrace()); - } - - /** - * Called when a skip needs to be output. - */ - function paintSkip($message) { - // Explicitly call grandparent, not parent::paintFail. - SimpleScorer::paintSkip($message); - $this->_paintPassFail('skip', $message); - } - - /** - * Called when an error (uncaught exception or PHP error) needs to be output. - */ - function paintError($message) { - // Explicitly call grandparent, not parent::paintError. - SimpleScorer::paintError($message); - $this->_paintPassFail('exception', $message); - } - - /** - * Called when a caught exception needs to be output. - */ - function paintException($exception) { - // Explicitly call grandparent, not parent::paintException. - SimpleScorer::paintException($exception); - - if (is_a($exception, 'moodle_exception') && - !get_string_manager()->string_exists($exception->errorcode, $exception->module)) { - $exceptionmessage = 'Exception with missing language string {' . - $exception->errorcode . '} from language file {' . $exception->module . '}'; - - if (!empty($exception->a)) { - if (is_string($exception->a)) { - $data = $exception->a; - } else { - $data = array(); - foreach ((array)$exception->a as $name => $value) { - $data[] = $name . ' => [' . $value . ']'; - } - $data = implode(', ', $data); - } - $exceptionmessage .= ' with data {' . $data . '}'; - } - - } else { - $exceptionmessage = $exception->getMessage(); - } - $message = 'Unexpected exception of type [' . get_class($exception) . - '] with message ['. $exceptionmessage . - '] in ['. $exception->getFile() . - ' line ' . $exception->getLine() . ']'; - - $debuginfo = null; - if (!empty($exception->debuginfo)) { - $debuginfo = $exception->debuginfo; - } - - $this->_paintPassFail('exception', $message, $exception->getTrace(), $debuginfo); - } - - /** - * Private method. Used by printPass/Fail/Skip/Error. - */ - function _paintPassFail($passorfail, $message, $stacktrace = null, $debuginfo = null) { - global $CFG, $OUTPUT; - - echo $OUTPUT->box_start($passorfail . ' generalbox '); - - $url = $this->_htmlEntities($this->_stripParameterFromUrl(qualified_me(), 'path')); - echo '', $this->get_string($passorfail), ': '; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - $file = array_shift($breadcrumb); - $pathbits = preg_split('/\/|\\\\/', substr($file, strlen($CFG->dirroot) + 1)); - $file = array_pop($pathbits); - $folder = ''; - foreach ($pathbits as $pathbit) { - $folder .= $pathbit . '/'; - echo "strrunonlyfolder\">$pathbit/"; - } - echo "strrunonlyfile\">$file"; - echo $this->strseparator, implode($this->strseparator, $breadcrumb); - - echo '
', $this->_htmlEntities($message), "\n\n"; - - if (!empty($debuginfo)) { - print_object('Debug info:'); - print_object($debuginfo); - } - - if ($stacktrace) { - $dotsadded = false; - $interestinglines = 0; - $filteredstacktrace = array(); - foreach ($stacktrace as $frame) { - if (empty($frame['file']) || (strpos($frame['file'], 'simpletestlib') === false && - strpos($frame['file'], 'simpletestcoveragelib') === false - && strpos($frame['file'], 'tool/unittest') === false)) { - $filteredstacktrace[] = $frame; - $interestinglines += 1; - $dotsadded = false; - } else if (!$dotsadded) { - $filteredstacktrace[] = array('line' => '...', 'file' => '...'); - $dotsadded = true; - } - } - if ($interestinglines > 1 || ($passorfail == 'exception' && $interestinglines > 0)) { - echo '
' . format_backtrace($filteredstacktrace) . "
\n\n"; - } - } - - echo $OUTPUT->box_end(); - flush(); - } - - /** - * Called when a notice needs to be output. - */ - function paintNotice($message) { - $this->paintMessage($this->_htmlEntities($message)); - } - - /** - * Paints a simple supplementary message. - * @param string $message Text to display. - */ - function paintMessage($message) { - global $OUTPUT; - if ($this->showpasses) { - echo $OUTPUT->box_start(); - echo '', $this->get_string('notice'), ': '; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - echo implode($this->strseparator, $breadcrumb); - echo $this->strseparator, '
', $message, "\n"; - echo $OUTPUT->box_end(); - flush(); - } - } - - /** - * Output anything that should appear above all the test output. - */ - function paintHeader($test_name) { - $this->timestart = time(); - // We do this the moodle way instead. - } - - /** - * Output anything that should appear below all the test output, e.g. summary information. - */ - function paintFooter($test_name) { - $summarydata = new stdClass; - $summarydata->run = $this->getTestCaseProgress(); - $summarydata->total = $this->getTestCaseCount(); - $summarydata->passes = $this->getPassCount(); - $summarydata->fails = $this->getFailCount(); - $summarydata->exceptions = $this->getExceptionCount(); - - if ($summarydata->fails == 0 && $summarydata->exceptions == 0) { - $status = "passed"; - } else { - $status = "failed"; - } - echo '
'; - echo $this->get_string('summary', $summarydata); - echo '
'; - - echo '
', - $this->get_string('runat', userdate($this->timestart)), ' ', - $this->get_string('timetakes', format_time(time() - $this->timestart)), ' ', - $this->get_string('version', SimpleTest::getVersion()), - '
'; - } - - /** - * Strip a specified parameter from the query string of a URL, if present. - * Adds a separator to the end of the URL, so that a new parameter - * can easily be appended. For example (assuming $param = 'frog'): - * - * http://example.com/index.php -> http://example.com/index.php? - * http://example.com/index.php?frog=1 -> http://example.com/index.php? - * http://example.com/index.php?toad=1 -> http://example.com/index.php?toad=1& - * http://example.com/index.php?frog=1&toad=1 -> http://example.com/index.php?toad=1& - * - * @param string $url the URL to modify. - * @param string $param the parameter to strip from the URL, if present. - * - * @return string The modified URL. - */ - function _stripParameterFromUrl($url, $param) { - $url = preg_replace('/(\?|&)' . $param . '=[^&]*&?/', '$1', $url); - if (strpos($url, '?') === false) { - $url = $url . '?'; - } else { - $url = $url . '&'; - } - return $url; - } - - /** - * Look up a lang string in the appropriate file. - */ - function get_string($identifier, $a = NULL) { - return get_string($identifier, 'tool_unittest', $a); - } - - function _htmlEntities($message) { - // Override subclass message that breaks UTF8. - return s($message); - } -} diff --git a/admin/tool/unittest/ex_simple_test.php b/admin/tool/unittest/ex_simple_test.php deleted file mode 100644 index dd6ee8a4391..00000000000 --- a/admin/tool/unittest/ex_simple_test.php +++ /dev/null @@ -1,231 +0,0 @@ -. - -/** - * A SimpleTest GroupTest that automatically finds all the - * test files in a directory tree according to certain rules. - * - * @package tool - * @subpackage unittest - * @copyright © 2006 The Open University - * @author N.D.Freear@open.ac.uk, T.J.Hunt@open.ac.uk - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -if (!defined('MOODLE_INTERNAL')) { - die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page -} - -require_once($CFG->libdir . '/simpletestlib/test_case.php'); - -/** - * This is a composite test class for finding test cases and - * other RunnableTest classes in a directory tree and combining - * them into a group test. - * @package SimpleTestEx - */ -class AutoGroupTest extends TestSuite { - - var $showsearch; - - function AutoGroupTest($showsearch, $test_name = null) { - $this->TestSuite($test_name); - $this->showsearch = $showsearch; - } - - function run($reporter) { - global $UNITTEST; - - $UNITTEST->running = true; - $return = parent::run($reporter); - unset($UNITTEST->running); - return $return; - } - - function setLabel($test_name) { - //:HACK: there is no GroupTest::setLabel, so access parent::_label. - $this->_label = $test_name; - } - - function addIgnoreFolder($ignorefolder) { - $this->ignorefolders[]=$ignorefolder; - } - - function _recurseFolders($path) { - if ($this->showsearch) { - echo '
  • ' . basename(realpath($path)) . '
  • '; - } - return $s_count; - } - - function findTestFiles($dir) { - if ($this->showsearch) { - echo '

    Searching folder: ' . realpath($dir) . '

    '; - } - return $count; - } - - function addTestFile($file, $internalcall = false) { - - if ($this->showsearch) { - if ($internalcall) { - echo '
  • ' . basename($file) . '
  • '; - } else { - echo '

    Adding test file: ' . realpath($file) . '

    '; - } - // Make sure that syntax errors show up suring the search, otherwise you often - // get blank screens because evil people turn down error_reporting elsewhere. - error_reporting(E_ALL); - } - if (!is_file($file) ){ - parent::add(new BadTest($file, 'Not a file or does not exist')); - } - parent::addFile($file); - } -} - - -/* ======================================================================= */ -// get_class_ex: Insert spaces to prettify the class-name. -function get_class_ex($object) { - return preg_replace('/(.?)([A-Z])/', '${1} ${2}', get_class($object)); -} - - -/** - * A failing test base-class for when a test suite has NOT loaded properly. - * See class, simple_test.php: BadGroupTest. - * @package SimpleTestEx - */ -class BadTest { - - var $label; - var $error; - - function BadTest($label, $error) { - $this->label = $label; - $this->error = $error; - } - - function getLabel() { - return $this->label; - } - - function run(&$reporter) { - $reporter->paintGroupStart(basename(__FILE__), $this->getSize()); - $reporter->paintFail(get_class_ex($this) .' [' . $this->getLabel() . - '] with error [' . $this->error . ']'); - $reporter->paintGroupEnd($this->getLabel()); - return $reporter->getStatus(); - } - - /** - * @return int the number of test cases starting. - */ - function getSize() { - return 0; - } -} - -/** - * An informational notice base-class for when a test suite is being processed. - * See class, simple_test.php: BadGroupTest. - * @package SimpleTestEx - */ -class Notice { - - var $label; - var $status; - - function Notice($label, $error) { - $this->label = $label; - $this->status = $error; - } - - function getLabel() { - return $this->label; - } - - function run(&$reporter) { - $reporter->paintGroupStart(basename(__FILE__), $this->getSize()); - $reporter->paintNotice(get_class_ex($this) . - ' ['. $this->getLabel() .'] with status [' . $this->status . ']'); - $reporter->paintGroupEnd($this->getLabel()); - return $reporter->getStatus(); - } - - function getSize() { - return 0; - } -} - -/** - * A failing folder test for when the test-user specifies an invalid directory - * (run.php?folder=woops). - * @package SimpleTestEx - */ -class BadFolderTest extends BadTest { } - -/** - * A failing auto test for when no unit test files are found. - * @package SimpleTestEx - */ -class BadAutoGroupTest extends BadTest { } - -/** - * Auto group test notices - 1. Search complete. 2. A test file has been found. - * @package SimpleTestEx - */ -class AutoGroupTestNotice extends Notice { } - -class FindFileNotice extends Notice { } diff --git a/admin/tool/unittest/index.php b/admin/tool/unittest/index.php deleted file mode 100644 index db0bbc73580..00000000000 --- a/admin/tool/unittest/index.php +++ /dev/null @@ -1,150 +0,0 @@ -. - -/** - * Run the unit tests. - * - * @package tool - * @subpackage unittest - * @copyright © 2006 The Open University - * @author N.D.Freear@open.ac.uk, T.J.Hunt@open.ac.uk - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -define('NO_OUTPUT_BUFFERING', true); - -require(dirname(__FILE__) . '/../../../config.php'); -require_once($CFG->libdir.'/adminlib.php'); -require_once('simpletestlib.php'); -require_once('simpletestcoveragelib.php'); -require_once('ex_simple_test.php'); -require_once('ex_reporter.php'); - -// page parameters -$path = optional_param('path', null, PARAM_PATH); -$showpasses = optional_param('showpasses', false, PARAM_BOOL); -$codecoverage = optional_param('codecoverage', false, PARAM_BOOL); -$showsearch = optional_param('showsearch', false, PARAM_BOOL); - -admin_externalpage_setup('toolsimpletest', '', array('showpasses'=>$showpasses, 'showsearch'=>$showsearch)); - -raise_memory_limit(MEMORY_EXTRA); - -$unittest = true; - -global $UNITTEST; -$UNITTEST = new stdClass(); - -// This limit is the time allowed per individual test function. Please do not -// increase this value. If you get a PHP time limit when running unit tests, -// find the unit test which is running slowly, and either make it faster, -// split it into multiple tests, or call set_time_limit within that test. -define('TIME_ALLOWED_PER_UNIT_TEST', 60); - -// Print the header. -$strtitle = get_string('unittests', 'tool_unittest'); - -if (!is_null($path)) { - //trim so user doesn't get an error if they include a space on the end of the path (ie by pasting path) - $path = trim($path); - - // Turn off xmlstrictheaders during the unit test run. - $origxmlstrictheaders = !empty($CFG->xmlstrictheaders); - $CFG->xmlstrictheaders = false; - echo $OUTPUT->header(); - $CFG->xmlstrictheaders = $origxmlstrictheaders; - unset($origxmlstrictheaders); - - // Create the group of tests. - $test = new autogroup_test_coverage($showsearch, true, $codecoverage, 'Moodle Unit Tests Code Coverage Report', 'unittest'); - - // OU specific. We use the _nonproject folder for stuff we want to - // keep in CVS, but which is not really relevant. It does no harm - // to leave this here. - $test->addIgnoreFolder($CFG->dirroot . '/_nonproject'); - - // Make the reporter, which is what displays the results. - $reporter = new ExHtmlReporter($showpasses); - - if ($showsearch) { - echo $OUTPUT->heading('Searching for test cases'); - } - flush(); - - // Work out what to test. - if (substr($path, 0, 1) == '/') { - $path = substr($path, 1); - } - $path = $CFG->dirroot . '/' . $path; - if (substr($path, -1) == '/') { - $path = substr($path, 0, -1); - } - $displaypath = substr($path, strlen($CFG->dirroot) + 1); - $ok = true; - if (is_file($path)) { - $test->addTestFile($path); - } else if (is_dir($path)){ - $test->findTestFiles($path); - } else { - echo $OUTPUT->box(get_string('pathdoesnotexist', 'tool_unittest', $path), 'errorbox'); - $ok = false; - } - - // If we have something to test, do it. - if ($ok) { - if ($path == $CFG->dirroot) { - $title = get_string('moodleunittests', 'tool_unittest', get_string('all', 'tool_unittest')); - } else { - $title = get_string('moodleunittests', 'tool_unittest', $displaypath); - } - echo $OUTPUT->heading($title); - $test->run($reporter); - } - - $formheader = get_string('retest', 'tool_unittest'); -} else { - $displaypath = ''; - echo $OUTPUT->header(); - $formheader = get_string('rununittests', 'tool_unittest'); -} -// Print the form for adjusting options. -echo $OUTPUT->box_start('generalbox boxwidthwide boxaligncenter'); -echo $OUTPUT->heading($formheader); -echo '
    '; -echo '
    '; -echo '

    '.html_writer::checkbox('showpasses', 1, $showpasses, get_string('showpasses', 'tool_unittest')).'

    '; -echo '

    '.html_writer::checkbox('showsearch', 1, $showsearch, get_string('showsearch', 'tool_unittest')).'

    '; -if (moodle_coverage_recorder::can_run_codecoverage()) { - echo '

    '.html_writer::checkbox('codecoverage', 1, $codecoverage, get_string('codecoverageanalysis', 'tool_unittest')).'

    '; -} else { - echo '

    '; print_string('codecoveragedisabled', 'tool_unittest'); echo '

    '; -} -echo '

    '; - echo ' '; - echo ''; -echo '

    '; -echo ''; -echo '
    '; -echo '
    '; -echo $OUTPUT->box_end(); - -// Print link to latest code coverage for this report type -if (is_null($path) || !$codecoverage) { - moodle_coverage_reporter::print_link_to_latest('unittest'); -} - -// Footer. -echo $OUTPUT->footer(); diff --git a/admin/tool/unittest/lang/en/tool_unittest.php b/admin/tool/unittest/lang/en/tool_unittest.php deleted file mode 100644 index ce4bb3679c1..00000000000 --- a/admin/tool/unittest/lang/en/tool_unittest.php +++ /dev/null @@ -1,86 +0,0 @@ -. - -/** - * Strings for component 'tool_unittest', language 'en', branch 'MOODLE_22_STABLE' - * - * This file contains strings that were previously located in lang/en/simpletest.php - * - * @package tool - * @subpackage unittest - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -$string['addconfigprefix'] = 'Add prefix to config file'; -$string['all'] = 'ALL'; -$string['codecoverageanalysis'] = 'Perform code coverage analysis.'; -$string['codecoveragecompletereport'] = '(view code coverage complete report)'; -$string['codecoveragedisabled'] = 'Cannot enable code coverage in this server (missing xdebug extension).'; -$string['codecoveragelatestdetails'] = '(on {$a->date}, with {$a->files} files, {$a->percentage} covered)'; -$string['codecoveragelatestreport'] = 'view latest code coverage complete report'; -$string['confignonwritable'] = 'The file config.php is not writeable by the web server. Either change its permissions, or edit it with the appropriate user account, and add the following line before the closing php tag:
    -$CFG->unittestprefix = \'tst_\' // Change tst_ to a prefix of your choice, different from $CFG->prefix'; -$string['coveredlines'] = 'Covered lines'; -$string['coveredpercentage'] = 'Overall code coverage'; -$string['dbtest'] = 'Functional DB tests'; -$string['deletingnoninsertedrecord'] = 'Trying to delete a record that was not inserted by these unit tests (id {$a->id} in table {$a->table}).'; -$string['deletingnoninsertedrecords'] = 'Trying to delete records that were not inserted by these unit tests (from table {$a->table}).'; -$string['droptesttables'] = 'Drop test tables'; -$string['exception'] = 'Exception'; -$string['executablelines'] = 'Executable lines'; -$string['fail'] = 'Fail'; -$string['ignorefile'] = 'Ignore tests in the file'; -$string['ignorethisfile'] = 'Re-run the tests ignoring this test file.'; -$string['installtesttables'] = 'Install test tables'; -$string['moodleunittests'] = 'Moodle unit tests: {$a}'; -$string['notice'] = 'Notice'; -$string['onlytest'] = 'Only run tests in'; -$string['othertestpages'] = 'Other test pages'; -$string['pass'] = 'Pass'; -$string['pathdoesnotexist'] = 'The path \'{$a}\' does not exist.'; -$string['pluginname'] = 'Unit tests'; -$string['prefix'] = 'Unit test tables prefix'; -$string['prefixnotset'] = 'The unit test database table prefix is not configured. Fill and submit this form to add it to config.php.'; -$string['reinstalltesttables'] = 'Reinstall test tables'; -$string['retest'] = 'Re-run the tests'; -$string['retestonlythisfile'] = 'Re-run only this test file.'; -$string['runall'] = 'Run the tests from all the test files.'; -$string['runat'] = 'Run at {$a}.'; -$string['runonlyfile'] = 'Run only the tests in this file'; -$string['runonlyfolder'] = 'Run only the tests in this folder'; -$string['runtests'] = 'Run tests'; -$string['rununittests'] = 'Run the unit tests'; -$string['showpasses'] = 'Show passes as well as fails.'; -$string['showsearch'] = 'Show the search for test files.'; -$string['skip'] = 'Skip'; -$string['stacktrace'] = 'Stack trace:'; -$string['summary'] = '{$a->run}/{$a->total} test cases complete: {$a->passes} passes, {$a->fails} fails and {$a->exceptions} exceptions.'; -$string['tablesnotsetup'] = 'Unit test tables are not yet built. Do you want to build them now?.'; -$string['testdboperations'] = 'Test database operations'; -$string['testtablescsvfileunwritable'] = 'The test tables CSV file is not writable ({$a->filename})'; -$string['testtablesneedupgrade'] = 'The test DB tables need to be upgraded. Do you wish to proceed with the upgrade now?'; -$string['testtablesok'] = 'The test DB tables were successfully installed.'; -$string['thorough'] = 'Run a thorough test (may be slow).'; -$string['timetakes'] = 'Time taken: {$a}.'; -$string['totallines'] = 'Total lines'; -$string['uncaughtexception'] = 'Uncaught exception [{$a->getMessage()}] in [{$a->getFile()}:{$a->getLine()}] TESTS ABORTED.'; -$string['uncoveredlines'] = 'Uncovered lines'; -$string['unittest:execute'] = 'Execute unit tests'; -$string['unittestprefixsetting'] = 'Unit test prefix: {$a->unittestprefix} (Edit config.php to modify this).'; -$string['unittests'] = 'Unit tests'; -$string['updatingnoninsertedrecord'] = 'Trying to update a record that was not inserted by these unit tests (id {$a->id} in table {$a->table}).'; -$string['version'] = 'Using SimpleTest version {$a}.'; diff --git a/admin/tool/unittest/settings.php b/admin/tool/unittest/settings.php deleted file mode 100644 index ee3406a7e87..00000000000 --- a/admin/tool/unittest/settings.php +++ /dev/null @@ -1,29 +0,0 @@ -. - -/** - * Unittest settings - * - * @package tool - * @subpackage unittest - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - - -defined('MOODLE_INTERNAL') || die; - -$ADMIN->add('development', new admin_externalpage('toolsimpletest', get_string('pluginname', 'tool_unittest'), "$CFG->wwwroot/$CFG->admin/tool/unittest/index.php", 'tool/unittest:execute', true)); diff --git a/admin/tool/unittest/simpletestcoveragelib.php b/admin/tool/unittest/simpletestcoveragelib.php deleted file mode 100644 index 306bf2941e7..00000000000 --- a/admin/tool/unittest/simpletestcoveragelib.php +++ /dev/null @@ -1,606 +0,0 @@ -. - -/** - * Extend simpletest to support code coverage analysis - * - * This package contains a collection of classes that, extending standard simpletest - * ones, provide code coverage analysis to already existing tests. Also there are some - * utility functions designed to make the coverage control easier. - * - * @package tool - * @subpackage unittest - * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Includes - */ -require_once($CFG->libdir.'/tablelib.php'); - -require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/unittest/simpletestlib.php'); -require_once($CFG->dirroot . '/' . $CFG->admin . '/tool/unittest/ex_simple_test.php'); - -require_once($CFG->libdir . '/spikephpcoverage/src/CoverageRecorder.php'); -require_once($CFG->libdir . '/spikephpcoverage/src/reporter/HtmlCoverageReporter.php'); - -/** - * AutoGroupTest class extension supporting code coverage - * - * This class extends AutoGroupTest to add the funcitionalities - * necessary to run code coverage, allowing its activation and - * specifying included / excluded files to be analysed - * - * @package moodlecore - * @subpackage simpletestcoverage - * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class autogroup_test_coverage extends AutoGroupTest { - - private $performcoverage; // boolean - private $coveragename; // title of the coverage report - private $coveragedir; // dir, relative to dataroot/coverage where the report will be saved - private $includecoverage; // paths to be analysed by the coverage report - private $excludecoverage; // paths to be excluded from the coverage report - - function __construct($showsearch, $test_name = null, - $performcoverage = false, $coveragename = 'Code Coverage Report', - $coveragedir = 'report') { - parent::__construct($showsearch, $test_name); - $this->performcoverage = $performcoverage; - $this->coveragename = $coveragename; - $this->coveragedir = $coveragedir; - $this->includecoverage = array(); - $this->excludecoverage = array(); - } - - public function addTestFile($file, $internalcall = false) { - global $CFG; - - if ($this->performcoverage) { - $refinfo = moodle_reflect_file($file); - require_once($file); - if ($refinfo->classes) { - foreach ($refinfo->classes as $class) { - $reflection = new ReflectionClass($class); - if ($staticprops = $reflection->getStaticProperties()) { - if (isset($staticprops['includecoverage']) && is_array($staticprops['includecoverage'])) { - foreach ($staticprops['includecoverage'] as $toinclude) { - $this->add_coverage_include_path($toinclude); - } - } - if (isset($staticprops['excludecoverage']) && is_array($staticprops['excludecoverage'])) { - foreach ($staticprops['excludecoverage'] as $toexclude) { - $this->add_coverage_exclude_path($toexclude); - } - } - } - } - // Automatically add the test dir itself, so nothing will be covered there - $this->add_coverage_exclude_path(dirname($file)); - } - } - parent::addTestFile($file, $internalcall); - } - - public function add_coverage_include_path($path) { - global $CFG; - - $path = $CFG->dirroot . '/' . $path; // Convert to full path - if (!in_array($path, $this->includecoverage)) { - array_push($this->includecoverage, $path); - } - } - - public function add_coverage_exclude_path($path) { - global $CFG; - - $path = $CFG->dirroot . '/' . $path; // Convert to full path - if (!in_array($path, $this->excludecoverage)) { - array_push($this->excludecoverage, $path); - } - } - - /** - * Run the autogroup_test_coverage using one internally defined code coverage reporter - * automatically generating the coverage report. Only supports one instrumentation - * to be executed and reported. - */ - public function run($simpletestreporter) { - global $CFG; - - if (moodle_coverage_recorder::can_run_codecoverage() && $this->performcoverage) { - // Testing with coverage - $covreporter = new moodle_coverage_reporter($this->coveragename, $this->coveragedir); - $covrecorder = new moodle_coverage_recorder($covreporter); - $covrecorder->setIncludePaths($this->includecoverage); - $covrecorder->setExcludePaths($this->excludecoverage); - $covrecorder->start_instrumentation(); - parent::run($simpletestreporter); - $covrecorder->stop_instrumentation(); - set_time_limit(60*10); // it may take a long time to generate the report - $covrecorder->generate_report(); - moodle_coverage_reporter::print_summary_info(basename($this->coveragedir)); - } else { - // Testing without coverage - parent::run($simpletestreporter); - } - } - - /** - * Run the autogroup_test_coverage tests using one externally defined code coverage reporter - * allowing further process of coverage data once tests are over. Supports multiple - * instrumentations (code coverage gathering sessions) to be executed. - */ - public function run_with_external_coverage($simpletestreporter, $covrecorder) { - - if (moodle_coverage_recorder::can_run_codecoverage() && $this->performcoverage) { - $covrecorder->setIncludePaths($this->includecoverage); - $covrecorder->setExcludePaths($this->excludecoverage); - $covrecorder->start_instrumentation(); - parent::run($simpletestreporter); - $covrecorder->stop_instrumentation(); - } else { - // Testing without coverage - parent::run($simpletestreporter); - } - } -} - -/** - * CoverageRecorder class extension supporting multiple - * coverage instrumentations to be accumulated - * - * This class extends CoverageRecorder class in order to - * support multimple xdebug code coverage sessions to be - * executed and get acummulated info about all them in order - * to produce one unique report (default CoverageRecorder - * resets info on each instrumentation (coverage session) - * - * @package moodlecore - * @subpackage simpletestcoverage - * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class moodle_coverage_recorder extends CoverageRecorder { - - public function __construct($reporter='new moodle_coverage_reporter()') { - parent::__construct(array(), array(), $reporter); - } - - /** - * Stop gathering coverage data, saving it for later reporting - */ - public function stop_instrumentation() { - if(extension_loaded("xdebug")) { - $lastcoveragedata = xdebug_get_code_coverage(); // Get last instrumentation coverage data - xdebug_stop_code_coverage(); // Stop code coverage - $this->coverageData = self::merge_coverage_data($this->coverageData, $lastcoveragedata); // Append lastcoveragedata - $this->logger->debug("[moodle_coverage_recorder::stopInstrumentation()] Code coverage: " . print_r($this->coverageData, true), - __FILE__, __LINE__); - return true; - } else { - $this->logger->critical("[moodle_coverage_recorder::stopInstrumentation()] Xdebug not loaded.", __FILE__, __LINE__); - } - return false; - } - - /** - * Start gathering coverage data - */ - public function start_instrumentation() { - $this->startInstrumentation(); /// Simple lowercase wrap over Spike function - } - - /** - * Generate the code coverage report - */ - public function generate_report() { - $this->generateReport(); /// Simple lowercase wrap over Spike function - } - - /** - * Determines if the server is able to run code coverage analysis - * - * @return bool - */ - static public function can_run_codecoverage() { - // Only req is xdebug loaded. PEAR XML is already in place and available - if(!extension_loaded("xdebug")) { - return false; - } - return true; - } - - /** - * Merge two collections of complete code coverage data - */ - protected static function merge_coverage_data($cov1, $cov2) { - - $result = array(); - - // protection against empty coverage collections - if (!is_array($cov1)) { - $cov1 = array(); - } - if (!is_array($cov2)) { - $cov2 = array(); - } - - // Get all the files used in both coverage datas - $files = array_unique(array_merge(array_keys($cov1), array_keys($cov2))); - - // Iterate, getting results - foreach($files as $file) { - // If file exists in both coverages, let's merge their lines - if (array_key_exists($file, $cov1) && array_key_exists($file, $cov2)) { - $result[$file] = self::merge_lines_coverage_data($cov1[$file], $cov2[$file]); - // Only one of the coverages has the file - } else if (array_key_exists($file, $cov1)) { - $result[$file] = $cov1[$file]; - } else { - $result[$file] = $cov2[$file]; - } - } - return $result; - } - - /** - * Merge two collections of lines of code coverage data belonging to the same file - * - * Merge algorithm obtained from Phing: http://phing.info - */ - protected static function merge_lines_coverage_data($lines1, $lines2) { - - $result = array(); - - reset($lines1); - reset($lines2); - - while (current($lines1) && current($lines2)) { - $linenr1 = key($lines1); - $linenr2 = key($lines2); - - if ($linenr1 < $linenr2) { - $result[$linenr1] = current($lines1); - next($lines1); - } else if ($linenr2 < $linenr1) { - $result[$linenr2] = current($lines2); - next($lines2); - } else { - if (current($lines1) < 0) { - $result[$linenr2] = current($lines2); - } else if (current($lines2) < 0) { - $result[$linenr2] = current($lines1); - } else { - $result[$linenr2] = current($lines1) + current($lines2); - } - next($lines1); - next($lines2); - } - } - - while (current($lines1)) { - $result[key($lines1)] = current($lines1); - next($lines1); - } - - while (current($lines2)) { - $result[key($lines2)] = current($lines2); - next($lines2); - } - - return $result; - } -} - -/** - * HtmlCoverageReporter class extension supporting Moodle customizations - * - * This class extends the HtmlCoverageReporter class in order to - * implement Moodle look and feel, inline reporting after executing - * unit tests, proper linking and other tweaks here and there. - * - * @package moodlecore - * @subpackage simpletestcoverage - * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class moodle_coverage_reporter extends HtmlCoverageReporter { - - public function __construct($heading='Coverage Report', $dir='report') { - global $CFG; - parent::__construct($heading, '', $CFG->dataroot . '/codecoverage/' . $dir); - } - - /** - * Writes one row in the index.html table to display filename - * and coverage recording. - * - * Overrided to transform names and links to shorter format - * - * @param $fileLink link to html details file. - * @param $realFile path to real PHP file. - * @param $fileCoverage Coverage recording for that file. - * @return string HTML code for a single row. - * @access protected - */ - protected function writeIndexFileTableRow($fileLink, $realFile, $fileCoverage) { - - global $CFG; - - $fileLink = str_replace($CFG->dirroot, '', $fileLink); - $realFile = str_replace($CFG->dirroot, '', $realFile); - - return parent::writeIndexFileTableRow($fileLink, $realFile, $fileCoverage);; - } - - /** - * Mark a source code file based on the coverage data gathered - * - * Overrided to transform names and links to shorter format - * - * @param $phpFile Name of the actual source file - * @param $fileLink Link to the html mark-up file for the $phpFile - * @param &$coverageLines Coverage recording for $phpFile - * @return boolean FALSE on failure - * @access protected - */ - protected function markFile($phpFile, $fileLink, &$coverageLines) { - global $CFG; - - $fileLink = str_replace($CFG->dirroot, '', $fileLink); - - return parent::markFile($phpFile, $fileLink, $coverageLines); - } - - - /** - * Update the grand totals - * - * Overrided to avoid the call to recordFileCoverageInfo() - * because it has been already executed by writeIndexFile() and - * cause files to be duplicated in the fileCoverage property - */ - protected function updateGrandTotals(&$coverageCounts) { - $this->grandTotalLines += $coverageCounts['total']; - $this->grandTotalCoveredLines += $coverageCounts['covered']; - $this->grandTotalUncoveredLines += $coverageCounts['uncovered']; - } - - /** - * Generate the static report - * - * Overrided to generate the serialised object to be displayed inline - * with the test results. - * - * @param &$data Reference to Coverage Data - */ - public function generateReport(&$data) { - parent::generateReport($data); - - // head data - $data = new stdClass(); - $data->time = time(); - $data->title = $this->heading; - $data->output = $this->outputDir; - - // summary data - $data->totalfiles = $this->grandTotalFiles; - $data->totalln = $this->grandTotalLines; - $data->totalcoveredln = $this->grandTotalCoveredLines; - $data->totaluncoveredln = $this->grandTotalUncoveredLines; - $data->totalpercentage = $this->getGrandCodeCoveragePercentage(); - - // file details data - $data->coveragedetails = $this->fileCoverage; - - // save serialised object - file_put_contents($data->output . '/codecoverage.ser', serialize($data)); - } - - /** - * Return the html contents for the summary for the last execution of the - * given test type - * - * @param string $type of the test to return last execution summary (dbtest|unittest) - * @return string html contents of the summary - */ - static public function get_summary_info($type) { - global $CFG, $OUTPUT; - - $serfilepath = $CFG->dataroot . '/codecoverage/' . $type . '/codecoverage.ser'; - if (file_exists($serfilepath) && is_readable($serfilepath)) { - if ($data = unserialize(file_get_contents($serfilepath))) { - // return one table with all the totals (we avoid individual file results here) - $result = ''; - $table = new html_table(); - $table->align = array('right', 'left'); - $table->tablealign = 'center'; - $table->attributes['class'] = 'codecoveragetable'; - $table->id = 'codecoveragetable_' . $type; - $table->rowclasses = array('label', 'value'); - $table->data = array( - array(get_string('date') , userdate($data->time)), - array(get_string('files') , format_float($data->totalfiles, 0)), - array(get_string('totallines', 'tool_unittest') , format_float($data->totalln, 0)), - array(get_string('executablelines', 'tool_unittest') , format_float($data->totalcoveredln + $data->totaluncoveredln, 0)), - array(get_string('coveredlines', 'tool_unittest') , format_float($data->totalcoveredln, 0)), - array(get_string('uncoveredlines', 'tool_unittest') , format_float($data->totaluncoveredln, 0)), - array(get_string('coveredpercentage', 'tool_unittest'), format_float($data->totalpercentage, 2) . '%') - ); - - $url = $CFG->wwwroot . '/'.$CFG->admin.'/tool/unittest/coveragefile.php/' . $type . '/index.html'; - $result .= $OUTPUT->heading($data->title, 3, 'main codecoverageheading'); - $result .= $OUTPUT->heading('' . get_string('codecoveragecompletereport', 'tool_unittest') . '', 4, 'main codecoveragelink'); - $result .= html_writer::table($table); - - return $OUTPUT->box($result, 'generalbox boxwidthwide boxaligncenter codecoveragebox', '', true); - } - } - return false; - } - - /** - * Print the html contents for the summary for the last execution of the - * given test type - * - * @param string $type of the test to return last execution summary (dbtest|unittest) - * @return string html contents of the summary - */ - static public function print_summary_info($type) { - echo self::get_summary_info($type); - } - - /** - * Return the html code needed to browse latest code coverage complete report of the - * given test type - * - * @param string $type of the test to return last execution summary (dbtest|unittest) - * @return string html contents of the summary - */ - static public function get_link_to_latest($type) { - global $CFG, $OUTPUT; - - $serfilepath = $CFG->dataroot . '/codecoverage/' . $type . '/codecoverage.ser'; - if (file_exists($serfilepath) && is_readable($serfilepath)) { - if ($data = unserialize(file_get_contents($serfilepath))) { - $info = new stdClass(); - $info->date = userdate($data->time); - $info->files = format_float($data->totalfiles, 0); - $info->percentage = format_float($data->totalpercentage, 2) . '%'; - - $strlatestreport = get_string('codecoveragelatestreport', 'tool_unittest'); - $strlatestdetails = get_string('codecoveragelatestdetails', 'tool_unittest', $info); - - // return one link to latest complete report - $result = ''; - $url = $CFG->wwwroot . '/'.$CFG->admin.'/tool/unittest/coveragefile.php/' . $type . '/index.html'; - $result .= $OUTPUT->heading('' . $strlatestreport . '', 3, 'main codecoveragelink'); - $result .= $OUTPUT->heading($strlatestdetails, 4, 'main codecoveragedetails'); - return $OUTPUT->box($result, 'generalbox boxwidthwide boxaligncenter codecoveragebox', '', true); - } - } - return false; - } - - /** - * Print the html code needed to browse latest code coverage complete report of the - * given test type - * - * @param string $type of the test to return last execution summary (dbtest|unittest) - * @return string html contents of the summary - */ - static public function print_link_to_latest($type) { - echo self::get_link_to_latest($type); - } -} - - -/** - * Return information about classes and functions - * - * This function will parse any PHP file, extracting information about the - * classes and functions defined within it, providing "File Reflection" as - * PHP standard reflection classes don't support that. - * - * The idea and the code has been obtained from the Zend Framework Reflection API - * http://framework.zend.com/manual/en/zend.reflection.reference.html - * - * Usage: $ref_file = moodle_reflect_file($file); - * - * @param string $file full path to the php file to introspect - * @return object object with both 'classes' and 'functions' properties - */ -function moodle_reflect_file($file) { - - $contents = file_get_contents($file); - $tokens = token_get_all($contents); - - $functionTrapped = false; - $classTrapped = false; - $openBraces = 0; - - $classes = array(); - $functions = array(); - - foreach ($tokens as $token) { - /* - * Tokens are characters representing symbols or arrays - * representing strings. The keys/values in the arrays are - * - * - 0 => token id, - * - 1 => string, - * - 2 => line number - * - * Token ID's are explained here: - * http://www.php.net/manual/en/tokens.php. - */ - - if (is_array($token)) { - $type = $token[0]; - $value = $token[1]; - $lineNum = $token[2]; - } else { - // It's a symbol - // Maintain the count of open braces - if ($token == '{') { - $openBraces++; - } else if ($token == '}') { - $openBraces--; - } - - continue; - } - - switch ($type) { - // Name of something - case T_STRING: - if ($functionTrapped) { - $functions[] = $value; - $functionTrapped = false; - } elseif ($classTrapped) { - $classes[] = $value; - $classTrapped = false; - } - continue; - - // Functions - case T_FUNCTION: - if ($openBraces == 0) { - $functionTrapped = true; - } - break; - - // Classes - case T_CLASS: - $classTrapped = true; - break; - - // Default case: do nothing - default: - break; - } - } - - return (object)array('classes' => $classes, 'functions' => $functions); -} diff --git a/admin/tool/unittest/simpletestlib.php b/admin/tool/unittest/simpletestlib.php deleted file mode 100644 index e60faf73ac5..00000000000 --- a/admin/tool/unittest/simpletestlib.php +++ /dev/null @@ -1,1371 +0,0 @@ -. - -/** - * Utility functions to make unit testing easier. - * - * These functions, particularly the the database ones, are quick and - * dirty methods for getting things done in test cases. None of these - * methods should be used outside test code. - * - * Major Contirbutors - * - T.J.Hunt@open.ac.uk - * - * @package tool - * @subpackage unittest - * @copyright © 2006 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Includes - */ -require_once($CFG->libdir . '/simpletestlib/simpletest.php'); -require_once($CFG->libdir . '/simpletestlib/unit_tester.php'); -require_once($CFG->libdir . '/simpletestlib/expectation.php'); -require_once($CFG->libdir . '/simpletestlib/reporter.php'); -require_once($CFG->libdir . '/simpletestlib/web_tester.php'); -require_once($CFG->libdir . '/simpletestlib/mock_objects.php'); - -/** - * Recursively visit all the files in the source tree. Calls the callback - * function with the pathname of each file found. - * - * @param $path the folder to start searching from. - * @param $callback the function to call with the name of each file found. - * @param $fileregexp a regexp used to filter the search (optional). - * @param $exclude If true, pathnames that match the regexp will be ingored. If false, - * only files that match the regexp will be included. (default false). - * @param array $ignorefolders will not go into any of these folders (optional). - */ -function recurseFolders($path, $callback, $fileregexp = '/.*/', $exclude = false, $ignorefolders = array()) { - $files = scandir($path); - - foreach ($files as $file) { - $filepath = $path .'/'. $file; - if (strpos($file, '.') === 0) { - /// Don't check hidden files. - continue; - } else if (is_dir($filepath)) { - if (!in_array($filepath, $ignorefolders)) { - recurseFolders($filepath, $callback, $fileregexp, $exclude, $ignorefolders); - } - } else if ($exclude xor preg_match($fileregexp, $filepath)) { - call_user_func($callback, $filepath); - } - } -} - -/** - * An expectation for comparing strings ignoring whitespace. - * - * @package moodlecore - * @subpackage simpletestex - * @copyright © 2006 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class IgnoreWhitespaceExpectation extends SimpleExpectation { - var $expect; - - function __construct($content, $message = '%s') { - parent::__construct($message); - $this->expect=$this->normalise($content); - } - - function test($ip) { - return $this->normalise($ip)==$this->expect; - } - - function normalise($text) { - return preg_replace('/\s+/m',' ',trim($text)); - } - - function testMessage($ip) { - return "Input string [$ip] doesn't match the required value."; - } -} - -/** - * An Expectation that two arrays contain the same list of values. - * - * @package moodlecore - * @subpackage simpletestex - * @copyright © 2006 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class ArraysHaveSameValuesExpectation extends SimpleExpectation { - var $expect; - - function __construct($expected, $message = '%s') { - parent::__construct($message); - if (!is_array($expected)) { - trigger_error('Attempt to create an ArraysHaveSameValuesExpectation ' . - 'with an expected value that is not an array.'); - } - $this->expect = $this->normalise($expected); - } - - function test($actual) { - return $this->normalise($actual) == $this->expect; - } - - function normalise($array) { - sort($array); - return $array; - } - - function testMessage($actual) { - return 'Array [' . implode(', ', $actual) . - '] does not contain the expected list of values [' . implode(', ', $this->expect) . '].'; - } -} - - -/** - * An Expectation that compares to objects, and ensures that for every field in the - * expected object, there is a key of the same name in the actual object, with - * the same value. (The actual object may have other fields to, but we ignore them.) - * - * @package moodlecore - * @subpackage simpletestex - * @copyright © 2006 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class CheckSpecifiedFieldsExpectation extends SimpleExpectation { - var $expect; - - function __construct($expected, $message = '%s') { - parent::__construct($message); - if (!is_object($expected)) { - trigger_error('Attempt to create a CheckSpecifiedFieldsExpectation ' . - 'with an expected value that is not an object.'); - } - $this->expect = $expected; - } - - function test($actual) { - foreach ($this->expect as $key => $value) { - if (isset($value) && isset($actual->$key) && $actual->$key == $value) { - // OK - } else if (is_null($value) && is_null($actual->$key)) { - // OK - } else { - return false; - } - } - return true; - } - - function testMessage($actual) { - $mismatches = array(); - foreach ($this->expect as $key => $value) { - if (isset($value) && isset($actual->$key) && $actual->$key == $value) { - // OK - } else if (is_null($value) && is_null($actual->$key)) { - // OK - } else if (!isset($actual->$key)) { - $mismatches[] = $key . ' (expected [' . $value . '] but was missing.'; - } else { - $mismatches[] = $key . ' (expected [' . $value . '] got [' . $actual->$key . '].'; - } - } - return 'Actual object does not have all the same fields with the same values as the expected object (' . - implode(', ', $mismatches) . ').'; - } -} - -abstract class XMLStructureExpectation extends SimpleExpectation { - /** - * Parse a string as XML and return a DOMDocument; - * @param $html - * @return unknown_type - */ - protected function load_xml($html) { - $prevsetting = libxml_use_internal_errors(true); - $parser = new DOMDocument(); - if (!$parser->loadXML('' . $html . '')) { - $parser = new DOMDocument(); - } - libxml_clear_errors(); - libxml_use_internal_errors($prevsetting); - return $parser; - } - - function testMessage($html) { - $parsererrors = $this->load_xml($html); - if (is_array($parsererrors)) { - foreach ($parsererrors as $key => $message) { - $parsererrors[$key] = $message->message; - } - return 'Could not parse XML [' . $html . '] errors were [' . - implode('], [', $parsererrors) . ']'; - } - return $this->customMessage($html); - } -} -/** - * An Expectation that looks to see whether some HMTL contains a tag with a certain attribute. - * - * @copyright 2009 Tim Hunt - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class ContainsTagWithAttribute extends XMLStructureExpectation { - protected $tag; - protected $attribute; - protected $value; - - function __construct($tag, $attribute, $value, $message = '%s') { - parent::__construct($message); - $this->tag = $tag; - $this->attribute = $attribute; - $this->value = $value; - } - - function test($html) { - $parser = $this->load_xml($html); - if (is_array($parser)) { - return false; - } - $list = $parser->getElementsByTagName($this->tag); - - foreach ($list as $node) { - if ($node->attributes->getNamedItem($this->attribute)->nodeValue === (string) $this->value) { - return true; - } - } - return false; - } - - function customMessage($html) { - return 'Content [' . $html . '] does not contain the tag [' . - $this->tag . '] with attribute [' . $this->attribute . '="' . $this->value . '"].'; - } -} - -/** - * An Expectation that looks to see whether some HMTL contains a tag with an array of attributes. - * All attributes must be present and their values must match the expected values. - * A third parameter can be used to specify attribute=>value pairs which must not be present in a positive match. - * - * @copyright 2009 Nicolas Connault - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class ContainsTagWithAttributes extends XMLStructureExpectation { - /** - * @var string $tag The name of the Tag to search - */ - protected $tag; - /** - * @var array $expectedvalues An associative array of parameters, all of which must be matched - */ - protected $expectedvalues = array(); - /** - * @var array $forbiddenvalues An associative array of parameters, none of which must be matched - */ - protected $forbiddenvalues = array(); - /** - * @var string $failurereason The reason why the test failed: nomatch or forbiddenmatch - */ - protected $failurereason = 'nomatch'; - - function __construct($tag, $expectedvalues, $forbiddenvalues=array(), $message = '%s') { - parent::__construct($message); - $this->tag = $tag; - $this->expectedvalues = $expectedvalues; - $this->forbiddenvalues = $forbiddenvalues; - } - - function test($html) { - $parser = $this->load_xml($html); - if (is_array($parser)) { - return false; - } - - $list = $parser->getElementsByTagName($this->tag); - $foundamatch = false; - - // Iterating through inputs - foreach ($list as $node) { - if (empty($node->attributes) || !is_a($node->attributes, 'DOMNamedNodeMap')) { - continue; - } - - // For the current expected attribute under consideration, check that values match - $allattributesmatch = true; - - foreach ($this->expectedvalues as $expectedattribute => $expectedvalue) { - if ($node->getAttribute($expectedattribute) === '' && $expectedvalue !== '') { - $this->failurereason = 'nomatch'; - continue 2; // Skip this tag, it doesn't have all the expected attributes - } - if ($node->getAttribute($expectedattribute) !== (string) $expectedvalue) { - $allattributesmatch = false; - $this->failurereason = 'nomatch'; - } - } - - if ($allattributesmatch) { - $foundamatch = true; - - // Now make sure this node doesn't have any of the forbidden attributes either - $nodeattrlist = $node->attributes; - - foreach ($nodeattrlist as $domattrname => $domattr) { - if (array_key_exists($domattrname, $this->forbiddenvalues) && $node->getAttribute($domattrname) === (string) $this->forbiddenvalues[$domattrname]) { - $this->failurereason = "forbiddenmatch:$domattrname:" . $node->getAttribute($domattrname); - $foundamatch = false; - } - } - } - } - - return $foundamatch; - } - - function customMessage($html) { - $output = 'Content [' . $html . '] '; - - if (preg_match('/forbiddenmatch:(.*):(.*)/', $this->failurereason, $matches)) { - $output .= "contains the tag $this->tag with the forbidden attribute=>value pair: [$matches[1]=>$matches[2]]"; - } else if ($this->failurereason == 'nomatch') { - $output .= 'does not contain the tag [' . $this->tag . '] with attributes ['; - foreach ($this->expectedvalues as $var => $val) { - $output .= "$var=\"$val\" "; - } - $output = rtrim($output); - $output .= '].'; - } - - return $output; - } -} - -/** - * An Expectation that looks to see whether some HMTL contains a tag with an array of attributes. - * All attributes must be present and their values must match the expected values. - * A third parameter can be used to specify attribute=>value pairs which must not be present in a positive match. - * - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class ContainsSelectExpectation extends XMLStructureExpectation { - /** - * @var string $tag The name of the Tag to search - */ - protected $name; - /** - * @var array $expectedvalues An associative array of parameters, all of which must be matched - */ - protected $choices; - /** - * @var array $forbiddenvalues An associative array of parameters, none of which must be matched - */ - protected $selected; - /** - * @var string $failurereason The reason why the test failed: nomatch or forbiddenmatch - */ - protected $enabled; - - function __construct($name, $choices, $selected = null, $enabled = null, $message = '%s') { - parent::__construct($message); - $this->name = $name; - $this->choices = $choices; - $this->selected = $selected; - $this->enabled = $enabled; - } - - function test($html) { - $parser = $this->load_xml($html); - if (is_array($parser)) { - return false; - } - - $list = $parser->getElementsByTagName('select'); - - // Iterating through inputs - foreach ($list as $node) { - if (empty($node->attributes) || !is_a($node->attributes, 'DOMNamedNodeMap')) { - continue; - } - - if ($node->getAttribute('name') != $this->name) { - continue; - } - - if ($this->enabled === true && $node->getAttribute('disabled')) { - continue; - } else if ($this->enabled === false && $node->getAttribute('disabled') != 'disabled') { - continue; - } - - $options = $node->getElementsByTagName('option'); - reset($this->choices); - foreach ($options as $option) { - if ($option->getAttribute('value') != key($this->choices)) { - continue 2; - } - if ($option->firstChild->wholeText != current($this->choices)) { - continue 2; - } - if ($option->getAttribute('value') === $this->selected && - !$option->hasAttribute('selected')) { - continue 2; - } - next($this->choices); - } - if (current($this->choices) !== false) { - // The HTML did not contain all the choices. - return false; - } - return true; - } - return false; - } - - function customMessage($html) { - if ($this->enabled === true) { - $state = 'an enabled'; - } else if ($this->enabled === false) { - $state = 'a disabled'; - } else { - $state = 'a'; - } - $output = 'Content [' . $html . '] does not contain ' . $state . - ' '; - $this->assert($expectation, $html); - } - - function test_zero_attr() { - $expectation = new ContainsTagWithAttribute('span', 'class', 0); - $this->assertTrue($expectation->test('message')); - } - - function test_zero_attr_does_not_match_blank() { - $expectation = new ContainsTagWithAttribute('span', 'class', 0); - $this->assertFalse($expectation->test('message')); - } - - function test_blank_attr() { - $expectation = new ContainsTagWithAttribute('span', 'class', ''); - $this->assertTrue($expectation->test('message')); - } - - function test_blank_attr_does_not_match_zero() { - $expectation = new ContainsTagWithAttribute('span', 'class', ''); - $this->assertFalse($expectation->test('message')); - } -} - - -/** - * Unit tests for the ContainsTagWithAttribute class. - * - * @copyright 2009 Tim Hunt - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class ContainsTagWithAttributes_test extends UnitTestCase { - function test_simple() { - $content = << -END; - $expectation = new ContainsTagWithAttributes('input', - array('type' => 'submit', 'name' => 'qIhr6wWLTt3,1_omact_gen_14', 'value' => 'Check')); - $this->assert($expectation, $content); - } - - function test_zero_attr() { - $expectation = new ContainsTagWithAttributes('span', array('class' => 0)); - $this->assertTrue($expectation->test('message')); - } - - function test_zero_attr_does_not_match_blank() { - $expectation = new ContainsTagWithAttributes('span', array('class' => 0)); - $this->assertFalse($expectation->test('message')); - } - - function test_blank_attr() { - $expectation = new ContainsTagWithAttributes('span', array('class' => '')); - $this->assertTrue($expectation->test('message')); - } - - function test_blank_attr_does_not_match_zero() { - $expectation = new ContainsTagWithAttributes('span', array('class' => '')); - $this->assertFalse($expectation->test('message')); - } -} - - -/** - * Unit tests for the ContainsTagWithAttribute_test class. - * - * @copyright 2009 Tim Hunt - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class ContainsTagWithContents_test extends UnitTestCase { - function test_simple() { - $expectation = new ContainsTagWithContents('span', 'message'); - $this->assertTrue($expectation->test('message')); - } - - function test_no_end() { - $expectation = new ContainsTagWithContents('span', 'message'); - $this->assertFalse($expectation->test('message')); - } -} - - -/** - * Unit tests for the {@link ContainsSelectExpectation} class. - * - * @copyright 2010 The Open University. - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class ContainsSelectExpectation_test extends UnitTestCase { - function test_matching_select_passes() { - $expectation = new ContainsSelectExpectation('selectname', array('Choice1', 'Choice2')); - $this->assertTrue($expectation->test(' - ')); - } - - function test_fails_if_no_select() { - $expectation = new ContainsSelectExpectation('selectname', array('Choice1', 'Choice2')); - $this->assertFalse($expectation->test('should not match')); - } - - function test_select_with_missing_choices_fails() { - $expectation = new ContainsSelectExpectation('selectname', array('Choice1', 'Choice2')); - $this->assertFalse($expectation->test(' - ')); - } - - function test_select_with_extra_choices_fails() { - $expectation = new ContainsSelectExpectation('selectname', array('Choice1')); - $this->assertFalse($expectation->test(' - ')); - } - - function test_select_with_wrong_order_choices_fails() { - $expectation = new ContainsSelectExpectation('selectname', array('Choice1')); - $this->assertFalse($expectation->test(' - ')); - } - - function test_select_check_selected_pass() { - $expectation = new ContainsSelectExpectation('selectname', - array('key1' => 'Choice1', 'key2' => 'Choice2'), 'key2'); - $this->assertTrue($expectation->test(' - ')); - } - - function test_select_check_wrong_one_selected_fail() { - $expectation = new ContainsSelectExpectation('selectname', - array('key1' => 'Choice1', 'key2' => 'Choice2'), 'key2'); - $this->assertFalse($expectation->test(' - ')); - } - - function test_select_check_nothing_selected_fail() { - $expectation = new ContainsSelectExpectation('selectname', - array('key1' => 'Choice1', 'key2' => 'Choice2'), 'key2'); - $this->assertFalse($expectation->test(' - ')); - } - - function test_select_disabled_pass() { - $expectation = new ContainsSelectExpectation('selectname', - array('key1' => 'Choice1', 'key2' => 'Choice2'), null, false); - $this->assertTrue($expectation->test(' - ')); - } - - function test_select_disabled_fail1() { - $expectation = new ContainsSelectExpectation('selectname', - array('key1' => 'Choice1', 'key2' => 'Choice2'), null, true); - $this->assertFalse($expectation->test(' - ')); - } - - function test_select_disabled_fail2() { - $expectation = new ContainsSelectExpectation('selectname', - array('key1' => 'Choice1', 'key2' => 'Choice2'), null, false); - $this->assertFalse($expectation->test(' - ')); - } -} - - -/** - * Unit tests for the {@link DoesNotContainTagWithAttributes} class. - * - * @copyright 2010 The Open University - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class DoesNotContainTagWithAttributes_test extends UnitTestCase { - function test_simple() { - $content = << -END; - $expectation = new DoesNotContainTagWithAttributes('input', - array('type' => 'submit', 'name' => 'qIhr6wWLTt3,1_omact_gen_14', 'value' => 'Check')); - $this->assertFalse($expectation->test($content)); - } - - function test_zero_attr() { - $expectation = new DoesNotContainTagWithAttributes('span', array('class' => 0)); - $this->assertFalse($expectation->test('message')); - } - - function test_zero_different_attr_ok() { - $expectation = new DoesNotContainTagWithAttributes('span', array('class' => 'shrub')); - $this->assertTrue($expectation->test('message')); - } - - function test_blank_attr() { - $expectation = new DoesNotContainTagWithAttributes('span', array('class' => '')); - $this->assertFalse($expectation->test('message')); - } - - function test_blank_attr_does_not_match_zero() { - $expectation = new ContainsTagWithAttributes('span', array('class' => '')); - $this->assertFalse($expectation->test('message')); - } -} diff --git a/lib/simpletest/testunittestusingdb.php b/lib/simpletest/testunittestusingdb.php deleted file mode 100644 index 7bc487bce51..00000000000 --- a/lib/simpletest/testunittestusingdb.php +++ /dev/null @@ -1,33 +0,0 @@ -testdb->get_manager(); - - $this->assertFalse($dbman->table_exists('quiz_attempts')); - $this->assertFalse($dbman->table_exists('quiz')); - $this->create_test_table('quiz_attempts', 'mod/quiz'); - $this->assertTrue($dbman->table_exists('quiz_attempts')); - $this->assertFalse($dbman->table_exists('quiz')); - - $this->load_test_data('quiz_attempts', - array('quiz', 'uniqueid', 'attempt', 'preview', 'layout'), array( - array( 1 , 1 , 1 , 0 , '1,2,3,0'), - array( 1 , 2 , 2 , 1 , '2,3,1,0'))); - - $this->switch_to_test_db(); - require_once($CFG->dirroot . '/mod/quiz/locallib.php'); - $this->assertTrue(quiz_has_attempts(1)); - $this->revert_to_real_db(); - - $this->drop_test_table('quiz_attempts'); - $this->assertFalse($dbman->table_exists('quiz_attempts')); - } - -} - diff --git a/lib/simpletestlib/HELP_MY_TESTS_DONT_WORK_ANYMORE b/lib/simpletestlib/HELP_MY_TESTS_DONT_WORK_ANYMORE deleted file mode 100644 index a65e83e8762..00000000000 --- a/lib/simpletestlib/HELP_MY_TESTS_DONT_WORK_ANYMORE +++ /dev/null @@ -1,399 +0,0 @@ -Simple Test interface changes -============================= -Because the SimpleTest tool set is still evolving it is likely that tests -written with earlier versions will fail with the newest ones. The most -dramatic changes are in the alpha releases. Here is a list of possible -problems and their fixes... - -assertText() no longer finds a string inside a ', 'js'); - $this->mapHandler('comment', 'ignore'); - $this->addEntryPattern('', 'comment'); - } - - /** - * Pattern matches to start and end a tag. - * @param string $tag Name of tag to scan for. - * @access private - */ - protected function addTag($tag) { - $this->addSpecialPattern("", 'text', 'acceptEndToken'); - $this->addEntryPattern("<$tag", 'text', 'tag'); - } - - /** - * Pattern matches to parse the inside of a tag - * including the attributes and their quoting. - * @access private - */ - protected function addInTagTokens() { - $this->mapHandler('tag', 'acceptStartToken'); - $this->addSpecialPattern('\s+', 'tag', 'ignore'); - $this->addAttributeTokens(); - $this->addExitPattern('/>', 'tag'); - $this->addExitPattern('>', 'tag'); - } - - /** - * Matches attributes that are either single quoted, - * double quoted or unquoted. - * @access private - */ - protected function addAttributeTokens() { - $this->mapHandler('dq_attribute', 'acceptAttributeToken'); - $this->addEntryPattern('=\s*"', 'tag', 'dq_attribute'); - $this->addPattern("\\\\\"", 'dq_attribute'); - $this->addExitPattern('"', 'dq_attribute'); - $this->mapHandler('sq_attribute', 'acceptAttributeToken'); - $this->addEntryPattern("=\s*'", 'tag', 'sq_attribute'); - $this->addPattern("\\\\'", 'sq_attribute'); - $this->addExitPattern("'", 'sq_attribute'); - $this->mapHandler('uq_attribute', 'acceptAttributeToken'); - $this->addSpecialPattern('=\s*[^>\s]*', 'tag', 'uq_attribute'); - } -} - -/** - * Converts HTML tokens into selected SAX events. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleHtmlSaxParser { - private $lexer; - private $listener; - private $tag; - private $attributes; - private $current_attribute; - - /** - * Sets the listener. - * @param SimplePhpPageBuilder $listener SAX event handler. - * @access public - */ - function __construct($listener) { - $this->listener = $listener; - $this->lexer = $this->createLexer($this); - $this->tag = ''; - $this->attributes = array(); - $this->current_attribute = ''; - } - - /** - * Runs the content through the lexer which - * should call back to the acceptors. - * @param string $raw Page text to parse. - * @return boolean False if parse error. - * @access public - */ - function parse($raw) { - return $this->lexer->parse($raw); - } - - /** - * Sets up the matching lexer. Starts in 'text' mode. - * @param SimpleSaxParser $parser Event generator, usually $self. - * @return SimpleLexer Lexer suitable for this parser. - * @access public - */ - static function createLexer(&$parser) { - return new SimpleHtmlLexer($parser); - } - - /** - * Accepts a token from the tag mode. If the - * starting element completes then the element - * is dispatched and the current attributes - * set back to empty. The element or attribute - * name is converted to lower case. - * @param string $token Incoming characters. - * @param integer $event Lexer event type. - * @return boolean False if parse error. - * @access public - */ - function acceptStartToken($token, $event) { - if ($event == LEXER_ENTER) { - $this->tag = strtolower(substr($token, 1)); - return true; - } - if ($event == LEXER_EXIT) { - $success = $this->listener->startElement( - $this->tag, - $this->attributes); - $this->tag = ''; - $this->attributes = array(); - return $success; - } - if ($token != '=') { - $this->current_attribute = strtolower(html_entity_decode($token, ENT_QUOTES)); - $this->attributes[$this->current_attribute] = ''; - } - return true; - } - - /** - * Accepts a token from the end tag mode. - * The element name is converted to lower case. - * @param string $token Incoming characters. - * @param integer $event Lexer event type. - * @return boolean False if parse error. - * @access public - */ - function acceptEndToken($token, $event) { - if (! preg_match('/<\/(.*)>/', $token, $matches)) { - return false; - } - return $this->listener->endElement(strtolower($matches[1])); - } - - /** - * Part of the tag data. - * @param string $token Incoming characters. - * @param integer $event Lexer event type. - * @return boolean False if parse error. - * @access public - */ - function acceptAttributeToken($token, $event) { - if ($this->current_attribute) { - if ($event == LEXER_UNMATCHED) { - $this->attributes[$this->current_attribute] .= - html_entity_decode($token, ENT_QUOTES); - } - if ($event == LEXER_SPECIAL) { - $this->attributes[$this->current_attribute] .= - preg_replace('/^=\s*/' , '', html_entity_decode($token, ENT_QUOTES)); - } - } - return true; - } - - /** - * A character entity. - * @param string $token Incoming characters. - * @param integer $event Lexer event type. - * @return boolean False if parse error. - * @access public - */ - function acceptEntityToken($token, $event) { - } - - /** - * Character data between tags regarded as - * important. - * @param string $token Incoming characters. - * @param integer $event Lexer event type. - * @return boolean False if parse error. - * @access public - */ - function acceptTextToken($token, $event) { - return $this->listener->addContent($token); - } - - /** - * Incoming data to be ignored. - * @param string $token Incoming characters. - * @param integer $event Lexer event type. - * @return boolean False if parse error. - * @access public - */ - function ignore($token, $event) { - return true; - } -} - -/** - * SAX event handler. Maintains a list of - * open tags and dispatches them as they close. - * @package SimpleTest - * @subpackage WebTester - */ -class SimplePhpPageBuilder { - private $tags; - private $page; - private $private_content_tag; - private $open_forms = array(); - private $complete_forms = array(); - private $frameset = false; - private $loading_frames = array(); - private $frameset_nesting_level = 0; - private $left_over_labels = array(); - - /** - * Frees up any references so as to allow the PHP garbage - * collection from unset() to work. - * @access public - */ - function free() { - unset($this->tags); - unset($this->page); - unset($this->private_content_tags); - $this->open_forms = array(); - $this->complete_forms = array(); - $this->frameset = false; - $this->loading_frames = array(); - $this->frameset_nesting_level = 0; - $this->left_over_labels = array(); - } - - /** - * This builder is always available. - * @return boolean Always true. - */ - function can() { - return true; - } - - /** - * Reads the raw content and send events - * into the page to be built. - * @param $response SimpleHttpResponse Fetched response. - * @return SimplePage Newly parsed page. - * @access public - */ - function parse($response) { - $this->tags = array(); - $this->page = $this->createPage($response); - $parser = $this->createParser($this); - $parser->parse($response->getContent()); - $this->acceptPageEnd(); - $page = $this->page; - $this->free(); - return $page; - } - - /** - * Creates an empty page. - * @return SimplePage New unparsed page. - * @access protected - */ - protected function createPage($response) { - return new SimplePage($response); - } - - /** - * Creates the parser used with the builder. - * @param SimplePhpPageBuilder $listener Target of parser. - * @return SimpleSaxParser Parser to generate - * events for the builder. - * @access protected - */ - protected function createParser(&$listener) { - return new SimpleHtmlSaxParser($listener); - } - - /** - * Start of element event. Opens a new tag. - * @param string $name Element name. - * @param hash $attributes Attributes without content - * are marked as true. - * @return boolean False on parse error. - * @access public - */ - function startElement($name, $attributes) { - $factory = new SimpleTagBuilder(); - $tag = $factory->createTag($name, $attributes); - if (! $tag) { - return true; - } - if ($tag->getTagName() == 'label') { - $this->acceptLabelStart($tag); - $this->openTag($tag); - return true; - } - if ($tag->getTagName() == 'form') { - $this->acceptFormStart($tag); - return true; - } - if ($tag->getTagName() == 'frameset') { - $this->acceptFramesetStart($tag); - return true; - } - if ($tag->getTagName() == 'frame') { - $this->acceptFrame($tag); - return true; - } - if ($tag->isPrivateContent() && ! isset($this->private_content_tag)) { - $this->private_content_tag = &$tag; - } - if ($tag->expectEndTag()) { - $this->openTag($tag); - return true; - } - $this->acceptTag($tag); - return true; - } - - /** - * End of element event. - * @param string $name Element name. - * @return boolean False on parse error. - * @access public - */ - function endElement($name) { - if ($name == 'label') { - $this->acceptLabelEnd(); - return true; - } - if ($name == 'form') { - $this->acceptFormEnd(); - return true; - } - if ($name == 'frameset') { - $this->acceptFramesetEnd(); - return true; - } - if ($this->hasNamedTagOnOpenTagStack($name)) { - $tag = array_pop($this->tags[$name]); - if ($tag->isPrivateContent() && $this->private_content_tag->getTagName() == $name) { - unset($this->private_content_tag); - } - $this->addContentTagToOpenTags($tag); - $this->acceptTag($tag); - return true; - } - return true; - } - - /** - * Test to see if there are any open tags awaiting - * closure that match the tag name. - * @param string $name Element name. - * @return boolean True if any are still open. - * @access private - */ - protected function hasNamedTagOnOpenTagStack($name) { - return isset($this->tags[$name]) && (count($this->tags[$name]) > 0); - } - - /** - * Unparsed, but relevant data. The data is added - * to every open tag. - * @param string $text May include unparsed tags. - * @return boolean False on parse error. - * @access public - */ - function addContent($text) { - if (isset($this->private_content_tag)) { - $this->private_content_tag->addContent($text); - } else { - $this->addContentToAllOpenTags($text); - } - return true; - } - - /** - * Any content fills all currently open tags unless it - * is part of an option tag. - * @param string $text May include unparsed tags. - * @access private - */ - protected function addContentToAllOpenTags($text) { - foreach (array_keys($this->tags) as $name) { - for ($i = 0, $count = count($this->tags[$name]); $i < $count; $i++) { - $this->tags[$name][$i]->addContent($text); - } - } - } - - /** - * Parsed data in tag form. The parsed tag is added - * to every open tag. Used for adding options to select - * fields only. - * @param SimpleTag $tag Option tags only. - * @access private - */ - protected function addContentTagToOpenTags(&$tag) { - if ($tag->getTagName() != 'option') { - return; - } - foreach (array_keys($this->tags) as $name) { - for ($i = 0, $count = count($this->tags[$name]); $i < $count; $i++) { - $this->tags[$name][$i]->addTag($tag); - } - } - } - - /** - * Opens a tag for receiving content. Multiple tags - * will be receiving input at the same time. - * @param SimpleTag $tag New content tag. - * @access private - */ - protected function openTag($tag) { - $name = $tag->getTagName(); - if (! in_array($name, array_keys($this->tags))) { - $this->tags[$name] = array(); - } - $this->tags[$name][] = $tag; - } - - /** - * Adds a tag to the page. - * @param SimpleTag $tag Tag to accept. - * @access public - */ - protected function acceptTag($tag) { - if ($tag->getTagName() == "a") { - $this->page->addLink($tag); - } elseif ($tag->getTagName() == "base") { - $this->page->setBase($tag->getAttribute('href')); - } elseif ($tag->getTagName() == "title") { - $this->page->setTitle($tag); - } elseif ($this->isFormElement($tag->getTagName())) { - for ($i = 0; $i < count($this->open_forms); $i++) { - $this->open_forms[$i]->addWidget($tag); - } - $this->last_widget = $tag; - } - } - - /** - * Opens a label for a described widget. - * @param SimpleFormTag $tag Tag to accept. - * @access public - */ - protected function acceptLabelStart($tag) { - $this->label = $tag; - unset($this->last_widget); - } - - /** - * Closes the most recently opened label. - * @access public - */ - protected function acceptLabelEnd() { - if (isset($this->label)) { - if (isset($this->last_widget)) { - $this->last_widget->setLabel($this->label->getText()); - unset($this->last_widget); - } else { - $this->left_over_labels[] = SimpleTestCompatibility::copy($this->label); - } - unset($this->label); - } - } - - /** - * Tests to see if a tag is a possible form - * element. - * @param string $name HTML element name. - * @return boolean True if form element. - * @access private - */ - protected function isFormElement($name) { - return in_array($name, array('input', 'button', 'textarea', 'select')); - } - - /** - * Opens a form. New widgets go here. - * @param SimpleFormTag $tag Tag to accept. - * @access public - */ - protected function acceptFormStart($tag) { - $this->open_forms[] = new SimpleForm($tag, $this->page); - } - - /** - * Closes the most recently opened form. - * @access public - */ - protected function acceptFormEnd() { - if (count($this->open_forms)) { - $this->complete_forms[] = array_pop($this->open_forms); - } - } - - /** - * Opens a frameset. A frameset may contain nested - * frameset tags. - * @param SimpleFramesetTag $tag Tag to accept. - * @access public - */ - protected function acceptFramesetStart($tag) { - if (! $this->isLoadingFrames()) { - $this->frameset = $tag; - } - $this->frameset_nesting_level++; - } - - /** - * Closes the most recently opened frameset. - * @access public - */ - protected function acceptFramesetEnd() { - if ($this->isLoadingFrames()) { - $this->frameset_nesting_level--; - } - } - - /** - * Takes a single frame tag and stashes it in - * the current frame set. - * @param SimpleFrameTag $tag Tag to accept. - * @access public - */ - protected function acceptFrame($tag) { - if ($this->isLoadingFrames()) { - if ($tag->getAttribute('src')) { - $this->loading_frames[] = $tag; - } - } - } - - /** - * Test to see if in the middle of reading - * a frameset. - * @return boolean True if inframeset. - * @access private - */ - protected function isLoadingFrames() { - return $this->frameset and $this->frameset_nesting_level > 0; - } - - /** - * Marker for end of complete page. Any work in - * progress can now be closed. - * @access public - */ - protected function acceptPageEnd() { - while (count($this->open_forms)) { - $this->complete_forms[] = array_pop($this->open_forms); - } - foreach ($this->left_over_labels as $label) { - for ($i = 0, $count = count($this->complete_forms); $i < $count; $i++) { - $this->complete_forms[$i]->attachLabelBySelector( - new SimpleById($label->getFor()), - $label->getText()); - } - } - $this->page->setForms($this->complete_forms); - $this->page->setFrames($this->loading_frames); - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/readme_moodle.txt b/lib/simpletestlib/readme_moodle.txt deleted file mode 100644 index 740af27a137..00000000000 --- a/lib/simpletestlib/readme_moodle.txt +++ /dev/null @@ -1,14 +0,0 @@ -Description of Simpletest 1.1.0 library import into Moodle - -Obtained from http://www.simpletest.org/en/download.html - -Changes: - * removed extensions and test directories (documentation is kept because it is not available online) - * neutralised autorun.php - only execution via our UIs is allowed - * test_case.php - added our global $CFG before include() MDL-10064 - * modified run() in test_case.php - skipping tests that need fake db if prefix not set - * test_case.php - added TIME_ALLOWED_PER_UNIT_TEST constant which - resets php time limit for each test function - MDL-24909. Marked with - comments (replace existing per-class hack in test_case.php). - -skodak, Tim, sammarshall diff --git a/lib/simpletestlib/recorder.php b/lib/simpletestlib/recorder.php deleted file mode 100644 index b3d0d01c625..00000000000 --- a/lib/simpletestlib/recorder.php +++ /dev/null @@ -1,101 +0,0 @@ -time, $this->breadcrumb, $this->message) = - array(time(), $breadcrumb, $message); - } -} - -/** - * A single pass captured for later. - * @package SimpleTest - * @subpackage Extensions - */ -class SimpleResultOfPass extends SimpleResult { } - -/** - * A single failure captured for later. - * @package SimpleTest - * @subpackage Extensions - */ -class SimpleResultOfFail extends SimpleResult { } - -/** - * A single exception captured for later. - * @package SimpleTest - * @subpackage Extensions - */ -class SimpleResultOfException extends SimpleResult { } - -/** - * Array-based test recorder. Returns an array - * with timestamp, status, test name and message for each pass and failure. - * @package SimpleTest - * @subpackage Extensions - */ -class Recorder extends SimpleReporterDecorator { - public $results = array(); - - /** - * Stashes the pass as a SimpleResultOfPass - * for later retrieval. - * @param string $message Pass message to be displayed - * eventually. - */ - function paintPass($message) { - parent::paintPass($message); - $this->results[] = new SimpleResultOfPass(parent::getTestList(), $message); - } - - /** - * Stashes the fail as a SimpleResultOfFail - * for later retrieval. - * @param string $message Failure message to be displayed - * eventually. - */ - function paintFail($message) { - parent::paintFail($message); - $this->results[] = new SimpleResultOfFail(parent::getTestList(), $message); - } - - /** - * Stashes the exception as a SimpleResultOfException - * for later retrieval. - * @param string $message Exception message to be displayed - * eventually. - */ - function paintException($message) { - parent::paintException($message); - $this->results[] = new SimpleResultOfException(parent::getTestList(), $message); - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/reflection_php4.php b/lib/simpletestlib/reflection_php4.php deleted file mode 100644 index 39801ea1bdb..00000000000 --- a/lib/simpletestlib/reflection_php4.php +++ /dev/null @@ -1,136 +0,0 @@ -_interface = $interface; - } - - /** - * Checks that a class has been declared. - * @return boolean True if defined. - * @access public - */ - function classExists() { - return class_exists($this->_interface); - } - - /** - * Needed to kill the autoload feature in PHP5 - * for classes created dynamically. - * @return boolean True if defined. - * @access public - */ - function classExistsSansAutoload() { - return class_exists($this->_interface); - } - - /** - * Checks that a class or interface has been - * declared. - * @return boolean True if defined. - * @access public - */ - function classOrInterfaceExists() { - return class_exists($this->_interface); - } - - /** - * Needed to kill the autoload feature in PHP5 - * for classes created dynamically. - * @return boolean True if defined. - * @access public - */ - function classOrInterfaceExistsSansAutoload() { - return class_exists($this->_interface); - } - - /** - * Gets the list of methods on a class or - * interface. - * @returns array List of method names. - * @access public - */ - function getMethods() { - return get_class_methods($this->_interface); - } - - /** - * Gets the list of interfaces from a class. If the - * class name is actually an interface then just that - * interface is returned. - * @returns array List of interfaces. - * @access public - */ - function getInterfaces() { - return array(); - } - - /** - * Finds the parent class name. - * @returns string Parent class name. - * @access public - */ - function getParent() { - return strtolower(get_parent_class($this->_interface)); - } - - /** - * Determines if the class is abstract, which for PHP 4 - * will never be the case. - * @returns boolean True if abstract. - * @access public - */ - function isAbstract() { - return false; - } - - /** - * Determines if the the entity is an interface, which for PHP 4 - * will never be the case. - * @returns boolean True if interface. - * @access public - */ - function isInterface() { - return false; - } - - /** - * Scans for final methods, but as it's PHP 4 there - * aren't any. - * @returns boolean True if the class has a final method. - * @access public - */ - function hasFinal() { - return false; - } - - /** - * Gets the source code matching the declaration - * of a method. - * @param string $method Method name. - * @access public - */ - function getSignature($method) { - return "function &$method()"; - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/reflection_php5.php b/lib/simpletestlib/reflection_php5.php deleted file mode 100644 index 43d8a7b287f..00000000000 --- a/lib/simpletestlib/reflection_php5.php +++ /dev/null @@ -1,386 +0,0 @@ -interface = $interface; - } - - /** - * Checks that a class has been declared. Versions - * before PHP5.0.2 need a check that it's not really - * an interface. - * @return boolean True if defined. - * @access public - */ - function classExists() { - if (! class_exists($this->interface)) { - return false; - } - $reflection = new ReflectionClass($this->interface); - return ! $reflection->isInterface(); - } - - /** - * Needed to kill the autoload feature in PHP5 - * for classes created dynamically. - * @return boolean True if defined. - * @access public - */ - function classExistsSansAutoload() { - return class_exists($this->interface, false); - } - - /** - * Checks that a class or interface has been - * declared. - * @return boolean True if defined. - * @access public - */ - function classOrInterfaceExists() { - return $this->classOrInterfaceExistsWithAutoload($this->interface, true); - } - - /** - * Needed to kill the autoload feature in PHP5 - * for classes created dynamically. - * @return boolean True if defined. - * @access public - */ - function classOrInterfaceExistsSansAutoload() { - return $this->classOrInterfaceExistsWithAutoload($this->interface, false); - } - - /** - * Needed to select the autoload feature in PHP5 - * for classes created dynamically. - * @param string $interface Class or interface name. - * @param boolean $autoload True totriggerautoload. - * @return boolean True if interface defined. - * @access private - */ - protected function classOrInterfaceExistsWithAutoload($interface, $autoload) { - if (function_exists('interface_exists')) { - if (interface_exists($this->interface, $autoload)) { - return true; - } - } - return class_exists($this->interface, $autoload); - } - - /** - * Gets the list of methods on a class or - * interface. - * @returns array List of method names. - * @access public - */ - function getMethods() { - return array_unique(get_class_methods($this->interface)); - } - - /** - * Gets the list of interfaces from a class. If the - * class name is actually an interface then just that - * interface is returned. - * @returns array List of interfaces. - * @access public - */ - function getInterfaces() { - $reflection = new ReflectionClass($this->interface); - if ($reflection->isInterface()) { - return array($this->interface); - } - return $this->onlyParents($reflection->getInterfaces()); - } - - /** - * Gets the list of methods for the implemented - * interfaces only. - * @returns array List of enforced method signatures. - * @access public - */ - function getInterfaceMethods() { - $methods = array(); - foreach ($this->getInterfaces() as $interface) { - $methods = array_merge($methods, get_class_methods($interface)); - } - return array_unique($methods); - } - - /** - * Checks to see if the method signature has to be tightly - * specified. - * @param string $method Method name. - * @returns boolean True if enforced. - * @access private - */ - protected function isInterfaceMethod($method) { - return in_array($method, $this->getInterfaceMethods()); - } - - /** - * Finds the parent class name. - * @returns string Parent class name. - * @access public - */ - function getParent() { - $reflection = new ReflectionClass($this->interface); - $parent = $reflection->getParentClass(); - if ($parent) { - return $parent->getName(); - } - return false; - } - - /** - * Trivially determines if the class is abstract. - * @returns boolean True if abstract. - * @access public - */ - function isAbstract() { - $reflection = new ReflectionClass($this->interface); - return $reflection->isAbstract(); - } - - /** - * Trivially determines if the class is an interface. - * @returns boolean True if interface. - * @access public - */ - function isInterface() { - $reflection = new ReflectionClass($this->interface); - return $reflection->isInterface(); - } - - /** - * Scans for final methods, as they screw up inherited - * mocks by not allowing you to override them. - * @returns boolean True if the class has a final method. - * @access public - */ - function hasFinal() { - $reflection = new ReflectionClass($this->interface); - foreach ($reflection->getMethods() as $method) { - if ($method->isFinal()) { - return true; - } - } - return false; - } - - /** - * Whittles a list of interfaces down to only the - * necessary top level parents. - * @param array $interfaces Reflection API interfaces - * to reduce. - * @returns array List of parent interface names. - * @access private - */ - protected function onlyParents($interfaces) { - $parents = array(); - $blacklist = array(); - foreach ($interfaces as $interface) { - foreach($interfaces as $possible_parent) { - if ($interface->getName() == $possible_parent->getName()) { - continue; - } - if ($interface->isSubClassOf($possible_parent)) { - $blacklist[$possible_parent->getName()] = true; - } - } - if (!isset($blacklist[$interface->getName()])) { - $parents[] = $interface->getName(); - } - } - return $parents; - } - - /** - * Checks whether a method is abstract or not. - * @param string $name Method name. - * @return bool true if method is abstract, else false - * @access private - */ - protected function isAbstractMethod($name) { - $interface = new ReflectionClass($this->interface); - if (! $interface->hasMethod($name)) { - return false; - } - return $interface->getMethod($name)->isAbstract(); - } - - /** - * Checks whether a method is the constructor. - * @param string $name Method name. - * @return bool true if method is the constructor - * @access private - */ - protected function isConstructor($name) { - return ($name == '__construct') || ($name == $this->interface); - } - - /** - * Checks whether a method is abstract in all parents or not. - * @param string $name Method name. - * @return bool true if method is abstract in parent, else false - * @access private - */ - protected function isAbstractMethodInParents($name) { - $interface = new ReflectionClass($this->interface); - $parent = $interface->getParentClass(); - while($parent) { - if (! $parent->hasMethod($name)) { - return false; - } - if ($parent->getMethod($name)->isAbstract()) { - return true; - } - $parent = $parent->getParentClass(); - } - return false; - } - - /** - * Checks whether a method is static or not. - * @param string $name Method name - * @return bool true if method is static, else false - * @access private - */ - protected function isStaticMethod($name) { - $interface = new ReflectionClass($this->interface); - if (! $interface->hasMethod($name)) { - return false; - } - return $interface->getMethod($name)->isStatic(); - } - - /** - * Writes the source code matching the declaration - * of a method. - * @param string $name Method name. - * @return string Method signature up to last - * bracket. - * @access public - */ - function getSignature($name) { - if ($name == '__set') { - return 'function __set($key, $value)'; - } - if ($name == '__call') { - return 'function __call($method, $arguments)'; - } - if (version_compare(phpversion(), '5.1.0', '>=')) { - if (in_array($name, array('__get', '__isset', $name == '__unset'))) { - return "function {$name}(\$key)"; - } - } - if ($name == '__toString') { - return "function $name()"; - } - - // This wonky try-catch is a work around for a faulty method_exists() - // in early versions of PHP 5 which would return false for static - // methods. The Reflection classes work fine, but hasMethod() - // doesn't exist prior to PHP 5.1.0, so we need to use a more crude - // detection method. - try { - $interface = new ReflectionClass($this->interface); - $interface->getMethod($name); - } catch (ReflectionException $e) { - return "function $name()"; - } - return $this->getFullSignature($name); - } - - /** - * For a signature specified in an interface, full - * details must be replicated to be a valid implementation. - * @param string $name Method name. - * @return string Method signature up to last - * bracket. - * @access private - */ - protected function getFullSignature($name) { - $interface = new ReflectionClass($this->interface); - $method = $interface->getMethod($name); - $reference = $method->returnsReference() ? '&' : ''; - $static = $method->isStatic() ? 'static ' : ''; - return "{$static}function $reference$name(" . - implode(', ', $this->getParameterSignatures($method)) . - ")"; - } - - /** - * Gets the source code for each parameter. - * @param ReflectionMethod $method Method object from - * reflection API - * @return array List of strings, each - * a snippet of code. - * @access private - */ - protected function getParameterSignatures($method) { - $signatures = array(); - foreach ($method->getParameters() as $parameter) { - $signature = ''; - $type = $parameter->getClass(); - if (is_null($type) && version_compare(phpversion(), '5.1.0', '>=') && $parameter->isArray()) { - $signature .= 'array '; - } elseif (!is_null($type)) { - $signature .= $type->getName() . ' '; - } - if ($parameter->isPassedByReference()) { - $signature .= '&'; - } - $signature .= '$' . $this->suppressSpurious($parameter->getName()); - if ($this->isOptional($parameter)) { - $signature .= ' = null'; - } - $signatures[] = $signature; - } - return $signatures; - } - - /** - * The SPL library has problems with the - * Reflection library. In particular, you can - * get extra characters in parameter names :(. - * @param string $name Parameter name. - * @return string Cleaner name. - * @access private - */ - protected function suppressSpurious($name) { - return str_replace(array('[', ']', ' '), '', $name); - } - - /** - * Test of a reflection parameter being optional - * that works with early versions of PHP5. - * @param reflectionParameter $parameter Is this optional. - * @return boolean True if optional. - * @access private - */ - protected function isOptional($parameter) { - if (method_exists($parameter, 'isOptional')) { - return $parameter->isOptional(); - } - return false; - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/remote.php b/lib/simpletestlib/remote.php deleted file mode 100644 index 4bb37b7c51b..00000000000 --- a/lib/simpletestlib/remote.php +++ /dev/null @@ -1,115 +0,0 @@ -url = $url; - $this->dry_url = $dry_url ? $dry_url : $url; - $this->size = false; - } - - /** - * Accessor for the test name for subclasses. - * @return string Name of the test. - * @access public - */ - function getLabel() { - return $this->url; - } - - /** - * Runs the top level test for this class. Currently - * reads the data as a single chunk. I'll fix this - * once I have added iteration to the browser. - * @param SimpleReporter $reporter Target of test results. - * @returns boolean True if no failures. - * @access public - */ - function run($reporter) { - $browser = $this->createBrowser(); - $xml = $browser->get($this->url); - if (! $xml) { - trigger_error('Cannot read remote test URL [' . $this->url . ']'); - return false; - } - $parser = $this->createParser($reporter); - if (! $parser->parse($xml)) { - trigger_error('Cannot parse incoming XML from [' . $this->url . ']'); - return false; - } - return true; - } - - /** - * Creates a new web browser object for fetching - * the XML report. - * @return SimpleBrowser New browser. - * @access protected - */ - protected function createBrowser() { - return new SimpleBrowser(); - } - - /** - * Creates the XML parser. - * @param SimpleReporter $reporter Target of test results. - * @return SimpleTestXmlListener XML reader. - * @access protected - */ - protected function createParser($reporter) { - return new SimpleTestXmlParser($reporter); - } - - /** - * Accessor for the number of subtests. - * @return integer Number of test cases. - * @access public - */ - function getSize() { - if ($this->size === false) { - $browser = $this->createBrowser(); - $xml = $browser->get($this->dry_url); - if (! $xml) { - trigger_error('Cannot read remote test URL [' . $this->dry_url . ']'); - return false; - } - $reporter = new SimpleReporter(); - $parser = $this->createParser($reporter); - if (! $parser->parse($xml)) { - trigger_error('Cannot parse incoming XML from [' . $this->dry_url . ']'); - return false; - } - $this->size = $reporter->getTestCaseCount(); - } - return $this->size; - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/reporter.php b/lib/simpletestlib/reporter.php deleted file mode 100644 index bd4f3fa41dd..00000000000 --- a/lib/simpletestlib/reporter.php +++ /dev/null @@ -1,445 +0,0 @@ -character_set = $character_set; - } - - /** - * Paints the top of the web page setting the - * title to the name of the starting test. - * @param string $test_name Name class of test. - * @access public - */ - function paintHeader($test_name) { - $this->sendNoCacheHeaders(); - print ""; - print "\n\n$test_name\n"; - print "\n"; - print "\n"; - print "\n\n"; - print "

    $test_name

    \n"; - flush(); - } - - /** - * Send the headers necessary to ensure the page is - * reloaded on every request. Otherwise you could be - * scratching your head over out of date test data. - * @access public - */ - static function sendNoCacheHeaders() { - if (! headers_sent()) { - header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); - } - } - - /** - * Paints the CSS. Add additional styles here. - * @return string CSS code as text. - * @access protected - */ - protected function getCss() { - return ".fail { background-color: inherit; color: red; }" . - ".pass { background-color: inherit; color: green; }" . - " pre { background-color: lightgray; color: inherit; }"; - } - - /** - * Paints the end of the test with a summary of - * the passes and failures. - * @param string $test_name Name class of test. - * @access public - */ - function paintFooter($test_name) { - $colour = ($this->getFailCount() + $this->getExceptionCount() > 0 ? "red" : "green"); - print "
    "; - print $this->getTestCaseProgress() . "/" . $this->getTestCaseCount(); - print " test cases complete:\n"; - print "" . $this->getPassCount() . " passes, "; - print "" . $this->getFailCount() . " fails and "; - print "" . $this->getExceptionCount() . " exceptions."; - print "
    \n"; - print "\n\n"; - } - - /** - * Paints the test failure with a breadcrumbs - * trail of the nesting test suites below the - * top level test. - * @param string $message Failure message displayed in - * the context of the other tests. - */ - function paintFail($message) { - parent::paintFail($message); - print "Fail: "; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - print implode(" -> ", $breadcrumb); - print " -> " . $this->htmlEntities($message) . "
    \n"; - } - - /** - * Paints a PHP error. - * @param string $message Message is ignored. - * @access public - */ - function paintError($message) { - parent::paintError($message); - print "Exception: "; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - print implode(" -> ", $breadcrumb); - print " -> " . $this->htmlEntities($message) . "
    \n"; - } - - /** - * Paints a PHP exception. - * @param Exception $exception Exception to display. - * @access public - */ - function paintException($exception) { - parent::paintException($exception); - print "Exception: "; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - print implode(" -> ", $breadcrumb); - $message = 'Unexpected exception of type [' . get_class($exception) . - '] with message ['. $exception->getMessage() . - '] in ['. $exception->getFile() . - ' line ' . $exception->getLine() . ']'; - print " -> " . $this->htmlEntities($message) . "
    \n"; - } - - /** - * Prints the message for skipping tests. - * @param string $message Text of skip condition. - * @access public - */ - function paintSkip($message) { - parent::paintSkip($message); - print "Skipped: "; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - print implode(" -> ", $breadcrumb); - print " -> " . $this->htmlEntities($message) . "
    \n"; - } - - /** - * Paints formatted text such as dumped privateiables. - * @param string $message Text to show. - * @access public - */ - function paintFormattedMessage($message) { - print '
    ' . $this->htmlEntities($message) . '
    '; - } - - /** - * Character set adjusted entity conversion. - * @param string $message Plain text or Unicode message. - * @return string Browser readable message. - * @access protected - */ - protected function htmlEntities($message) { - return htmlentities($message, ENT_COMPAT, $this->character_set); - } -} - -/** - * Sample minimal test displayer. Generates only - * failure messages and a pass count. For command - * line use. I've tried to make it look like JUnit, - * but I wanted to output the errors as they arrived - * which meant dropping the dots. - * @package SimpleTest - * @subpackage UnitTester - */ -class TextReporter extends SimpleReporter { - - /** - * Does nothing yet. The first output will - * be sent on the first test start. - */ - function __construct() { - parent::__construct(); - } - - /** - * Paints the title only. - * @param string $test_name Name class of test. - * @access public - */ - function paintHeader($test_name) { - if (! SimpleReporter::inCli()) { - header('Content-type: text/plain'); - } - print "$test_name\n"; - flush(); - } - - /** - * Paints the end of the test with a summary of - * the passes and failures. - * @param string $test_name Name class of test. - * @access public - */ - function paintFooter($test_name) { - if ($this->getFailCount() + $this->getExceptionCount() == 0) { - print "OK\n"; - } else { - print "FAILURES!!!\n"; - } - print "Test cases run: " . $this->getTestCaseProgress() . - "/" . $this->getTestCaseCount() . - ", Passes: " . $this->getPassCount() . - ", Failures: " . $this->getFailCount() . - ", Exceptions: " . $this->getExceptionCount() . "\n"; - } - - /** - * Paints the test failure as a stack trace. - * @param string $message Failure message displayed in - * the context of the other tests. - * @access public - */ - function paintFail($message) { - parent::paintFail($message); - print $this->getFailCount() . ") $message\n"; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); - print "\n"; - } - - /** - * Paints a PHP error or exception. - * @param string $message Message to be shown. - * @access public - * @abstract - */ - function paintError($message) { - parent::paintError($message); - print "Exception " . $this->getExceptionCount() . "!\n$message\n"; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); - print "\n"; - } - - /** - * Paints a PHP error or exception. - * @param Exception $exception Exception to describe. - * @access public - * @abstract - */ - function paintException($exception) { - parent::paintException($exception); - $message = 'Unexpected exception of type [' . get_class($exception) . - '] with message ['. $exception->getMessage() . - '] in ['. $exception->getFile() . - ' line ' . $exception->getLine() . ']'; - print "Exception " . $this->getExceptionCount() . "!\n$message\n"; - $breadcrumb = $this->getTestList(); - array_shift($breadcrumb); - print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); - print "\n"; - } - - /** - * Prints the message for skipping tests. - * @param string $message Text of skip condition. - * @access public - */ - function paintSkip($message) { - parent::paintSkip($message); - print "Skip: $message\n"; - } - - /** - * Paints formatted text such as dumped privateiables. - * @param string $message Text to show. - * @access public - */ - function paintFormattedMessage($message) { - print "$message\n"; - flush(); - } -} - -/** - * Runs just a single test group, a single case or - * even a single test within that case. - * @package SimpleTest - * @subpackage UnitTester - */ -class SelectiveReporter extends SimpleReporterDecorator { - private $just_this_case = false; - private $just_this_test = false; - private $on; - - /** - * Selects the test case or group to be run, - * and optionally a specific test. - * @param SimpleScorer $reporter Reporter to receive events. - * @param string $just_this_case Only this case or group will run. - * @param string $just_this_test Only this test method will run. - */ - function __construct($reporter, $just_this_case = false, $just_this_test = false) { - if (isset($just_this_case) && $just_this_case) { - $this->just_this_case = strtolower($just_this_case); - $this->off(); - } else { - $this->on(); - } - if (isset($just_this_test) && $just_this_test) { - $this->just_this_test = strtolower($just_this_test); - } - parent::__construct($reporter); - } - - /** - * Compares criteria to actual the case/group name. - * @param string $test_case The incoming test. - * @return boolean True if matched. - * @access protected - */ - protected function matchesTestCase($test_case) { - return $this->just_this_case == strtolower($test_case); - } - - /** - * Compares criteria to actual the test name. If no - * name was specified at the beginning, then all tests - * can run. - * @param string $method The incoming test method. - * @return boolean True if matched. - * @access protected - */ - protected function shouldRunTest($test_case, $method) { - if ($this->isOn() || $this->matchesTestCase($test_case)) { - if ($this->just_this_test) { - return $this->just_this_test == strtolower($method); - } else { - return true; - } - } - return false; - } - - /** - * Switch on testing for the group or subgroup. - * @access private - */ - protected function on() { - $this->on = true; - } - - /** - * Switch off testing for the group or subgroup. - * @access private - */ - protected function off() { - $this->on = false; - } - - /** - * Is this group actually being tested? - * @return boolean True if the current test group is active. - * @access private - */ - protected function isOn() { - return $this->on; - } - - /** - * Veto everything that doesn't match the method wanted. - * @param string $test_case Name of test case. - * @param string $method Name of test method. - * @return boolean True if test should be run. - * @access public - */ - function shouldInvoke($test_case, $method) { - if ($this->shouldRunTest($test_case, $method)) { - return $this->reporter->shouldInvoke($test_case, $method); - } - return false; - } - - /** - * Paints the start of a group test. - * @param string $test_case Name of test or other label. - * @param integer $size Number of test cases starting. - * @access public - */ - function paintGroupStart($test_case, $size) { - if ($this->just_this_case && $this->matchesTestCase($test_case)) { - $this->on(); - } - $this->reporter->paintGroupStart($test_case, $size); - } - - /** - * Paints the end of a group test. - * @param string $test_case Name of test or other label. - * @access public - */ - function paintGroupEnd($test_case) { - $this->reporter->paintGroupEnd($test_case); - if ($this->just_this_case && $this->matchesTestCase($test_case)) { - $this->off(); - } - } -} - -/** - * Suppresses skip messages. - * @package SimpleTest - * @subpackage UnitTester - */ -class NoSkipsReporter extends SimpleReporterDecorator { - - /** - * Does nothing. - * @param string $message Text of skip condition. - * @access public - */ - function paintSkip($message) { } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/scorer.php b/lib/simpletestlib/scorer.php deleted file mode 100644 index 27776f4b631..00000000000 --- a/lib/simpletestlib/scorer.php +++ /dev/null @@ -1,875 +0,0 @@ -passes = 0; - $this->fails = 0; - $this->exceptions = 0; - $this->is_dry_run = false; - } - - /** - * Signals that the next evaluation will be a dry - * run. That is, the structure events will be - * recorded, but no tests will be run. - * @param boolean $is_dry Dry run if true. - * @access public - */ - function makeDry($is_dry = true) { - $this->is_dry_run = $is_dry; - } - - /** - * The reporter has a veto on what should be run. - * @param string $test_case_name name of test case. - * @param string $method Name of test method. - * @access public - */ - function shouldInvoke($test_case_name, $method) { - return ! $this->is_dry_run; - } - - /** - * Can wrap the invoker in preperation for running - * a test. - * @param SimpleInvoker $invoker Individual test runner. - * @return SimpleInvoker Wrapped test runner. - * @access public - */ - function createInvoker($invoker) { - return $invoker; - } - - /** - * Accessor for current status. Will be false - * if there have been any failures or exceptions. - * Used for command line tools. - * @return boolean True if no failures. - * @access public - */ - function getStatus() { - if ($this->exceptions + $this->fails > 0) { - return false; - } - return true; - } - - /** - * Paints the start of a group test. - * @param string $test_name Name of test or other label. - * @param integer $size Number of test cases starting. - * @access public - */ - function paintGroupStart($test_name, $size) { - } - - /** - * Paints the end of a group test. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintGroupEnd($test_name) { - } - - /** - * Paints the start of a test case. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintCaseStart($test_name) { - } - - /** - * Paints the end of a test case. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintCaseEnd($test_name) { - } - - /** - * Paints the start of a test method. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintMethodStart($test_name) { - } - - /** - * Paints the end of a test method. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintMethodEnd($test_name) { - } - - /** - * Increments the pass count. - * @param string $message Message is ignored. - * @access public - */ - function paintPass($message) { - $this->passes++; - } - - /** - * Increments the fail count. - * @param string $message Message is ignored. - * @access public - */ - function paintFail($message) { - $this->fails++; - } - - /** - * Deals with PHP 4 throwing an error. - * @param string $message Text of error formatted by - * the test case. - * @access public - */ - function paintError($message) { - $this->exceptions++; - } - - /** - * Deals with PHP 5 throwing an exception. - * @param Exception $exception The actual exception thrown. - * @access public - */ - function paintException($exception) { - $this->exceptions++; - } - - /** - * Prints the message for skipping tests. - * @param string $message Text of skip condition. - * @access public - */ - function paintSkip($message) { - } - - /** - * Accessor for the number of passes so far. - * @return integer Number of passes. - * @access public - */ - function getPassCount() { - return $this->passes; - } - - /** - * Accessor for the number of fails so far. - * @return integer Number of fails. - * @access public - */ - function getFailCount() { - return $this->fails; - } - - /** - * Accessor for the number of untrapped errors - * so far. - * @return integer Number of exceptions. - * @access public - */ - function getExceptionCount() { - return $this->exceptions; - } - - /** - * Paints a simple supplementary message. - * @param string $message Text to display. - * @access public - */ - function paintMessage($message) { - } - - /** - * Paints a formatted ASCII message such as a - * privateiable dump. - * @param string $message Text to display. - * @access public - */ - function paintFormattedMessage($message) { - } - - /** - * By default just ignores user generated events. - * @param string $type Event type as text. - * @param mixed $payload Message or object. - * @access public - */ - function paintSignal($type, $payload) { - } -} - -/** - * Recipient of generated test messages that can display - * page footers and headers. Also keeps track of the - * test nesting. This is the main base class on which - * to build the finished test (page based) displays. - * @package SimpleTest - * @subpackage UnitTester - */ -class SimpleReporter extends SimpleScorer { - private $test_stack; - private $size; - private $progress; - - /** - * Starts the display with no results in. - * @access public - */ - function __construct() { - parent::__construct(); - $this->test_stack = array(); - $this->size = null; - $this->progress = 0; - } - - /** - * Gets the formatter for small generic data items. - * @return SimpleDumper Formatter. - * @access public - */ - function getDumper() { - return new SimpleDumper(); - } - - /** - * Paints the start of a group test. Will also paint - * the page header and footer if this is the - * first test. Will stash the size if the first - * start. - * @param string $test_name Name of test that is starting. - * @param integer $size Number of test cases starting. - * @access public - */ - function paintGroupStart($test_name, $size) { - if (! isset($this->size)) { - $this->size = $size; - } - if (count($this->test_stack) == 0) { - $this->paintHeader($test_name); - } - $this->test_stack[] = $test_name; - } - - /** - * Paints the end of a group test. Will paint the page - * footer if the stack of tests has unwound. - * @param string $test_name Name of test that is ending. - * @param integer $progress Number of test cases ending. - * @access public - */ - function paintGroupEnd($test_name) { - array_pop($this->test_stack); - if (count($this->test_stack) == 0) { - $this->paintFooter($test_name); - } - } - - /** - * Paints the start of a test case. Will also paint - * the page header and footer if this is the - * first test. Will stash the size if the first - * start. - * @param string $test_name Name of test that is starting. - * @access public - */ - function paintCaseStart($test_name) { - if (! isset($this->size)) { - $this->size = 1; - } - if (count($this->test_stack) == 0) { - $this->paintHeader($test_name); - } - $this->test_stack[] = $test_name; - } - - /** - * Paints the end of a test case. Will paint the page - * footer if the stack of tests has unwound. - * @param string $test_name Name of test that is ending. - * @access public - */ - function paintCaseEnd($test_name) { - $this->progress++; - array_pop($this->test_stack); - if (count($this->test_stack) == 0) { - $this->paintFooter($test_name); - } - } - - /** - * Paints the start of a test method. - * @param string $test_name Name of test that is starting. - * @access public - */ - function paintMethodStart($test_name) { - $this->test_stack[] = $test_name; - } - - /** - * Paints the end of a test method. Will paint the page - * footer if the stack of tests has unwound. - * @param string $test_name Name of test that is ending. - * @access public - */ - function paintMethodEnd($test_name) { - array_pop($this->test_stack); - } - - /** - * Paints the test document header. - * @param string $test_name First test top level - * to start. - * @access public - * @abstract - */ - function paintHeader($test_name) { - } - - /** - * Paints the test document footer. - * @param string $test_name The top level test. - * @access public - * @abstract - */ - function paintFooter($test_name) { - } - - /** - * Accessor for internal test stack. For - * subclasses that need to see the whole test - * history for display purposes. - * @return array List of methods in nesting order. - * @access public - */ - function getTestList() { - return $this->test_stack; - } - - /** - * Accessor for total test size in number - * of test cases. Null until the first - * test is started. - * @return integer Total number of cases at start. - * @access public - */ - function getTestCaseCount() { - return $this->size; - } - - /** - * Accessor for the number of test cases - * completed so far. - * @return integer Number of ended cases. - * @access public - */ - function getTestCaseProgress() { - return $this->progress; - } - - /** - * Static check for running in the comand line. - * @return boolean True if CLI. - * @access public - */ - static function inCli() { - return php_sapi_name() == 'cli'; - } -} - -/** - * For modifying the behaviour of the visual reporters. - * @package SimpleTest - * @subpackage UnitTester - */ -class SimpleReporterDecorator { - protected $reporter; - - /** - * Mediates between the reporter and the test case. - * @param SimpleScorer $reporter Reporter to receive events. - */ - function __construct($reporter) { - $this->reporter = $reporter; - } - - /** - * Signals that the next evaluation will be a dry - * run. That is, the structure events will be - * recorded, but no tests will be run. - * @param boolean $is_dry Dry run if true. - * @access public - */ - function makeDry($is_dry = true) { - $this->reporter->makeDry($is_dry); - } - - /** - * Accessor for current status. Will be false - * if there have been any failures or exceptions. - * Used for command line tools. - * @return boolean True if no failures. - * @access public - */ - function getStatus() { - return $this->reporter->getStatus(); - } - - /** - * The nesting of the test cases so far. Not - * all reporters have this facility. - * @return array Test list if accessible. - * @access public - */ - function getTestList() { - if (method_exists($this->reporter, 'getTestList')) { - return $this->reporter->getTestList(); - } else { - return array(); - } - } - - /** - * The reporter has a veto on what should be run. - * @param string $test_case_name Name of test case. - * @param string $method Name of test method. - * @return boolean True if test should be run. - * @access public - */ - function shouldInvoke($test_case_name, $method) { - return $this->reporter->shouldInvoke($test_case_name, $method); - } - - /** - * Can wrap the invoker in preparation for running - * a test. - * @param SimpleInvoker $invoker Individual test runner. - * @return SimpleInvoker Wrapped test runner. - * @access public - */ - function createInvoker($invoker) { - return $this->reporter->createInvoker($invoker); - } - - /** - * Gets the formatter for privateiables and other small - * generic data items. - * @return SimpleDumper Formatter. - * @access public - */ - function getDumper() { - return $this->reporter->getDumper(); - } - - /** - * Paints the start of a group test. - * @param string $test_name Name of test or other label. - * @param integer $size Number of test cases starting. - * @access public - */ - function paintGroupStart($test_name, $size) { - $this->reporter->paintGroupStart($test_name, $size); - } - - /** - * Paints the end of a group test. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintGroupEnd($test_name) { - $this->reporter->paintGroupEnd($test_name); - } - - /** - * Paints the start of a test case. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintCaseStart($test_name) { - $this->reporter->paintCaseStart($test_name); - } - - /** - * Paints the end of a test case. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintCaseEnd($test_name) { - $this->reporter->paintCaseEnd($test_name); - } - - /** - * Paints the start of a test method. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintMethodStart($test_name) { - $this->reporter->paintMethodStart($test_name); - } - - /** - * Paints the end of a test method. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintMethodEnd($test_name) { - $this->reporter->paintMethodEnd($test_name); - } - - /** - * Chains to the wrapped reporter. - * @param string $message Message is ignored. - * @access public - */ - function paintPass($message) { - $this->reporter->paintPass($message); - } - - /** - * Chains to the wrapped reporter. - * @param string $message Message is ignored. - * @access public - */ - function paintFail($message) { - $this->reporter->paintFail($message); - } - - /** - * Chains to the wrapped reporter. - * @param string $message Text of error formatted by - * the test case. - * @access public - */ - function paintError($message) { - $this->reporter->paintError($message); - } - - /** - * Chains to the wrapped reporter. - * @param Exception $exception Exception to show. - * @access public - */ - function paintException($exception) { - $this->reporter->paintException($exception); - } - - /** - * Prints the message for skipping tests. - * @param string $message Text of skip condition. - * @access public - */ - function paintSkip($message) { - $this->reporter->paintSkip($message); - } - - /** - * Chains to the wrapped reporter. - * @param string $message Text to display. - * @access public - */ - function paintMessage($message) { - $this->reporter->paintMessage($message); - } - - /** - * Chains to the wrapped reporter. - * @param string $message Text to display. - * @access public - */ - function paintFormattedMessage($message) { - $this->reporter->paintFormattedMessage($message); - } - - /** - * Chains to the wrapped reporter. - * @param string $type Event type as text. - * @param mixed $payload Message or object. - * @return boolean Should return false if this - * type of signal should fail the - * test suite. - * @access public - */ - function paintSignal($type, $payload) { - $this->reporter->paintSignal($type, $payload); - } -} - -/** - * For sending messages to multiple reporters at - * the same time. - * @package SimpleTest - * @subpackage UnitTester - */ -class MultipleReporter { - private $reporters = array(); - - /** - * Adds a reporter to the subscriber list. - * @param SimpleScorer $reporter Reporter to receive events. - * @access public - */ - function attachReporter($reporter) { - $this->reporters[] = $reporter; - } - - /** - * Signals that the next evaluation will be a dry - * run. That is, the structure events will be - * recorded, but no tests will be run. - * @param boolean $is_dry Dry run if true. - * @access public - */ - function makeDry($is_dry = true) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->makeDry($is_dry); - } - } - - /** - * Accessor for current status. Will be false - * if there have been any failures or exceptions. - * If any reporter reports a failure, the whole - * suite fails. - * @return boolean True if no failures. - * @access public - */ - function getStatus() { - for ($i = 0; $i < count($this->reporters); $i++) { - if (! $this->reporters[$i]->getStatus()) { - return false; - } - } - return true; - } - - /** - * The reporter has a veto on what should be run. - * It requires all reporters to want to run the method. - * @param string $test_case_name name of test case. - * @param string $method Name of test method. - * @access public - */ - function shouldInvoke($test_case_name, $method) { - for ($i = 0; $i < count($this->reporters); $i++) { - if (! $this->reporters[$i]->shouldInvoke($test_case_name, $method)) { - return false; - } - } - return true; - } - - /** - * Every reporter gets a chance to wrap the invoker. - * @param SimpleInvoker $invoker Individual test runner. - * @return SimpleInvoker Wrapped test runner. - * @access public - */ - function createInvoker($invoker) { - for ($i = 0; $i < count($this->reporters); $i++) { - $invoker = $this->reporters[$i]->createInvoker($invoker); - } - return $invoker; - } - - /** - * Gets the formatter for privateiables and other small - * generic data items. - * @return SimpleDumper Formatter. - * @access public - */ - function getDumper() { - return new SimpleDumper(); - } - - /** - * Paints the start of a group test. - * @param string $test_name Name of test or other label. - * @param integer $size Number of test cases starting. - * @access public - */ - function paintGroupStart($test_name, $size) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintGroupStart($test_name, $size); - } - } - - /** - * Paints the end of a group test. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintGroupEnd($test_name) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintGroupEnd($test_name); - } - } - - /** - * Paints the start of a test case. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintCaseStart($test_name) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintCaseStart($test_name); - } - } - - /** - * Paints the end of a test case. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintCaseEnd($test_name) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintCaseEnd($test_name); - } - } - - /** - * Paints the start of a test method. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintMethodStart($test_name) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintMethodStart($test_name); - } - } - - /** - * Paints the end of a test method. - * @param string $test_name Name of test or other label. - * @access public - */ - function paintMethodEnd($test_name) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintMethodEnd($test_name); - } - } - - /** - * Chains to the wrapped reporter. - * @param string $message Message is ignored. - * @access public - */ - function paintPass($message) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintPass($message); - } - } - - /** - * Chains to the wrapped reporter. - * @param string $message Message is ignored. - * @access public - */ - function paintFail($message) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintFail($message); - } - } - - /** - * Chains to the wrapped reporter. - * @param string $message Text of error formatted by - * the test case. - * @access public - */ - function paintError($message) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintError($message); - } - } - - /** - * Chains to the wrapped reporter. - * @param Exception $exception Exception to display. - * @access public - */ - function paintException($exception) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintException($exception); - } - } - - /** - * Prints the message for skipping tests. - * @param string $message Text of skip condition. - * @access public - */ - function paintSkip($message) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintSkip($message); - } - } - - /** - * Chains to the wrapped reporter. - * @param string $message Text to display. - * @access public - */ - function paintMessage($message) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintMessage($message); - } - } - - /** - * Chains to the wrapped reporter. - * @param string $message Text to display. - * @access public - */ - function paintFormattedMessage($message) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintFormattedMessage($message); - } - } - - /** - * Chains to the wrapped reporter. - * @param string $type Event type as text. - * @param mixed $payload Message or object. - * @return boolean Should return false if this - * type of signal should fail the - * test suite. - * @access public - */ - function paintSignal($type, $payload) { - for ($i = 0; $i < count($this->reporters); $i++) { - $this->reporters[$i]->paintSignal($type, $payload); - } - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/selector.php b/lib/simpletestlib/selector.php deleted file mode 100644 index ba2fed312a8..00000000000 --- a/lib/simpletestlib/selector.php +++ /dev/null @@ -1,141 +0,0 @@ -name = $name; - } - - /** - * Accessor for name. - * @returns string $name Name to match. - */ - function getName() { - return $this->name; - } - - /** - * Compares with name attribute of widget. - * @param SimpleWidget $widget Control to compare. - * @access public - */ - function isMatch($widget) { - return ($widget->getName() == $this->name); - } -} - -/** - * Used to extract form elements for testing against. - * Searches by visible label or alt text. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleByLabel { - private $label; - - /** - * Stashes the name for later comparison. - * @param string $label Visible text to match. - */ - function __construct($label) { - $this->label = $label; - } - - /** - * Comparison. Compares visible text of widget or - * related label. - * @param SimpleWidget $widget Control to compare. - * @access public - */ - function isMatch($widget) { - if (! method_exists($widget, 'isLabel')) { - return false; - } - return $widget->isLabel($this->label); - } -} - -/** - * Used to extract form elements for testing against. - * Searches dy id attribute. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleById { - private $id; - - /** - * Stashes the name for later comparison. - * @param string $id ID atribute to match. - */ - function __construct($id) { - $this->id = $id; - } - - /** - * Comparison. Compares id attribute of widget. - * @param SimpleWidget $widget Control to compare. - * @access public - */ - function isMatch($widget) { - return $widget->isId($this->id); - } -} - -/** - * Used to extract form elements for testing against. - * Searches by visible label, name or alt text. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleByLabelOrName { - private $label; - - /** - * Stashes the name/label for later comparison. - * @param string $label Visible text to match. - */ - function __construct($label) { - $this->label = $label; - } - - /** - * Comparison. Compares visible text of widget or - * related label or name. - * @param SimpleWidget $widget Control to compare. - * @access public - */ - function isMatch($widget) { - if (method_exists($widget, 'isLabel')) { - if ($widget->isLabel($this->label)) { - return true; - } - } - return ($widget->getName() == $this->label); - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/shell_tester.php b/lib/simpletestlib/shell_tester.php deleted file mode 100644 index 9a3bd389eeb..00000000000 --- a/lib/simpletestlib/shell_tester.php +++ /dev/null @@ -1,330 +0,0 @@ -output = false; - } - - /** - * Actually runs the command. Does not trap the - * error stream output as this need PHP 4.3+. - * @param string $command The actual command line - * to run. - * @return integer Exit code. - * @access public - */ - function execute($command) { - $this->output = false; - exec($command, $this->output, $ret); - return $ret; - } - - /** - * Accessor for the last output. - * @return string Output as text. - * @access public - */ - function getOutput() { - return implode("\n", $this->output); - } - - /** - * Accessor for the last output. - * @return array Output as array of lines. - * @access public - */ - function getOutputAsList() { - return $this->output; - } -} - -/** - * Test case for testing of command line scripts and - * utilities. Usually scripts that are external to the - * PHP code, but support it in some way. - * @package SimpleTest - * @subpackage UnitTester - */ -class ShellTestCase extends SimpleTestCase { - private $current_shell; - private $last_status; - private $last_command; - - /** - * Creates an empty test case. Should be subclassed - * with test methods for a functional test case. - * @param string $label Name of test case. Will use - * the class name if none specified. - * @access public - */ - function __construct($label = false) { - parent::__construct($label); - $this->current_shell = $this->createShell(); - $this->last_status = false; - $this->last_command = ''; - } - - /** - * Executes a command and buffers the results. - * @param string $command Command to run. - * @return boolean True if zero exit code. - * @access public - */ - function execute($command) { - $shell = $this->getShell(); - $this->last_status = $shell->execute($command); - $this->last_command = $command; - return ($this->last_status === 0); - } - - /** - * Dumps the output of the last command. - * @access public - */ - function dumpOutput() { - $this->dump($this->getOutput()); - } - - /** - * Accessor for the last output. - * @return string Output as text. - * @access public - */ - function getOutput() { - $shell = $this->getShell(); - return $shell->getOutput(); - } - - /** - * Accessor for the last output. - * @return array Output as array of lines. - * @access public - */ - function getOutputAsList() { - $shell = $this->getShell(); - return $shell->getOutputAsList(); - } - - /** - * Called from within the test methods to register - * passes and failures. - * @param boolean $result Pass on true. - * @param string $message Message to display describing - * the test state. - * @return boolean True on pass - * @access public - */ - function assertTrue($result, $message = false) { - return $this->assert(new TrueExpectation(), $result, $message); - } - - /** - * Will be true on false and vice versa. False - * is the PHP definition of false, so that null, - * empty strings, zero and an empty array all count - * as false. - * @param boolean $result Pass on false. - * @param string $message Message to display. - * @return boolean True on pass - * @access public - */ - function assertFalse($result, $message = '%s') { - return $this->assert(new FalseExpectation(), $result, $message); - } - - /** - * Will trigger a pass if the two parameters have - * the same value only. Otherwise a fail. This - * is for testing hand extracted text, etc. - * @param mixed $first Value to compare. - * @param mixed $second Value to compare. - * @param string $message Message to display. - * @return boolean True on pass - * @access public - */ - function assertEqual($first, $second, $message = "%s") { - return $this->assert( - new EqualExpectation($first), - $second, - $message); - } - - /** - * Will trigger a pass if the two parameters have - * a different value. Otherwise a fail. This - * is for testing hand extracted text, etc. - * @param mixed $first Value to compare. - * @param mixed $second Value to compare. - * @param string $message Message to display. - * @return boolean True on pass - * @access public - */ - function assertNotEqual($first, $second, $message = "%s") { - return $this->assert( - new NotEqualExpectation($first), - $second, - $message); - } - - /** - * Tests the last status code from the shell. - * @param integer $status Expected status of last - * command. - * @param string $message Message to display. - * @return boolean True if pass. - * @access public - */ - function assertExitCode($status, $message = "%s") { - $message = sprintf($message, "Expected status code of [$status] from [" . - $this->last_command . "], but got [" . - $this->last_status . "]"); - return $this->assertTrue($status === $this->last_status, $message); - } - - /** - * Attempt to exactly match the combined STDERR and - * STDOUT output. - * @param string $expected Expected output. - * @param string $message Message to display. - * @return boolean True if pass. - * @access public - */ - function assertOutput($expected, $message = "%s") { - $shell = $this->getShell(); - return $this->assert( - new EqualExpectation($expected), - $shell->getOutput(), - $message); - } - - /** - * Scans the output for a Perl regex. If found - * anywhere it passes, else it fails. - * @param string $pattern Regex to search for. - * @param string $message Message to display. - * @return boolean True if pass. - * @access public - */ - function assertOutputPattern($pattern, $message = "%s") { - $shell = $this->getShell(); - return $this->assert( - new PatternExpectation($pattern), - $shell->getOutput(), - $message); - } - - /** - * If a Perl regex is found anywhere in the current - * output then a failure is generated, else a pass. - * @param string $pattern Regex to search for. - * @param $message Message to display. - * @return boolean True if pass. - * @access public - */ - function assertNoOutputPattern($pattern, $message = "%s") { - $shell = $this->getShell(); - return $this->assert( - new NoPatternExpectation($pattern), - $shell->getOutput(), - $message); - } - - /** - * File existence check. - * @param string $path Full filename and path. - * @param string $message Message to display. - * @return boolean True if pass. - * @access public - */ - function assertFileExists($path, $message = "%s") { - $message = sprintf($message, "File [$path] should exist"); - return $this->assertTrue(file_exists($path), $message); - } - - /** - * File non-existence check. - * @param string $path Full filename and path. - * @param string $message Message to display. - * @return boolean True if pass. - * @access public - */ - function assertFileNotExists($path, $message = "%s") { - $message = sprintf($message, "File [$path] should not exist"); - return $this->assertFalse(file_exists($path), $message); - } - - /** - * Scans a file for a Perl regex. If found - * anywhere it passes, else it fails. - * @param string $pattern Regex to search for. - * @param string $path Full filename and path. - * @param string $message Message to display. - * @return boolean True if pass. - * @access public - */ - function assertFilePattern($pattern, $path, $message = "%s") { - return $this->assert( - new PatternExpectation($pattern), - implode('', file($path)), - $message); - } - - /** - * If a Perl regex is found anywhere in the named - * file then a failure is generated, else a pass. - * @param string $pattern Regex to search for. - * @param string $path Full filename and path. - * @param string $message Message to display. - * @return boolean True if pass. - * @access public - */ - function assertNoFilePattern($pattern, $path, $message = "%s") { - return $this->assert( - new NoPatternExpectation($pattern), - implode('', file($path)), - $message); - } - - /** - * Accessor for current shell. Used for testing the - * the tester itself. - * @return Shell Current shell. - * @access protected - */ - protected function getShell() { - return $this->current_shell; - } - - /** - * Factory for the shell to run the command on. - * @return Shell New shell object. - * @access protected - */ - protected function createShell() { - return new SimpleShell(); - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/simpletest.php b/lib/simpletestlib/simpletest.php deleted file mode 100644 index 425c869a825..00000000000 --- a/lib/simpletestlib/simpletest.php +++ /dev/null @@ -1,391 +0,0 @@ -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(); - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/socket.php b/lib/simpletestlib/socket.php deleted file mode 100644 index 06e8ca62d00..00000000000 --- a/lib/simpletestlib/socket.php +++ /dev/null @@ -1,312 +0,0 @@ -clearError(); - } - - /** - * Test for an outstanding error. - * @return boolean True if there is an error. - * @access public - */ - function isError() { - return ($this->error != ''); - } - - /** - * Accessor for an outstanding error. - * @return string Empty string if no error otherwise - * the error message. - * @access public - */ - function getError() { - return $this->error; - } - - /** - * Sets the internal error. - * @param string Error message to stash. - * @access protected - */ - function setError($error) { - $this->error = $error; - } - - /** - * Resets the error state to no error. - * @access protected - */ - function clearError() { - $this->setError(''); - } -} - -/** - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleFileSocket extends SimpleStickyError { - private $handle; - private $is_open = false; - private $sent = ''; - private $block_size; - - /** - * Opens a socket for reading and writing. - * @param SimpleUrl $file Target URI to fetch. - * @param integer $block_size Size of chunk to read. - * @access public - */ - function __construct($file, $block_size = 1024) { - parent::__construct(); - if (! ($this->handle = $this->openFile($file, $error))) { - $file_string = $file->asString(); - $this->setError("Cannot open [$file_string] with [$error]"); - return; - } - $this->is_open = true; - $this->block_size = $block_size; - } - - /** - * Writes some data to the socket and saves alocal copy. - * @param string $message String to send to socket. - * @return boolean True if successful. - * @access public - */ - function write($message) { - return true; - } - - /** - * Reads data from the socket. The error suppresion - * is a workaround for PHP4 always throwing a warning - * with a secure socket. - * @return integer/boolean Incoming bytes. False - * on error. - * @access public - */ - function read() { - $raw = @fread($this->handle, $this->block_size); - if ($raw === false) { - $this->setError('Cannot read from socket'); - $this->close(); - } - return $raw; - } - - /** - * Accessor for socket open state. - * @return boolean True if open. - * @access public - */ - function isOpen() { - return $this->is_open; - } - - /** - * Closes the socket preventing further reads. - * Cannot be reopened once closed. - * @return boolean True if successful. - * @access public - */ - function close() { - if (!$this->is_open) return false; - $this->is_open = false; - return fclose($this->handle); - } - - /** - * Accessor for content so far. - * @return string Bytes sent only. - * @access public - */ - function getSent() { - return $this->sent; - } - - /** - * Actually opens the low level socket. - * @param SimpleUrl $file SimpleUrl file target. - * @param string $error Recipient of error message. - * @param integer $timeout Maximum time to wait for connection. - * @access protected - */ - protected function openFile($file, &$error) { - return @fopen($file->asString(), 'r'); - } -} - -/** - * Wrapper for TCP/IP socket. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleSocket extends SimpleStickyError { - private $handle; - private $is_open = false; - private $sent = ''; - private $lock_size; - - /** - * Opens a socket for reading and writing. - * @param string $host Hostname to send request to. - * @param integer $port Port on remote machine to open. - * @param integer $timeout Connection timeout in seconds. - * @param integer $block_size Size of chunk to read. - * @access public - */ - function __construct($host, $port, $timeout, $block_size = 255) { - parent::__construct(); - if (! ($this->handle = $this->openSocket($host, $port, $error_number, $error, $timeout))) { - $this->setError("Cannot open [$host:$port] with [$error] within [$timeout] seconds"); - return; - } - $this->is_open = true; - $this->block_size = $block_size; - SimpleTestCompatibility::setTimeout($this->handle, $timeout); - } - - /** - * Writes some data to the socket and saves alocal copy. - * @param string $message String to send to socket. - * @return boolean True if successful. - * @access public - */ - function write($message) { - if ($this->isError() || ! $this->isOpen()) { - return false; - } - $count = fwrite($this->handle, $message); - if (! $count) { - if ($count === false) { - $this->setError('Cannot write to socket'); - $this->close(); - } - return false; - } - fflush($this->handle); - $this->sent .= $message; - return true; - } - - /** - * Reads data from the socket. The error suppresion - * is a workaround for PHP4 always throwing a warning - * with a secure socket. - * @return integer/boolean Incoming bytes. False - * on error. - * @access public - */ - function read() { - if ($this->isError() || ! $this->isOpen()) { - return false; - } - $raw = @fread($this->handle, $this->block_size); - if ($raw === false) { - $this->setError('Cannot read from socket'); - $this->close(); - } - return $raw; - } - - /** - * Accessor for socket open state. - * @return boolean True if open. - * @access public - */ - function isOpen() { - return $this->is_open; - } - - /** - * Closes the socket preventing further reads. - * Cannot be reopened once closed. - * @return boolean True if successful. - * @access public - */ - function close() { - $this->is_open = false; - return fclose($this->handle); - } - - /** - * Accessor for content so far. - * @return string Bytes sent only. - * @access public - */ - function getSent() { - return $this->sent; - } - - /** - * Actually opens the low level socket. - * @param string $host Host to connect to. - * @param integer $port Port on host. - * @param integer $error_number Recipient of error code. - * @param string $error Recipoent of error message. - * @param integer $timeout Maximum time to wait for connection. - * @access protected - */ - protected function openSocket($host, $port, &$error_number, &$error, $timeout) { - return @fsockopen($host, $port, $error_number, $error, $timeout); - } -} - -/** - * Wrapper for TCP/IP socket over TLS. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleSecureSocket extends SimpleSocket { - - /** - * Opens a secure socket for reading and writing. - * @param string $host Hostname to send request to. - * @param integer $port Port on remote machine to open. - * @param integer $timeout Connection timeout in seconds. - * @access public - */ - function __construct($host, $port, $timeout) { - parent::__construct($host, $port, $timeout); - } - - /** - * Actually opens the low level socket. - * @param string $host Host to connect to. - * @param integer $port Port on host. - * @param integer $error_number Recipient of error code. - * @param string $error Recipient of error message. - * @param integer $timeout Maximum time to wait for connection. - * @access protected - */ - function openSocket($host, $port, &$error_number, &$error, $timeout) { - return parent::openSocket("tls://$host", $port, $error_number, $error, $timeout); - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/tag.php b/lib/simpletestlib/tag.php deleted file mode 100644 index afe649ec5dd..00000000000 --- a/lib/simpletestlib/tag.php +++ /dev/null @@ -1,1527 +0,0 @@ - 'SimpleAnchorTag', - 'title' => 'SimpleTitleTag', - 'base' => 'SimpleBaseTag', - 'button' => 'SimpleButtonTag', - 'textarea' => 'SimpleTextAreaTag', - 'option' => 'SimpleOptionTag', - 'label' => 'SimpleLabelTag', - 'form' => 'SimpleFormTag', - 'frame' => 'SimpleFrameTag'); - $attributes = $this->keysToLowerCase($attributes); - if (array_key_exists($name, $map)) { - $tag_class = $map[$name]; - return new $tag_class($attributes); - } elseif ($name == 'select') { - return $this->createSelectionTag($attributes); - } elseif ($name == 'input') { - return $this->createInputTag($attributes); - } - return new SimpleTag($name, $attributes); - } - - /** - * Factory for selection fields. - * @param hash $attributes Element attributes. - * @return SimpleTag Tag object. - * @access protected - */ - protected function createSelectionTag($attributes) { - if (isset($attributes['multiple'])) { - return new MultipleSelectionTag($attributes); - } - return new SimpleSelectionTag($attributes); - } - - /** - * Factory for input tags. - * @param hash $attributes Element attributes. - * @return SimpleTag Tag object. - * @access protected - */ - protected function createInputTag($attributes) { - if (! isset($attributes['type'])) { - return new SimpleTextTag($attributes); - } - $type = strtolower(trim($attributes['type'])); - $map = array( - 'submit' => 'SimpleSubmitTag', - 'image' => 'SimpleImageSubmitTag', - 'checkbox' => 'SimpleCheckboxTag', - 'radio' => 'SimpleRadioButtonTag', - 'text' => 'SimpleTextTag', - 'hidden' => 'SimpleTextTag', - 'password' => 'SimpleTextTag', - 'file' => 'SimpleUploadTag'); - if (array_key_exists($type, $map)) { - $tag_class = $map[$type]; - return new $tag_class($attributes); - } - return false; - } - - /** - * Make the keys lower case for case insensitive look-ups. - * @param hash $map Hash to convert. - * @return hash Unchanged values, but keys lower case. - * @access private - */ - protected function keysToLowerCase($map) { - $lower = array(); - foreach ($map as $key => $value) { - $lower[strtolower($key)] = $value; - } - return $lower; - } -} - -/** - * HTML or XML tag. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleTag { - private $name; - private $attributes; - private $content; - - /** - * Starts with a named tag with attributes only. - * @param string $name Tag name. - * @param hash $attributes Attribute names and - * string values. Note that - * the keys must have been - * converted to lower case. - */ - function __construct($name, $attributes) { - $this->name = strtolower(trim($name)); - $this->attributes = $attributes; - $this->content = ''; - } - - /** - * Check to see if the tag can have both start and - * end tags with content in between. - * @return boolean True if content allowed. - * @access public - */ - function expectEndTag() { - return true; - } - - /** - * The current tag should not swallow all content for - * itself as it's searchable page content. Private - * content tags are usually widgets that contain default - * values. - * @return boolean False as content is available - * to other tags by default. - * @access public - */ - function isPrivateContent() { - return false; - } - - /** - * Appends string content to the current content. - * @param string $content Additional text. - * @access public - */ - function addContent($content) { - $this->content .= (string)$content; - return $this; - } - - /** - * Adds an enclosed tag to the content. - * @param SimpleTag $tag New tag. - * @access public - */ - function addTag($tag) { - } - - /** - * Adds multiple enclosed tags to the content. - * @param array List of SimpleTag objects to be added. - */ - function addTags($tags) { - foreach ($tags as $tag) { - $this->addTag($tag); - } - } - - /** - * Accessor for tag name. - * @return string Name of tag. - * @access public - */ - function getTagName() { - return $this->name; - } - - /** - * List of legal child elements. - * @return array List of element names. - * @access public - */ - function getChildElements() { - return array(); - } - - /** - * Accessor for an attribute. - * @param string $label Attribute name. - * @return string Attribute value. - * @access public - */ - function getAttribute($label) { - $label = strtolower($label); - if (! isset($this->attributes[$label])) { - return false; - } - return (string)$this->attributes[$label]; - } - - /** - * Sets an attribute. - * @param string $label Attribute name. - * @return string $value New attribute value. - * @access protected - */ - protected function setAttribute($label, $value) { - $this->attributes[strtolower($label)] = $value; - } - - /** - * Accessor for the whole content so far. - * @return string Content as big raw string. - * @access public - */ - function getContent() { - return $this->content; - } - - /** - * Accessor for content reduced to visible text. Acts - * like a text mode browser, normalising space and - * reducing images to their alt text. - * @return string Content as plain text. - * @access public - */ - function getText() { - return SimplePage::normalise($this->content); - } - - /** - * Test to see if id attribute matches. - * @param string $id ID to test against. - * @return boolean True on match. - * @access public - */ - function isId($id) { - return ($this->getAttribute('id') == $id); - } -} - -/** - * Base url. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleBaseTag extends SimpleTag { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('base', $attributes); - } - - /** - * Base tag is not a block tag. - * @return boolean false - * @access public - */ - function expectEndTag() { - return false; - } -} - -/** - * Page title. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleTitleTag extends SimpleTag { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('title', $attributes); - } -} - -/** - * Link. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleAnchorTag extends SimpleTag { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('a', $attributes); - } - - /** - * Accessor for URL as string. - * @return string Coerced as string. - * @access public - */ - function getHref() { - $url = $this->getAttribute('href'); - if (is_bool($url)) { - $url = ''; - } - return $url; - } -} - -/** - * Form element. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleWidget extends SimpleTag { - private $value; - private $label; - private $is_set; - - /** - * Starts with a named tag with attributes only. - * @param string $name Tag name. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($name, $attributes) { - parent::__construct($name, $attributes); - $this->value = false; - $this->label = false; - $this->is_set = false; - } - - /** - * Accessor for name submitted as the key in - * GET/POST privateiables hash. - * @return string Parsed value. - * @access public - */ - function getName() { - return $this->getAttribute('name'); - } - - /** - * Accessor for default value parsed with the tag. - * @return string Parsed value. - * @access public - */ - function getDefault() { - return $this->getAttribute('value'); - } - - /** - * Accessor for currently set value or default if - * none. - * @return string Value set by form or default - * if none. - * @access public - */ - function getValue() { - if (! $this->is_set) { - return $this->getDefault(); - } - return $this->value; - } - - /** - * Sets the current form element value. - * @param string $value New value. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - $this->value = $value; - $this->is_set = true; - return true; - } - - /** - * Resets the form element value back to the - * default. - * @access public - */ - function resetValue() { - $this->is_set = false; - } - - /** - * Allows setting of a label externally, say by a - * label tag. - * @param string $label Label to attach. - * @access public - */ - function setLabel($label) { - $this->label = trim($label); - return $this; - } - - /** - * Reads external or internal label. - * @param string $label Label to test. - * @return boolean True is match. - * @access public - */ - function isLabel($label) { - return $this->label == trim($label); - } - - /** - * Dispatches the value into the form encoded packet. - * @param SimpleEncoding $encoding Form packet. - * @access public - */ - function write($encoding) { - if ($this->getName()) { - $encoding->add($this->getName(), $this->getValue()); - } - } -} - -/** - * Text, password and hidden field. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleTextTag extends SimpleWidget { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('input', $attributes); - if ($this->getAttribute('value') === false) { - $this->setAttribute('value', ''); - } - } - - /** - * Tag contains no content. - * @return boolean False. - * @access public - */ - function expectEndTag() { - return false; - } - - /** - * Sets the current form element value. Cannot - * change the value of a hidden field. - * @param string $value New value. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - if ($this->getAttribute('type') == 'hidden') { - return false; - } - return parent::setValue($value); - } -} - -/** - * Submit button as input tag. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleSubmitTag extends SimpleWidget { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('input', $attributes); - if ($this->getAttribute('value') === false) { - $this->setAttribute('value', 'Submit'); - } - } - - /** - * Tag contains no end element. - * @return boolean False. - * @access public - */ - function expectEndTag() { - return false; - } - - /** - * Disables the setting of the button value. - * @param string $value Ignored. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - return false; - } - - /** - * Value of browser visible text. - * @return string Visible label. - * @access public - */ - function getLabel() { - return $this->getValue(); - } - - /** - * Test for a label match when searching. - * @param string $label Label to test. - * @return boolean True on match. - * @access public - */ - function isLabel($label) { - return trim($label) == trim($this->getLabel()); - } -} - -/** - * Image button as input tag. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleImageSubmitTag extends SimpleWidget { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('input', $attributes); - } - - /** - * Tag contains no end element. - * @return boolean False. - * @access public - */ - function expectEndTag() { - return false; - } - - /** - * Disables the setting of the button value. - * @param string $value Ignored. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - return false; - } - - /** - * Value of browser visible text. - * @return string Visible label. - * @access public - */ - function getLabel() { - if ($this->getAttribute('title')) { - return $this->getAttribute('title'); - } - return $this->getAttribute('alt'); - } - - /** - * Test for a label match when searching. - * @param string $label Label to test. - * @return boolean True on match. - * @access public - */ - function isLabel($label) { - return trim($label) == trim($this->getLabel()); - } - - /** - * Dispatches the value into the form encoded packet. - * @param SimpleEncoding $encoding Form packet. - * @param integer $x X coordinate of click. - * @param integer $y Y coordinate of click. - * @access public - */ - function write($encoding, $x = 1, $y = 1) { - if ($this->getName()) { - $encoding->add($this->getName() . '.x', $x); - $encoding->add($this->getName() . '.y', $y); - } else { - $encoding->add('x', $x); - $encoding->add('y', $y); - } - } -} - -/** - * Submit button as button tag. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleButtonTag extends SimpleWidget { - - /** - * Starts with a named tag with attributes only. - * Defaults are very browser dependent. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('button', $attributes); - } - - /** - * Check to see if the tag can have both start and - * end tags with content in between. - * @return boolean True if content allowed. - * @access public - */ - function expectEndTag() { - return true; - } - - /** - * Disables the setting of the button value. - * @param string $value Ignored. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - return false; - } - - /** - * Value of browser visible text. - * @return string Visible label. - * @access public - */ - function getLabel() { - return $this->getContent(); - } - - /** - * Test for a label match when searching. - * @param string $label Label to test. - * @return boolean True on match. - * @access public - */ - function isLabel($label) { - return trim($label) == trim($this->getLabel()); - } -} - -/** - * Content tag for text area. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleTextAreaTag extends SimpleWidget { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('textarea', $attributes); - } - - /** - * Accessor for starting value. - * @return string Parsed value. - * @access public - */ - function getDefault() { - return $this->wrap(html_entity_decode($this->getContent(), ENT_QUOTES)); - } - - /** - * Applies word wrapping if needed. - * @param string $value New value. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - return parent::setValue($this->wrap($value)); - } - - /** - * Test to see if text should be wrapped. - * @return boolean True if wrapping on. - * @access private - */ - function wrapIsEnabled() { - if ($this->getAttribute('cols')) { - $wrap = $this->getAttribute('wrap'); - if (($wrap == 'physical') || ($wrap == 'hard')) { - return true; - } - } - return false; - } - - /** - * Performs the formatting that is peculiar to - * this tag. There is strange behaviour in this - * one, including stripping a leading new line. - * Go figure. I am using Firefox as a guide. - * @param string $text Text to wrap. - * @return string Text wrapped with carriage - * returns and line feeds - * @access private - */ - protected function wrap($text) { - $text = str_replace("\r\r\n", "\r\n", str_replace("\n", "\r\n", $text)); - $text = str_replace("\r\n\n", "\r\n", str_replace("\r", "\r\n", $text)); - if (strncmp($text, "\r\n", strlen("\r\n")) == 0) { - $text = substr($text, strlen("\r\n")); - } - if ($this->wrapIsEnabled()) { - return wordwrap( - $text, - (integer)$this->getAttribute('cols'), - "\r\n"); - } - return $text; - } - - /** - * The content of textarea is not part of the page. - * @return boolean True. - * @access public - */ - function isPrivateContent() { - return true; - } -} - -/** - * File upload widget. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleUploadTag extends SimpleWidget { - - /** - * Starts with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('input', $attributes); - } - - /** - * Tag contains no content. - * @return boolean False. - * @access public - */ - function expectEndTag() { - return false; - } - - /** - * Dispatches the value into the form encoded packet. - * @param SimpleEncoding $encoding Form packet. - * @access public - */ - function write($encoding) { - if (! file_exists($this->getValue())) { - return; - } - $encoding->attach( - $this->getName(), - implode('', file($this->getValue())), - basename($this->getValue())); - } -} - -/** - * Drop down widget. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleSelectionTag extends SimpleWidget { - private $options; - private $choice; - - /** - * Starts with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('select', $attributes); - $this->options = array(); - $this->choice = false; - } - - /** - * Adds an option tag to a selection field. - * @param SimpleOptionTag $tag New option. - * @access public - */ - function addTag($tag) { - if ($tag->getTagName() == 'option') { - $this->options[] = $tag; - } - } - - /** - * Text within the selection element is ignored. - * @param string $content Ignored. - * @access public - */ - function addContent($content) { - return $this; - } - - /** - * Scans options for defaults. If none, then - * the first option is selected. - * @return string Selected field. - * @access public - */ - function getDefault() { - for ($i = 0, $count = count($this->options); $i < $count; $i++) { - if ($this->options[$i]->getAttribute('selected') !== false) { - return $this->options[$i]->getDefault(); - } - } - if ($count > 0) { - return $this->options[0]->getDefault(); - } - return ''; - } - - /** - * Can only set allowed values. - * @param string $value New choice. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - for ($i = 0, $count = count($this->options); $i < $count; $i++) { - if ($this->options[$i]->isValue($value)) { - $this->choice = $i; - return true; - } - } - return false; - } - - /** - * Accessor for current selection value. - * @return string Value attribute or - * content of opton. - * @access public - */ - function getValue() { - if ($this->choice === false) { - return $this->getDefault(); - } - return $this->options[$this->choice]->getValue(); - } -} - -/** - * Drop down widget. - * @package SimpleTest - * @subpackage WebTester - */ -class MultipleSelectionTag extends SimpleWidget { - private $options; - private $values; - - /** - * Starts with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('select', $attributes); - $this->options = array(); - $this->values = false; - } - - /** - * Adds an option tag to a selection field. - * @param SimpleOptionTag $tag New option. - * @access public - */ - function addTag($tag) { - if ($tag->getTagName() == 'option') { - $this->options[] = &$tag; - } - } - - /** - * Text within the selection element is ignored. - * @param string $content Ignored. - * @access public - */ - function addContent($content) { - return $this; - } - - /** - * Scans options for defaults to populate the - * value array(). - * @return array Selected fields. - * @access public - */ - function getDefault() { - $default = array(); - for ($i = 0, $count = count($this->options); $i < $count; $i++) { - if ($this->options[$i]->getAttribute('selected') !== false) { - $default[] = $this->options[$i]->getDefault(); - } - } - return $default; - } - - /** - * Can only set allowed values. Any illegal value - * will result in a failure, but all correct values - * will be set. - * @param array $desired New choices. - * @return boolean True if all allowed. - * @access public - */ - function setValue($desired) { - $achieved = array(); - foreach ($desired as $value) { - $success = false; - for ($i = 0, $count = count($this->options); $i < $count; $i++) { - if ($this->options[$i]->isValue($value)) { - $achieved[] = $this->options[$i]->getValue(); - $success = true; - break; - } - } - if (! $success) { - return false; - } - } - $this->values = $achieved; - return true; - } - - /** - * Accessor for current selection value. - * @return array List of currently set options. - * @access public - */ - function getValue() { - if ($this->values === false) { - return $this->getDefault(); - } - return $this->values; - } -} - -/** - * Option for selection field. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleOptionTag extends SimpleWidget { - - /** - * Stashes the attributes. - */ - function __construct($attributes) { - parent::__construct('option', $attributes); - } - - /** - * Does nothing. - * @param string $value Ignored. - * @return boolean Not allowed. - * @access public - */ - function setValue($value) { - return false; - } - - /** - * Test to see if a value matches the option. - * @param string $compare Value to compare with. - * @return boolean True if possible match. - * @access public - */ - function isValue($compare) { - $compare = trim($compare); - if (trim($this->getValue()) == $compare) { - return true; - } - return trim(strip_tags($this->getContent())) == $compare; - } - - /** - * Accessor for starting value. Will be set to - * the option label if no value exists. - * @return string Parsed value. - * @access public - */ - function getDefault() { - if ($this->getAttribute('value') === false) { - return strip_tags($this->getContent()); - } - return $this->getAttribute('value'); - } - - /** - * The content of options is not part of the page. - * @return boolean True. - * @access public - */ - function isPrivateContent() { - return true; - } -} - -/** - * Radio button. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleRadioButtonTag extends SimpleWidget { - - /** - * Stashes the attributes. - * @param array $attributes Hash of attributes. - */ - function __construct($attributes) { - parent::__construct('input', $attributes); - if ($this->getAttribute('value') === false) { - $this->setAttribute('value', 'on'); - } - } - - /** - * Tag contains no content. - * @return boolean False. - * @access public - */ - function expectEndTag() { - return false; - } - - /** - * The only allowed value sn the one in the - * "value" attribute. - * @param string $value New value. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - if ($value === false) { - return parent::setValue($value); - } - if ($value != $this->getAttribute('value')) { - return false; - } - return parent::setValue($value); - } - - /** - * Accessor for starting value. - * @return string Parsed value. - * @access public - */ - function getDefault() { - if ($this->getAttribute('checked') !== false) { - return $this->getAttribute('value'); - } - return false; - } -} - -/** - * Checkbox widget. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleCheckboxTag extends SimpleWidget { - - /** - * Starts with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('input', $attributes); - if ($this->getAttribute('value') === false) { - $this->setAttribute('value', 'on'); - } - } - - /** - * Tag contains no content. - * @return boolean False. - * @access public - */ - function expectEndTag() { - return false; - } - - /** - * The only allowed value in the one in the - * "value" attribute. The default for this - * attribute is "on". If this widget is set to - * true, then the usual value will be taken. - * @param string $value New value. - * @return boolean True if allowed. - * @access public - */ - function setValue($value) { - if ($value === false) { - return parent::setValue($value); - } - if ($value === true) { - return parent::setValue($this->getAttribute('value')); - } - if ($value != $this->getAttribute('value')) { - return false; - } - return parent::setValue($value); - } - - /** - * Accessor for starting value. The default - * value is "on". - * @return string Parsed value. - * @access public - */ - function getDefault() { - if ($this->getAttribute('checked') !== false) { - return $this->getAttribute('value'); - } - return false; - } -} - -/** - * A group of multiple widgets with some shared behaviour. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleTagGroup { - private $widgets = array(); - - /** - * Adds a tag to the group. - * @param SimpleWidget $widget - * @access public - */ - function addWidget($widget) { - $this->widgets[] = $widget; - } - - /** - * Accessor to widget set. - * @return array All widgets. - * @access protected - */ - protected function &getWidgets() { - return $this->widgets; - } - - /** - * Accessor for an attribute. - * @param string $label Attribute name. - * @return boolean Always false. - * @access public - */ - function getAttribute($label) { - return false; - } - - /** - * Fetches the name for the widget from the first - * member. - * @return string Name of widget. - * @access public - */ - function getName() { - if (count($this->widgets) > 0) { - return $this->widgets[0]->getName(); - } - } - - /** - * Scans the widgets for one with the appropriate - * ID field. - * @param string $id ID value to try. - * @return boolean True if matched. - * @access public - */ - function isId($id) { - for ($i = 0, $count = count($this->widgets); $i < $count; $i++) { - if ($this->widgets[$i]->isId($id)) { - return true; - } - } - return false; - } - - /** - * Scans the widgets for one with the appropriate - * attached label. - * @param string $label Attached label to try. - * @return boolean True if matched. - * @access public - */ - function isLabel($label) { - for ($i = 0, $count = count($this->widgets); $i < $count; $i++) { - if ($this->widgets[$i]->isLabel($label)) { - return true; - } - } - return false; - } - - /** - * Dispatches the value into the form encoded packet. - * @param SimpleEncoding $encoding Form packet. - * @access public - */ - function write($encoding) { - $encoding->add($this->getName(), $this->getValue()); - } -} - -/** - * A group of tags with the same name within a form. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleCheckboxGroup extends SimpleTagGroup { - - /** - * Accessor for current selected widget or false - * if none. - * @return string/array Widget values or false if none. - * @access public - */ - function getValue() { - $values = array(); - $widgets = $this->getWidgets(); - for ($i = 0, $count = count($widgets); $i < $count; $i++) { - if ($widgets[$i]->getValue() !== false) { - $values[] = $widgets[$i]->getValue(); - } - } - return $this->coerceValues($values); - } - - /** - * Accessor for starting value that is active. - * @return string/array Widget values or false if none. - * @access public - */ - function getDefault() { - $values = array(); - $widgets = $this->getWidgets(); - for ($i = 0, $count = count($widgets); $i < $count; $i++) { - if ($widgets[$i]->getDefault() !== false) { - $values[] = $widgets[$i]->getDefault(); - } - } - return $this->coerceValues($values); - } - - /** - * Accessor for current set values. - * @param string/array/boolean $values Either a single string, a - * hash or false for nothing set. - * @return boolean True if all values can be set. - * @access public - */ - function setValue($values) { - $values = $this->makeArray($values); - if (! $this->valuesArePossible($values)) { - return false; - } - $widgets = $this->getWidgets(); - for ($i = 0, $count = count($widgets); $i < $count; $i++) { - $possible = $widgets[$i]->getAttribute('value'); - if (in_array($widgets[$i]->getAttribute('value'), $values)) { - $widgets[$i]->setValue($possible); - } else { - $widgets[$i]->setValue(false); - } - } - return true; - } - - /** - * Tests to see if a possible value set is legal. - * @param string/array/boolean $values Either a single string, a - * hash or false for nothing set. - * @return boolean False if trying to set a - * missing value. - * @access private - */ - protected function valuesArePossible($values) { - $matches = array(); - $widgets = &$this->getWidgets(); - for ($i = 0, $count = count($widgets); $i < $count; $i++) { - $possible = $widgets[$i]->getAttribute('value'); - if (in_array($possible, $values)) { - $matches[] = $possible; - } - } - return ($values == $matches); - } - - /** - * Converts the output to an appropriate format. This means - * that no values is false, a single value is just that - * value and only two or more are contained in an array. - * @param array $values List of values of widgets. - * @return string/array/boolean Expected format for a tag. - * @access private - */ - protected function coerceValues($values) { - if (count($values) == 0) { - return false; - } elseif (count($values) == 1) { - return $values[0]; - } else { - return $values; - } - } - - /** - * Converts false or string into array. The opposite of - * the coercian method. - * @param string/array/boolean $value A single item is converted - * to a one item list. False - * gives an empty list. - * @return array List of values, possibly empty. - * @access private - */ - protected function makeArray($value) { - if ($value === false) { - return array(); - } - if (is_string($value)) { - return array($value); - } - return $value; - } -} - -/** - * A group of tags with the same name within a form. - * Used for radio buttons. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleRadioGroup extends SimpleTagGroup { - - /** - * Each tag is tried in turn until one is - * successfully set. The others will be - * unchecked if successful. - * @param string $value New value. - * @return boolean True if any allowed. - * @access public - */ - function setValue($value) { - if (! $this->valueIsPossible($value)) { - return false; - } - $index = false; - $widgets = $this->getWidgets(); - for ($i = 0, $count = count($widgets); $i < $count; $i++) { - if (! $widgets[$i]->setValue($value)) { - $widgets[$i]->setValue(false); - } - } - return true; - } - - /** - * Tests to see if a value is allowed. - * @param string Attempted value. - * @return boolean True if a valid value. - * @access private - */ - protected function valueIsPossible($value) { - $widgets = $this->getWidgets(); - for ($i = 0, $count = count($widgets); $i < $count; $i++) { - if ($widgets[$i]->getAttribute('value') == $value) { - return true; - } - } - return false; - } - - /** - * Accessor for current selected widget or false - * if none. - * @return string/boolean Value attribute or - * content of opton. - * @access public - */ - function getValue() { - $widgets = $this->getWidgets(); - for ($i = 0, $count = count($widgets); $i < $count; $i++) { - if ($widgets[$i]->getValue() !== false) { - return $widgets[$i]->getValue(); - } - } - return false; - } - - /** - * Accessor for starting value that is active. - * @return string/boolean Value of first checked - * widget or false if none. - * @access public - */ - function getDefault() { - $widgets = $this->getWidgets(); - for ($i = 0, $count = count($widgets); $i < $count; $i++) { - if ($widgets[$i]->getDefault() !== false) { - return $widgets[$i]->getDefault(); - } - } - return false; - } -} - -/** - * Tag to keep track of labels. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleLabelTag extends SimpleTag { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('label', $attributes); - } - - /** - * Access for the ID to attach the label to. - * @return string For attribute. - * @access public - */ - function getFor() { - return $this->getAttribute('for'); - } -} - -/** - * Tag to aid parsing the form. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleFormTag extends SimpleTag { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('form', $attributes); - } -} - -/** - * Tag to aid parsing the frames in a page. - * @package SimpleTest - * @subpackage WebTester - */ -class SimpleFrameTag extends SimpleTag { - - /** - * Starts with a named tag with attributes only. - * @param hash $attributes Attribute names and - * string values. - */ - function __construct($attributes) { - parent::__construct('frame', $attributes); - } - - /** - * Tag contains no content. - * @return boolean False. - * @access public - */ - function expectEndTag() { - return false; - } -} -?> \ No newline at end of file diff --git a/lib/simpletestlib/test_case.php b/lib/simpletestlib/test_case.php deleted file mode 100644 index 18a283059a1..00000000000 --- a/lib/simpletestlib/test_case.php +++ /dev/null @@ -1,683 +0,0 @@ -label = $label; - } - } - - /** - * Accessor for the test name for subclasses. - * @return string Name of the test. - * @access public - */ - function getLabel() { - return $this->label ? $this->label : get_class($this); - } - - /** - * This is a placeholder for skipping tests. In this - * method you place skipIf() and skipUnless() calls to - * set the skipping state. - * @access public - */ - function skip() { - } - - /** - * Will issue a message to the reporter and tell the test - * case to skip if the incoming flag is true. - * @param string $should_skip Condition causing the tests to be skipped. - * @param string $message Text of skip condition. - * @access public - */ - function skipIf($should_skip, $message = '%s') { - if ($should_skip && ! $this->should_skip) { - $this->should_skip = true; - $message = sprintf($message, 'Skipping [' . get_class($this) . ']'); - $this->reporter->paintSkip($message . $this->getAssertionLine()); - } - } - - /** - * Accessor for the private variable $_shoud_skip - * @access public - */ - function shouldSkip() { - return $this->should_skip; - } - - /** - * Will issue a message to the reporter and tell the test - * case to skip if the incoming flag is false. - * @param string $shouldnt_skip Condition causing the tests to be run. - * @param string $message Text of skip condition. - * @access public - */ - function skipUnless($shouldnt_skip, $message = false) { - $this->skipIf(! $shouldnt_skip, $message); - } - - /** - * Used to invoke the single tests. - * @return SimpleInvoker Individual test runner. - * @access public - */ - function createInvoker() { - return new SimpleErrorTrappingInvoker( - new SimpleExceptionTrappingInvoker(new SimpleInvoker($this))); - } - - /** - * Uses reflection to run every method within itself - * starting with the string "test" unless a method - * is specified. - * @param SimpleReporter $reporter Current test reporter. - * @return boolean True if all tests passed. - * @access public - */ - function run($reporter) { - $context = SimpleTest::getContext(); - $context->setTest($this); - $context->setReporter($reporter); - $this->reporter = $reporter; - $started = false; - foreach ($this->getTests() as $method) { - if ($reporter->shouldInvoke($this->getLabel(), $method)) { - $this->skip(); - if ($this->should_skip) { - break; - } - if (! $started) { - $reporter->paintCaseStart($this->getLabel()); - $started = true; - } - - //moodlefix begins - if (defined('TIME_ALLOWED_PER_UNIT_TEST')) { - set_time_limit(TIME_ALLOWED_PER_UNIT_TEST); - } - //moodlefix ends - - $invoker = $this->reporter->createInvoker($this->createInvoker()); - $invoker->before($method); - $invoker->invoke($method); - $invoker->after($method); - } - } - if ($started) { - $reporter->paintCaseEnd($this->getLabel()); - } - unset($this->reporter); - $context->setTest(null); - return $reporter->getStatus(); - } - - /** - * Gets a list of test names. Normally that will - * be all internal methods that start with the - * name "test". This method should be overridden - * if you want a different rule. - * @return array List of test names. - * @access public - */ - function getTests() { - $methods = array(); - foreach (get_class_methods(get_class($this)) as $method) { - if ($this->isTest($method)) { - $methods[] = $method; - } - } - return $methods; - } - - /** - * Tests to see if the method is a test that should - * be run. Currently any method that starts with 'test' - * is a candidate unless it is the constructor. - * @param string $method Method name to try. - * @return boolean True if test method. - * @access protected - */ - protected function isTest($method) { - if (strtolower(substr($method, 0, 4)) == 'test') { - return ! SimpleTestCompatibility::isA($this, strtolower($method)); - } - return false; - } - - /** - * Announces the start of the test. - * @param string $method Test method just started. - * @access public - */ - function before($method) { - $this->reporter->paintMethodStart($method); - $this->observers = array(); - } - - /** - * Sets up unit test wide variables at the start - * of each test method. To be overridden in - * actual user test cases. - * @access public - */ - function setUp() { - } - - /** - * Clears the data set in the setUp() method call. - * To be overridden by the user in actual user test cases. - * @access public - */ - function tearDown() { - } - - /** - * Announces the end of the test. Includes private clean up. - * @param string $method Test method just finished. - * @access public - */ - function after($method) { - for ($i = 0; $i < count($this->observers); $i++) { - $this->observers[$i]->atTestEnd($method, $this); - } - $this->reporter->paintMethodEnd($method); - } - - /** - * Sets up an observer for the test end. - * @param object $observer Must have atTestEnd() - * method. - * @access public - */ - function tell($observer) { - $this->observers[] = &$observer; - } - - /** - * @deprecated - */ - function pass($message = "Pass") { - if (! isset($this->reporter)) { - trigger_error('Can only make assertions within test methods'); - } - $this->reporter->paintPass( - $message . $this->getAssertionLine()); - return true; - } - - /** - * Sends a fail event with a message. - * @param string $message Message to send. - * @access public - */ - function fail($message = "Fail") { - if (! isset($this->reporter)) { - trigger_error('Can only make assertions within test methods'); - } - $this->reporter->paintFail( - $message . $this->getAssertionLine()); - return false; - } - - /** - * Formats a PHP error and dispatches it to the - * reporter. - * @param integer $severity PHP error code. - * @param string $message Text of error. - * @param string $file File error occoured in. - * @param integer $line Line number of error. - * @access public - */ - function error($severity, $message, $file, $line) { - if (! isset($this->reporter)) { - trigger_error('Can only make assertions within test methods'); - } - $this->reporter->paintError( - "Unexpected PHP error [$message] severity [$severity] in [$file line $line]"); - } - - /** - * Formats an exception and dispatches it to the - * reporter. - * @param Exception $exception Object thrown. - * @access public - */ - function exception($exception) { - $this->reporter->paintException($exception); - } - - /** - * For user defined expansion of the available messages. - * @param string $type Tag for sorting the signals. - * @param mixed $payload Extra user specific information. - */ - function signal($type, $payload) { - if (! isset($this->reporter)) { - trigger_error('Can only make assertions within test methods'); - } - $this->reporter->paintSignal($type, $payload); - } - - /** - * Runs an expectation directly, for extending the - * tests with new expectation classes. - * @param SimpleExpectation $expectation Expectation subclass. - * @param mixed $compare Value to compare. - * @param string $message Message to display. - * @return boolean True on pass - * @access public - */ - function assert($expectation, $compare, $message = '%s') { - if ($expectation->test($compare)) { - return $this->pass(sprintf( - $message, - $expectation->overlayMessage($compare, $this->reporter->getDumper()))); - } else { - return $this->fail(sprintf( - $message, - $expectation->overlayMessage($compare, $this->reporter->getDumper()))); - } - } - - /** - * Uses a stack trace to find the line of an assertion. - * @return string Line number of first assert* - * method embedded in format string. - * @access public - */ - function getAssertionLine() { - $trace = new SimpleStackTrace(array('assert', 'expect', 'pass', 'fail', 'skip')); - return $trace->traceMethod(); - } - - /** - * Sends a formatted dump of a variable to the - * test suite for those emergency debugging - * situations. - * @param mixed $variable Variable to display. - * @param string $message Message to display. - * @return mixed The original variable. - * @access public - */ - function dump($variable, $message = false) { - $dumper = $this->reporter->getDumper(); - $formatted = $dumper->dump($variable); - if ($message) { - $formatted = $message . "\n" . $formatted; - } - $this->reporter->paintFormattedMessage($formatted); - return $variable; - } - - /** - * Accessor for the number of subtests including myelf. - * @return integer Number of test cases. - * @access public - */ - function getSize() { - return 1; - } -} - -/** - * Helps to extract test cases automatically from a file. - * @package SimpleTest - * @subpackage UnitTester - */ -class SimpleFileLoader { - - /** - * Builds a test suite from a library of test cases. - * The new suite is composed into this one. - * @param string $test_file File name of library with - * test case classes. - * @return TestSuite The new test suite. - * @access public - */ - function load($test_file) { - $existing_classes = get_declared_classes(); - $existing_globals = get_defined_vars(); - - global $CFG; // moodle hack - - include_once($test_file); - $new_globals = get_defined_vars(); - $this->makeFileVariablesGlobal($existing_globals, $new_globals); - $new_classes = array_diff(get_declared_classes(), $existing_classes); - if (empty($new_classes)) { - $new_classes = $this->scrapeClassesFromFile($test_file); - } - $classes = $this->selectRunnableTests($new_classes); - return $this->createSuiteFromClasses($test_file, $classes); - } - - /** - * Imports new variables into the global namespace. - * @param hash $existing Variables before the file was loaded. - * @param hash $new Variables after the file was loaded. - * @access private - */ - protected function makeFileVariablesGlobal($existing, $new) { - $globals = array_diff(array_keys($new), array_keys($existing)); - foreach ($globals as $global) { - $GLOBALS[$global] = $new[$global]; - } - } - - /** - * Lookup classnames from file contents, in case the - * file may have been included before. - * Note: This is probably too clever by half. Figuring this - * out after a failed test case is going to be tricky for us, - * never mind the user. A test case should not be included - * twice anyway. - * @param string $test_file File name with classes. - * @access private - */ - protected function scrapeClassesFromFile($test_file) { - preg_match_all('~^\s*class\s+(\w+)(\s+(extends|implements)\s+\w+)*\s*\{~mi', - file_get_contents($test_file), - $matches ); - return $matches[1]; - } - - /** - * Calculates the incoming test cases. Skips abstract - * and ignored classes. - * @param array $candidates Candidate classes. - * @return array New classes which are test - * cases that shouldn't be ignored. - * @access public - */ - function selectRunnableTests($candidates) { - $classes = array(); - foreach ($candidates as $class) { - if (TestSuite::getBaseTestCase($class)) { - $reflection = new SimpleReflection($class); - if ($reflection->isAbstract()) { - SimpleTest::ignore($class); - } else { - $classes[] = $class; - } - } - } - return $classes; - } - - /** - * Builds a test suite from a class list. - * @param string $title Title of new group. - * @param array $classes Test classes. - * @return TestSuite Group loaded with the new - * test cases. - * @access public - */ - function createSuiteFromClasses($title, $classes) { - if (count($classes) == 0) { - $suite = new BadTestSuite($title, "No runnable test cases in [$title]"); - return $suite; - } - SimpleTest::ignoreParentsIfIgnored($classes); - $suite = new TestSuite($title); - foreach ($classes as $class) { - if (! SimpleTest::isIgnored($class)) { - $suite->add($class); - } - } - return $suite; - } -} - -/** - * This is a composite test class for combining - * test cases and other RunnableTest classes into - * a group test. - * @package SimpleTest - * @subpackage UnitTester - */ -class TestSuite { - private $label; - private $test_cases; - - /** - * Sets the name of the test suite. - * @param string $label Name sent at the start and end - * of the test. - * @access public - */ - function TestSuite($label = false) { - $this->label = $label; - $this->test_cases = array(); - } - - /** - * Accessor for the test name for subclasses. If the suite - * wraps a single test case the label defaults to the name of that test. - * @return string Name of the test. - * @access public - */ - function getLabel() { - if (! $this->label) { - return ($this->getSize() == 1) ? - get_class($this->test_cases[0]) : get_class($this); - } else { - return $this->label; - } - } - - /** - * Adds a test into the suite by instance or class. The class will - * be instantiated if it's a test suite. - * @param SimpleTestCase $test_case Suite or individual test - * case implementing the - * runnable test interface. - * @access public - */ - function add($test_case) { - if (! is_string($test_case)) { - $this->test_cases[] = $test_case; - } elseif (TestSuite::getBaseTestCase($test_case) == 'testsuite') { - $this->test_cases[] = new $test_case(); - } else { - $this->test_cases[] = $test_case; - } - } - - /** - * Builds a test suite from a library of test cases. - * The new suite is composed into this one. - * @param string $test_file File name of library with - * test case classes. - * @access public - */ - function addFile($test_file) { - $extractor = new SimpleFileLoader(); - $this->add($extractor->load($test_file)); - } - - /** - * Delegates to a visiting collector to add test - * files. - * @param string $path Path to scan from. - * @param SimpleCollector $collector Directory scanner. - * @access public - */ - function collect($path, $collector) { - $collector->collect($this, $path); - } - - /** - * Invokes run() on all of the held test cases, instantiating - * them if necessary. - * @param SimpleReporter $reporter Current test reporter. - * @access public - */ - function run($reporter) { - $reporter->paintGroupStart($this->getLabel(), $this->getSize()); - for ($i = 0, $count = count($this->test_cases); $i < $count; $i++) { - if (is_string($this->test_cases[$i])) { - $class = $this->test_cases[$i]; - - // moodle hack start - need to do this before the constructor call, because of FakeDBUnitTestCase. - global $CFG; - if (is_subclass_of($class, 'FakeDBUnitTestCase')) { - // Do not execute this test because the test tables system no longer works, reporting it as exception - $reporter->paintError("Unit test \"{$class}\" of type FakeDBUnitTestCase no longer supported. Must be migrated to UnitTestCaseUsingDatabase."); - continue; - } - if (is_subclass_of($class, 'UnitTestCaseUsingDatabase') && empty($CFG->unittestprefix)) { - // Do not execute this test because $CFG->unittestprefix is not set, but it will be required. - $reporter->paintSkip("Unit test \"{$class}\" of type UnitTestCaseUsingDatabase skipped. Must define different, non-conflicting \$CFG->unittestprefix to be runnable."); - continue; - } - // moodle hack end - - $test = new $class(); - $test->run($reporter); - unset($test); - } else { - $this->test_cases[$i]->run($reporter); - } - } - $reporter->paintGroupEnd($this->getLabel()); - return $reporter->getStatus(); - } - - /** - * Number of contained test cases. - * @return integer Total count of cases in the group. - * @access public - */ - function getSize() { - $count = 0; - foreach ($this->test_cases as $case) { - if (is_string($case)) { - if (! SimpleTest::isIgnored($case)) { - $count++; - } - } else { - $count += $case->getSize(); - } - } - return $count; - } - - /** - * Test to see if a class is derived from the - * SimpleTestCase class. - * @param string $class Class name. - * @access public - */ - static function getBaseTestCase($class) { - while ($class = get_parent_class($class)) { - $class = strtolower($class); - if ($class == 'simpletestcase' || $class == 'testsuite') { - return $class; - } - } - return false; - } -} - -/** - * This is a failing group test for when a test suite hasn't - * loaded properly. - * @package SimpleTest - * @subpackage UnitTester - */ -class BadTestSuite { - private $label; - private $error; - - /** - * Sets the name of the test suite and error message. - * @param string $label Name sent at the start and end - * of the test. - * @access public - */ - function BadTestSuite($label, $error) { - $this->label = $label; - $this->error = $error; - } - - /** - * Accessor for the test name for subclasses. - * @return string Name of the test. - * @access public - */ - function getLabel() { - return $this->label; - } - - /** - * Sends a single error to the reporter. - * @param SimpleReporter $reporter Current test reporter. - * @access public - */ - function run($reporter) { - $reporter->paintGroupStart($this->getLabel(), $this->getSize()); - $reporter->paintFail('Bad TestSuite [' . $this->getLabel() . - '] with error [' . $this->error . ']'); - $reporter->paintGroupEnd($this->getLabel()); - return $reporter->getStatus(); - } - - /** - * Number of contained test cases. Always zero. - * @return integer Total count of cases in the group. - * @access public - */ - function getSize() { - return 0; - } -} -?> diff --git a/lib/simpletestlib/tidy_parser.php b/lib/simpletestlib/tidy_parser.php deleted file mode 100644 index 3d8b4b2ac7d..00000000000 --- a/lib/simpletestlib/tidy_parser.php +++ /dev/null @@ -1,382 +0,0 @@ -free(); - } - - /** - * Frees up any references so as to allow the PHP garbage - * collection from unset() to work. - */ - private function free() { - unset($this->page); - $this->forms = array(); - $this->labels = array(); - } - - /** - * This builder is only available if the 'tidy' extension is loaded. - * @return boolean True if available. - */ - function can() { - return extension_loaded('tidy'); - } - - /** - * Reads the raw content the page using HTML Tidy. - * @param $response SimpleHttpResponse Fetched response. - * @return SimplePage Newly parsed page. - */ - function parse($response) { - $this->page = new SimplePage($response); - $tidied = tidy_parse_string($input = $this->insertGuards($response->getContent()), - array('output-xml' => false, 'wrap' => '0', 'indent' => 'no'), - 'latin1'); - $this->walkTree($tidied->html()); - $this->attachLabels($this->widgets_by_id, $this->labels); - $this->page->setForms($this->forms); - $page = $this->page; - $this->free(); - return $page; - } - - /** - * Stops HTMLTidy stripping content that we wish to preserve. - * @param string The raw html. - * @return string The html with guard tags inserted. - */ - private function insertGuards($html) { - return $this->insertEmptyTagGuards($this->insertTextareaSimpleWhitespaceGuards($html)); - } - - /** - * Removes the extra content added during the parse stage - * in order to preserve content we don't want stripped - * out by HTMLTidy. - * @param string The raw html. - * @return string The html with guard tags removed. - */ - private function stripGuards($html) { - return $this->stripTextareaWhitespaceGuards($this->stripEmptyTagGuards($html)); - } - - /** - * HTML tidy strips out empty tags such as