cakephp2-php8/vendors/simpletest/xml.php
pies da79dff7d7 - merged in Brego's SimpleTest implementation, fixed some of the tests (the Folder test fails to delete one of the test directories on my system, so it's not perfectly clean yet)
- Dispatcher sets a Controller::here variable with the real URL used to access the page, so that tag generators can that use an url (linkTo and formTag for example) use the real url, not guess it from the controller and action names which often fails
- Log class works more reliably and a LogError() shortcut function was added
- Nstring class added, to store string-related functions (there are just four yet, including a random password generator and an string-to-array splitter
- SimpleTest library (with Rephlux) included in /vendors; I've tweaked SimpleScorer::inCli() function, because it didn't work on my setup, it should work everywhere now (it checks for empty REQUEST_METHOD, which should only be empty in CLI)

git-svn-id: https://svn.cakephp.org/repo/trunk/cake@248 3807eeeb-6ff5-0310-8944-8be069107fe0
2005-06-18 23:26:35 +00:00

615 lines
20 KiB
PHP

<?php
/**
* base include file for SimpleTest
* @package SimpleTest
* @subpackage UnitTester
* @version $Id$
*/
/**#@+
* include other SimpleTest class files
*/
require_once(dirname(__FILE__) . '/scorer.php');
/**#@-*/
/**
* Creates the XML needed for remote communication
* by SimpleTest.
* @package SimpleTest
* @subpackage UnitTester
*/
class XmlReporter extends SimpleReporter {
var $_indent;
var $_namespace;
/**
* Does nothing yet.
* @access public
*/
function XmlReporter($namespace = false, $indent = ' ') {
$this->SimpleReporter();
$this->_namespace = ($namespace ? $namespace . ':' : '');
$this->_indent = $indent;
}
/**
* Calculates the pretty printing indent level
* from the current level of nesting.
* @param integer $offset Extra indenting level.
* @return string Leading space.
* @access protected
*/
function _getIndent($offset = 0) {
return str_repeat(
$this->_indent,
count($this->getTestList()) + $offset);
}
/**
* Converts character string to parsed XML
* entities string.
* @param string text Unparsed character data.
* @return string Parsed character data.
* @access public
*/
function toParsedXml($text) {
return str_replace(
array('&', '<', '>', '"', '\''),
array('&amp;', '&lt;', '&gt;', '&quot;', '&apos;'),
$text);
}
/**
* Paints the start of a group test.
* @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) {
parent::paintGroupStart($test_name, $size);
print $this->_getIndent();
print "<" . $this->_namespace . "group size=\"$size\">\n";
print $this->_getIndent(1);
print "<" . $this->_namespace . "name>" .
$this->toParsedXml($test_name) .
"</" . $this->_namespace . "name>\n";
}
/**
* Paints the end of a group test.
* @param string $test_name Name of test that is ending.
* @access public
*/
function paintGroupEnd($test_name) {
print $this->_getIndent();
print "</" . $this->_namespace . "group>\n";
parent::paintGroupEnd($test_name);
}
/**
* Paints the start of a test case.
* @param string $test_name Name of test that is starting.
* @access public
*/
function paintCaseStart($test_name) {
parent::paintCaseStart($test_name);
print $this->_getIndent();
print "<" . $this->_namespace . "case>\n";
print $this->_getIndent(1);
print "<" . $this->_namespace . "name>" .
$this->toParsedXml($test_name) .
"</" . $this->_namespace . "name>\n";
}
/**
* Paints the end of a test case.
* @param string $test_name Name of test that is ending.
* @access public
*/
function paintCaseEnd($test_name) {
print $this->_getIndent();
print "</" . $this->_namespace . "case>\n";
parent::paintCaseEnd($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) {
parent::paintMethodStart($test_name);
print $this->_getIndent();
print "<" . $this->_namespace . "test>\n";
print $this->_getIndent(1);
print "<" . $this->_namespace . "name>" .
$this->toParsedXml($test_name) .
"</" . $this->_namespace . "name>\n";
}
/**
* Paints the end of a test method.
* @param string $test_name Name of test that is ending.
* @param integer $progress Number of test cases ending.
* @access public
*/
function paintMethodEnd($test_name) {
print $this->_getIndent();
print "</" . $this->_namespace . "test>\n";
parent::paintMethodEnd($test_name);
}
/**
* Increments the pass count.
* @param string $message Message is ignored.
* @access public
*/
function paintPass($message) {
parent::paintPass($message);
print $this->_getIndent(1);
print "<" . $this->_namespace . "pass>";
print $this->toParsedXml($message);
print "</" . $this->_namespace . "pass>\n";
}
/**
* Increments the fail count.
* @param string $message Message is ignored.
* @access public
*/
function paintFail($message) {
parent::paintFail($message);
print $this->_getIndent(1);
print "<" . $this->_namespace . "fail>";
print $this->toParsedXml($message);
print "</" . $this->_namespace . "fail>\n";
}
/**
* Paints a PHP error or exception.
* @param string $message Message is ignored.
* @access public
* @abstract
*/
function paintException($message) {
parent::paintException($message);
print $this->_getIndent(1);
print "<" . $this->_namespace . "exception>";
print $this->toParsedXml($message);
print "</" . $this->_namespace . "exception>\n";
}
/**
* Paints a simple supplementary message.
* @param string $message Text to display.
* @access public
*/
function paintMessage($message) {
parent::paintMessage($message);
print $this->_getIndent(1);
print "<" . $this->_namespace . "message>";
print $this->toParsedXml($message);
print "</" . $this->_namespace . "message>\n";
}
/**
* Paints a formatted ASCII message such as a
* variable dump.
* @param string $message Text to display.
* @access public
*/
function paintFormattedMessage($message) {
parent::paintFormattedMessage($message);
print $this->_getIndent(1);
print "<" . $this->_namespace . "formatted>";
print "<![CDATA[$message]]>";
print "</" . $this->_namespace . "formatted>\n";
}
/**
* Serialises the event object.
* @param string $type Event type as text.
* @param mixed $payload Message or object.
* @access public
*/
function paintSignal($type, &$payload) {
parent::paintSignal($type, $payload);
print $this->_getIndent(1);
print "<" . $this->_namespace . "signal type=\"$type\">";
print "<![CDATA[" . serialize($payload) . "]]>";
print "</" . $this->_namespace . "signal>\n";
}
/**
* Paints the test document header.
* @param string $test_name First test top level
* to start.
* @access public
* @abstract
*/
function paintHeader($test_name) {
if (! SimpleReporter::inCli()) {
header('Content-type: text/xml');
}
print "<?xml version=\"1.0\"";
if ($this->_namespace) {
print " xmlns:" . $this->_namespace .
"=\"www.lastcraft.com/SimpleTest/Beta3/Report\"";
}
print "?>\n";
print "<" . $this->_namespace . "run>\n";
}
/**
* Paints the test document footer.
* @param string $test_name The top level test.
* @access public
* @abstract
*/
function paintFooter($test_name) {
print "</" . $this->_namespace . "run>\n";
}
}
/**
* Accumulator for incoming tag. Holds the
* incoming test structure information for
* later dispatch to the reporter.
* @package SimpleTest
* @subpackage UnitTester
*/
class NestingXmlTag {
var $_name;
var $_attributes;
/**
* Sets the basic test information except
* the name.
* @param hash $attributes Name value pairs.
* @access public
*/
function NestingXmlTag($attributes) {
$this->_name = false;
$this->_attributes = $attributes;
}
/**
* Sets the test case/method name.
* @param string $name Name of test.
* @access public
*/
function setName($name) {
$this->_name = $name;
}
/**
* Accessor for name.
* @return string Name of test.
* @access public
*/
function getName() {
return $this->_name;
}
/**
* Accessor for attributes.
* @return hash All attributes.
* @access protected
*/
function _getAttributes() {
return $this->_attributes;
}
}
/**
* Accumulator for incoming method tag. Holds the
* incoming test structure information for
* later dispatch to the reporter.
* @package SimpleTest
* @subpackage UnitTester
*/
class NestingMethodTag extends NestingXmlTag {
/**
* Sets the basic test information except
* the name.
* @param hash $attributes Name value pairs.
* @access public
*/
function NestingMethodTag($attributes) {
$this->NestingXmlTag($attributes);
}
/**
* Signals the appropriate start event on the
* listener.
* @param SimpleReporter $listener Target for events.
* @access public
*/
function paintStart(&$listener) {
$listener->paintMethodStart($this->getName());
}
/**
* Signals the appropriate end event on the
* listener.
* @param SimpleReporter $listener Target for events.
* @access public
*/
function paintEnd(&$listener) {
$listener->paintMethodEnd($this->getName());
}
}
/**
* Accumulator for incoming case tag. Holds the
* incoming test structure information for
* later dispatch to the reporter.
* @package SimpleTest
* @subpackage UnitTester
*/
class NestingCaseTag extends NestingXmlTag {
/**
* Sets the basic test information except
* the name.
* @param hash $attributes Name value pairs.
* @access public
*/
function NestingCaseTag($attributes) {
$this->NestingXmlTag($attributes);
}
/**
* Signals the appropriate start event on the
* listener.
* @param SimpleReporter $listener Target for events.
* @access public
*/
function paintStart(&$listener) {
$listener->paintCaseStart($this->getName());
}
/**
* Signals the appropriate end event on the
* listener.
* @param SimpleReporter $listener Target for events.
* @access public
*/
function paintEnd(&$listener) {
$listener->paintCaseEnd($this->getName());
}
}
/**
* Accumulator for incoming group tag. Holds the
* incoming test structure information for
* later dispatch to the reporter.
* @package SimpleTest
* @subpackage UnitTester
*/
class NestingGroupTag extends NestingXmlTag {
/**
* Sets the basic test information except
* the name.
* @param hash $attributes Name value pairs.
* @access public
*/
function NestingGroupTag($attributes) {
$this->NestingXmlTag($attributes);
}
/**
* Signals the appropriate start event on the
* listener.
* @param SimpleReporter $listener Target for events.
* @access public
*/
function paintStart(&$listener) {
$listener->paintGroupStart($this->getName(), $this->getSize());
}
/**
* Signals the appropriate end event on the
* listener.
* @param SimpleReporter $listener Target for events.
* @access public
*/
function paintEnd(&$listener) {
$listener->paintGroupEnd($this->getName());
}
/**
* The size in the attributes.
* @return integer Value of size attribute or zero.
* @access public
*/
function getSize() {
$attributes = $this->_getAttributes();
if (isset($attributes['SIZE'])) {
return (integer)$attributes['SIZE'];
}
return 0;
}
}
/**
* Parser for importing the output of the XmlReporter.
* Dispatches that output to another reporter.
* @package SimpleTest
* @subpackage UnitTester
*/
class SimpleTestXmlParser {
var $_listener;
var $_expat;
var $_tag_stack;
var $_in_content_tag;
var $_content;
var $_attributes;
/**
* Loads a listener with the SimpleReporter
* interface.
* @param SimpleReporter $listener Listener of tag events.
* @access public
*/
function SimpleTestXmlParser(&$listener) {
$this->_listener = &$listener;
$this->_expat = &$this->_createParser();
$this->_tag_stack = array();
$this->_in_content_tag = false;
$this->_content = '';
$this->_attributes = array();
}
/**
* Parses a block of XML sending the results to
* the listener.
* @param string $chunk Block of text to read.
* @return boolean True if valid XML.
* @access public
*/
function parse($chunk) {
if (! xml_parse($this->_expat, $chunk)) {
trigger_error('XML parse error with ' .
xml_error_string(xml_get_error_code($this->_expat)));
return false;
}
return true;
}
/**
* Sets up expat as the XML parser.
* @return resource Expat handle.
* @access protected
*/
function &_createParser() {
$expat = xml_parser_create();
xml_set_object($expat, $this);
xml_set_element_handler($expat, '_startElement', '_endElement');
xml_set_character_data_handler($expat, '_addContent');
xml_set_default_handler($expat, '_default');
return $expat;
}
/**
* Opens a new test nesting level.
* @return NestedXmlTag The group, case or method tag
* to start.
* @access private
*/
function _pushNestingTag($nested) {
array_unshift($this->_tag_stack, $nested);
}
/**
* Accessor for current test structure tag.
* @return NestedXmlTag The group, case or method tag
* being parsed.
* @access private
*/
function &_getCurrentNestingTag() {
return $this->_tag_stack[0];
}
/**
* Ends a nesting tag.
* @return NestedXmlTag The group, case or method tag
* just finished.
* @access private
*/
function _popNestingTag() {
return array_shift($this->_tag_stack);
}
/**
* Test if tag is a leaf node with only text content.
* @param string $tag XML tag name.
* @return @boolean True if leaf, false if nesting.
* @private
*/
function _isLeaf($tag) {
return in_array(
$tag,
array('NAME', 'PASS', 'FAIL', 'EXCEPTION', 'MESSAGE', 'FORMATTED', 'SIGNAL'));
}
/**
* Handler for start of event element.
* @param resource $expat Parser handle.
* @param string $tag Element name.
* @param hash $attributes Name value pairs.
* Attributes without content
* are marked as true.
* @access protected
*/
function _startElement($expat, $tag, $attributes) {
$this->_attributes = $attributes;
if ($tag == 'GROUP') {
$this->_pushNestingTag(new NestingGroupTag($attributes));
} elseif ($tag == 'CASE') {
$this->_pushNestingTag(new NestingCaseTag($attributes));
} elseif ($tag == 'TEST') {
$this->_pushNestingTag(new NestingMethodTag($attributes));
} elseif ($this->_isLeaf($tag)) {
$this->_in_content_tag = true;
$this->_content = '';
}
}
/**
* End of element event.
* @param resource $expat Parser handle.
* @param string $tag Element name.
* @access protected
*/
function _endElement($expat, $tag) {
$this->_in_content_tag = false;
if (in_array($tag, array('GROUP', 'CASE', 'TEST'))) {
$nesting_tag = $this->_popNestingTag();
$nesting_tag->paintEnd($this->_listener);
} elseif ($tag == 'NAME') {
$nesting_tag = &$this->_getCurrentNestingTag();
$nesting_tag->setName($this->_content);
$nesting_tag->paintStart($this->_listener);
} elseif ($tag == 'PASS') {
$this->_listener->paintPass($this->_content);
} elseif ($tag == 'FAIL') {
$this->_listener->paintFail($this->_content);
} elseif ($tag == 'EXCEPTION') {
$this->_listener->paintException($this->_content);
} elseif ($tag == 'SIGNAL') {
$this->_listener->paintSignal(
$this->_attributes['TYPE'],
unserialize($this->_content));
} elseif ($tag == 'MESSAGE') {
$this->_listener->paintMessage($this->_content);
} elseif ($tag == 'FORMATTED') {
$this->_listener->paintFormattedMessage($this->_content);
}
}
/**
* Content between start and end elements.
* @param resource $expat Parser handle.
* @param string $text Usually output messages.
* @access protected
*/
function _addContent($expat, $text) {
if ($this->_in_content_tag) {
$this->_content .= $text;
}
return true;
}
/**
* XML and Doctype handler. Discards all such content.
* @param resource $expat Parser handle.
* @param string $default Text of default content.
* @access protected
*/
function _default($expat, $default) {
}
}
?>