diff options
Diffstat (limited to '3rdparty/simpletest/xml.php')
-rwxr-xr-x | 3rdparty/simpletest/xml.php | 647 |
1 files changed, 647 insertions, 0 deletions
diff --git a/3rdparty/simpletest/xml.php b/3rdparty/simpletest/xml.php new file mode 100755 index 00000000000..54fb6f5b16d --- /dev/null +++ b/3rdparty/simpletest/xml.php @@ -0,0 +1,647 @@ +<?php +/** + * base include file for SimpleTest + * @package SimpleTest + * @subpackage UnitTester + * @version $Id: xml.php 1787 2008-04-26 20:35:39Z pp11 $ + */ + +/**#@+ + * 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 { + private $indent; + private $namespace; + + /** + * Sets up indentation and namespace. + * @param string $namespace Namespace to add to each tag. + * @param string $indent Indenting to add on each nesting. + * @access public + */ + function __construct($namespace = false, $indent = ' ') { + parent::__construct(); + $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 + */ + 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('&', '<', '>', '"', '''), + $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); + } + + /** + * Paints pass as XML. + * @param string $message Message to encode. + * @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"; + } + + /** + * Paints failure as XML. + * @param string $message Message to encode. + * @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 error as XML. + * @param string $message Message to encode. + * @access public + */ + function paintError($message) { + parent::paintError($message); + print $this->getIndent(1); + print "<" . $this->namespace . "exception>"; + print $this->toParsedXml($message); + print "</" . $this->namespace . "exception>\n"; + } + + /** + * Paints exception as XML. + * @param Exception $exception Exception to encode. + * @access public + */ + function paintException($exception) { + parent::paintException($exception); + print $this->getIndent(1); + print "<" . $this->namespace . "exception>"; + $message = 'Unexpected exception of type [' . get_class($exception) . + '] with message ['. $exception->getMessage() . + '] in ['. $exception->getFile() . + ' line ' . $exception->getLine() . ']'; + print $this->toParsedXml($message); + print "</" . $this->namespace . "exception>\n"; + } + + /** + * Paints the skipping message and tag. + * @param string $message Text to display in skip tag. + * @access public + */ + function paintSkip($message) { + parent::paintSkip($message); + print $this->getIndent(1); + print "<" . $this->namespace . "skip>"; + print $this->toParsedXml($message); + print "</" . $this->namespace . "skip>\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 + * privateiable 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 { + private $name; + private $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 + */ + 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 { + private $listener; + private $expat; + private $tag_stack; + private $in_content_tag; + private $content; + private $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 + */ + 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, 'defaultContent'); + return $expat; + } + + /** + * Opens a new test nesting level. + * @return NestedXmlTag The group, case or method tag + * to start. + * @access private + */ + protected 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 + */ + protected function &getCurrentNestingTag() { + return $this->tag_stack[0]; + } + + /** + * Ends a nesting tag. + * @return NestedXmlTag The group, case or method tag + * just finished. + * @access private + */ + protected 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 + */ + protected function isLeaf($tag) { + return in_array($tag, array( + 'NAME', 'PASS', 'FAIL', 'EXCEPTION', 'SKIP', '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 + */ + 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 + */ + 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->paintError($this->content); + } elseif ($tag == 'SKIP') { + $this->listener->paintSkip($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 + */ + 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 + */ + protected function defaultContent($expat, $default) { + } +} +?> |