summaryrefslogtreecommitdiff
path: root/tests/test_tools/simpletest/xml.php
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_tools/simpletest/xml.php')
-rw-r--r--tests/test_tools/simpletest/xml.php615
1 files changed, 615 insertions, 0 deletions
diff --git a/tests/test_tools/simpletest/xml.php b/tests/test_tools/simpletest/xml.php
new file mode 100644
index 00000000..dd007d41
--- /dev/null
+++ b/tests/test_tools/simpletest/xml.php
@@ -0,0 +1,615 @@
+<?php
+ /**
+ * base include file for SimpleTest
+ * @package SimpleTest
+ * @subpackage UnitTester
+ * @version $Id: xml.php,v 1.20 2004/08/04 22:09:39 lastcraft Exp $
+ */
+
+ /**#@+
+ * 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 {
+ protected $_indent;
+ protected $_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 {
+ protected $_name;
+ protected $_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 {
+ protected $_listener;
+ protected $_expat;
+ protected $_tag_stack;
+ protected $_in_content_tag;
+ protected $_content;
+ protected $_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) {
+ }
+ }
+?>