[ Index ]

PHP Cross Reference of Limb3

title

Body

[close]

/tests_runner/lib/simpletest/ -> xml.php (source)

   1  <?php
   2      /**

   3       *    base include file for SimpleTest

   4       *    @package    SimpleTest

   5       *    @subpackage    UnitTester

   6       *    @version    $Id: xml.php 5999 2007-06-18 13:13:08Z pachanga $

   7       */
   8  
   9      /**#@+

  10       *    include other SimpleTest class files

  11       */
  12      require_once(dirname(__FILE__) . '/scorer.php');
  13      /**#@-*/

  14  
  15      /**

  16       *    Creates the XML needed for remote communication

  17       *    by SimpleTest.

  18       *      @package SimpleTest

  19       *      @subpackage UnitTester

  20       */
  21      class XmlReporter extends SimpleReporter {
  22          var $_indent;
  23          var $_namespace;
  24  
  25          /**

  26           *    Sets up indentation and namespace.

  27           *    @param string $namespace        Namespace to add to each tag.

  28           *    @param string $indent           Indenting to add on each nesting.

  29           *    @access public

  30           */
  31          function XmlReporter($namespace = false, $indent = '  ') {
  32              $this->SimpleReporter();
  33              $this->_namespace = ($namespace ? $namespace . ':' : '');
  34              $this->_indent = $indent;
  35          }
  36  
  37          /**

  38           *    Calculates the pretty printing indent level

  39           *    from the current level of nesting.

  40           *    @param integer $offset  Extra indenting level.

  41           *    @return string          Leading space.

  42           *    @access protected

  43           */
  44          function _getIndent($offset = 0) {
  45              return str_repeat(
  46                      $this->_indent,
  47                      count($this->getTestList()) + $offset);
  48          }
  49  
  50          /**

  51           *    Converts character string to parsed XML

  52           *    entities string.

  53           *    @param string text        Unparsed character data.

  54           *    @return string            Parsed character data.

  55           *    @access public

  56           */
  57          function toParsedXml($text) {
  58              return str_replace(
  59                      array('&', '<', '>', '"', '\''),
  60                      array('&amp;', '&lt;', '&gt;', '&quot;', '&apos;'),
  61                      $text);
  62          }
  63  
  64          /**

  65           *    Paints the start of a group test.

  66           *    @param string $test_name   Name of test that is starting.

  67           *    @param integer $size       Number of test cases starting.

  68           *    @access public

  69           */
  70          function paintGroupStart($test_name, $size) {
  71              parent::paintGroupStart($test_name, $size);
  72              print $this->_getIndent();
  73              print "<" . $this->_namespace . "group size=\"$size\">\n";
  74              print $this->_getIndent(1);
  75              print "<" . $this->_namespace . "name>" .
  76                      $this->toParsedXml($test_name) .
  77                      "</" . $this->_namespace . "name>\n";
  78          }
  79  
  80          /**

  81           *    Paints the end of a group test.

  82           *    @param string $test_name   Name of test that is ending.

  83           *    @access public

  84           */
  85          function paintGroupEnd($test_name) {
  86              print $this->_getIndent();
  87              print "</" . $this->_namespace . "group>\n";
  88              parent::paintGroupEnd($test_name);
  89          }
  90  
  91          /**

  92           *    Paints the start of a test case.

  93           *    @param string $test_name   Name of test that is starting.

  94           *    @access public

  95           */
  96          function paintCaseStart($test_name) {
  97              parent::paintCaseStart($test_name);
  98              print $this->_getIndent();
  99              print "<" . $this->_namespace . "case>\n";
 100              print $this->_getIndent(1);
 101              print "<" . $this->_namespace . "name>" .
 102                      $this->toParsedXml($test_name) .
 103                      "</" . $this->_namespace . "name>\n";
 104          }
 105  
 106          /**

 107           *    Paints the end of a test case.

 108           *    @param string $test_name   Name of test that is ending.

 109           *    @access public

 110           */
 111          function paintCaseEnd($test_name) {
 112              print $this->_getIndent();
 113              print "</" . $this->_namespace . "case>\n";
 114              parent::paintCaseEnd($test_name);
 115          }
 116  
 117          /**

 118           *    Paints the start of a test method.

 119           *    @param string $test_name   Name of test that is starting.

 120           *    @access public

 121           */
 122          function paintMethodStart($test_name) {
 123              parent::paintMethodStart($test_name);
 124              print $this->_getIndent();
 125              print "<" . $this->_namespace . "test>\n";
 126              print $this->_getIndent(1);
 127              print "<" . $this->_namespace . "name>" .
 128                      $this->toParsedXml($test_name) .
 129                      "</" . $this->_namespace . "name>\n";
 130          }
 131  
 132          /**

 133           *    Paints the end of a test method.

 134           *    @param string $test_name   Name of test that is ending.

 135           *    @param integer $progress   Number of test cases ending.

 136           *    @access public

 137           */
 138          function paintMethodEnd($test_name) {
 139              print $this->_getIndent();
 140              print "</" . $this->_namespace . "test>\n";
 141              parent::paintMethodEnd($test_name);
 142          }
 143  
 144          /**

 145           *    Paints pass as XML.

 146           *    @param string $message        Message to encode.

 147           *    @access public

 148           */
 149          function paintPass($message) {
 150              parent::paintPass($message);
 151              print $this->_getIndent(1);
 152              print "<" . $this->_namespace . "pass>";
 153              print $this->toParsedXml($message);
 154              print "</" . $this->_namespace . "pass>\n";
 155          }
 156  
 157          /**

 158           *    Paints failure as XML.

 159           *    @param string $message        Message to encode.

 160           *    @access public

 161           */
 162          function paintFail($message) {
 163              parent::paintFail($message);
 164              print $this->_getIndent(1);
 165              print "<" . $this->_namespace . "fail>";
 166              print $this->toParsedXml($message);
 167              print "</" . $this->_namespace . "fail>\n";
 168          }
 169  
 170          /**

 171           *    Paints error as XML.

 172           *    @param string $message        Message to encode.

 173           *    @access public

 174           */
 175          function paintError($message) {
 176              parent::paintError($message);
 177              print $this->_getIndent(1);
 178              print "<" . $this->_namespace . "exception>";
 179              print $this->toParsedXml($message);
 180              print "</" . $this->_namespace . "exception>\n";
 181          }
 182  
 183          /**

 184           *    Paints exception as XML.

 185           *    @param Exception $exception    Exception to encode.

 186           *    @access public

 187           */
 188          function paintException($exception) {
 189              parent::paintException($exception);
 190              print $this->_getIndent(1);
 191              print "<" . $this->_namespace . "exception>";
 192              $message = 'Unexpected exception of type [' . get_class($exception) .
 193                      '] with message ['. $exception->getMessage() .
 194                      '] in ['. $exception->getFile() .
 195                      ' line ' . $exception->getLine() . ']';
 196              print $this->toParsedXml($message);
 197              print "</" . $this->_namespace . "exception>\n";
 198          }
 199  
 200          /**

 201           *    Paints the skipping message and tag.

 202           *    @param string $message        Text to display in skip tag.

 203           *    @access public

 204           */
 205          function paintSkip($message) {
 206              parent::paintSkip($message);
 207              print $this->_getIndent(1);
 208              print "<" . $this->_namespace . "skip>";
 209              print $this->toParsedXml($message);
 210              print "</" . $this->_namespace . "skip>\n";
 211          }
 212  
 213          /**

 214           *    Paints a simple supplementary message.

 215           *    @param string $message        Text to display.

 216           *    @access public

 217           */
 218          function paintMessage($message) {
 219              parent::paintMessage($message);
 220              print $this->_getIndent(1);
 221              print "<" . $this->_namespace . "message>";
 222              print $this->toParsedXml($message);
 223              print "</" . $this->_namespace . "message>\n";
 224          }
 225  
 226          /**

 227           *    Paints a formatted ASCII message such as a

 228           *    variable dump.

 229           *    @param string $message        Text to display.

 230           *    @access public

 231           */
 232          function paintFormattedMessage($message) {
 233              parent::paintFormattedMessage($message);
 234              print $this->_getIndent(1);
 235              print "<" . $this->_namespace . "formatted>";
 236              print "<![CDATA[$message]]>";
 237              print "</" . $this->_namespace . "formatted>\n";
 238          }
 239  
 240          /**

 241           *    Serialises the event object.

 242           *    @param string $type        Event type as text.

 243           *    @param mixed $payload      Message or object.

 244           *    @access public

 245           */
 246          function paintSignal($type, &$payload) {
 247              parent::paintSignal($type, $payload);
 248              print $this->_getIndent(1);
 249              print "<" . $this->_namespace . "signal type=\"$type\">";
 250              print "<![CDATA[" . serialize($payload) . "]]>";
 251              print "</" . $this->_namespace . "signal>\n";
 252          }
 253  
 254          /**

 255           *    Paints the test document header.

 256           *    @param string $test_name     First test top level

 257           *                                 to start.

 258           *    @access public

 259           *    @abstract

 260           */
 261          function paintHeader($test_name) {
 262              if (! SimpleReporter::inCli()) {
 263                  header('Content-type: text/xml');
 264              }
 265              print "<?xml version=\"1.0\"";
 266              if ($this->_namespace) {
 267                  print " xmlns:" . $this->_namespace .
 268                          "=\"www.lastcraft.com/SimpleTest/Beta3/Report\"";
 269              }
 270              print "?>\n";
 271              print "<" . $this->_namespace . "run>\n";
 272          }
 273  
 274          /**

 275           *    Paints the test document footer.

 276           *    @param string $test_name        The top level test.

 277           *    @access public

 278           *    @abstract

 279           */
 280          function paintFooter($test_name) {
 281              print "</" . $this->_namespace . "run>\n";
 282          }
 283      }
 284  
 285      /**

 286       *    Accumulator for incoming tag. Holds the

 287       *    incoming test structure information for

 288       *    later dispatch to the reporter.

 289       *      @package SimpleTest

 290       *      @subpackage UnitTester

 291       */
 292      class NestingXmlTag {
 293          var $_name;
 294          var $_attributes;
 295  
 296          /**

 297           *    Sets the basic test information except

 298           *    the name.

 299           *    @param hash $attributes   Name value pairs.

 300           *    @access public

 301           */
 302          function NestingXmlTag($attributes) {
 303              $this->_name = false;
 304              $this->_attributes = $attributes;
 305          }
 306  
 307          /**

 308           *    Sets the test case/method name.

 309           *    @param string $name        Name of test.

 310           *    @access public

 311           */
 312          function setName($name) {
 313              $this->_name = $name;
 314          }
 315  
 316          /**

 317           *    Accessor for name.

 318           *    @return string        Name of test.

 319           *    @access public

 320           */
 321          function getName() {
 322              return $this->_name;
 323          }
 324  
 325          /**

 326           *    Accessor for attributes.

 327           *    @return hash        All attributes.

 328           *    @access protected

 329           */
 330          function _getAttributes() {
 331              return $this->_attributes;
 332          }
 333      }
 334  
 335      /**

 336       *    Accumulator for incoming method tag. Holds the

 337       *    incoming test structure information for

 338       *    later dispatch to the reporter.

 339       *      @package SimpleTest

 340       *      @subpackage UnitTester

 341       */
 342      class NestingMethodTag extends NestingXmlTag {
 343  
 344          /**

 345           *    Sets the basic test information except

 346           *    the name.

 347           *    @param hash $attributes   Name value pairs.

 348           *    @access public

 349           */
 350          function NestingMethodTag($attributes) {
 351              $this->NestingXmlTag($attributes);
 352          }
 353  
 354          /**

 355           *    Signals the appropriate start event on the

 356           *    listener.

 357           *    @param SimpleReporter $listener    Target for events.

 358           *    @access public

 359           */
 360          function paintStart(&$listener) {
 361              $listener->paintMethodStart($this->getName());
 362          }
 363  
 364          /**

 365           *    Signals the appropriate end event on the

 366           *    listener.

 367           *    @param SimpleReporter $listener    Target for events.

 368           *    @access public

 369           */
 370          function paintEnd(&$listener) {
 371              $listener->paintMethodEnd($this->getName());
 372          }
 373      }
 374  
 375      /**

 376       *    Accumulator for incoming case tag. Holds the

 377       *    incoming test structure information for

 378       *    later dispatch to the reporter.

 379       *      @package SimpleTest

 380       *      @subpackage UnitTester

 381       */
 382      class NestingCaseTag extends NestingXmlTag {
 383  
 384          /**

 385           *    Sets the basic test information except

 386           *    the name.

 387           *    @param hash $attributes   Name value pairs.

 388           *    @access public

 389           */
 390          function NestingCaseTag($attributes) {
 391              $this->NestingXmlTag($attributes);
 392          }
 393  
 394          /**

 395           *    Signals the appropriate start event on the

 396           *    listener.

 397           *    @param SimpleReporter $listener    Target for events.

 398           *    @access public

 399           */
 400          function paintStart(&$listener) {
 401              $listener->paintCaseStart($this->getName());
 402          }
 403  
 404          /**

 405           *    Signals the appropriate end event on the

 406           *    listener.

 407           *    @param SimpleReporter $listener    Target for events.

 408           *    @access public

 409           */
 410          function paintEnd(&$listener) {
 411              $listener->paintCaseEnd($this->getName());
 412          }
 413      }
 414  
 415      /**

 416       *    Accumulator for incoming group tag. Holds the

 417       *    incoming test structure information for

 418       *    later dispatch to the reporter.

 419       *      @package SimpleTest

 420       *      @subpackage UnitTester

 421       */
 422      class NestingGroupTag extends NestingXmlTag {
 423  
 424          /**

 425           *    Sets the basic test information except

 426           *    the name.

 427           *    @param hash $attributes   Name value pairs.

 428           *    @access public

 429           */
 430          function NestingGroupTag($attributes) {
 431              $this->NestingXmlTag($attributes);
 432          }
 433  
 434          /**

 435           *    Signals the appropriate start event on the

 436           *    listener.

 437           *    @param SimpleReporter $listener    Target for events.

 438           *    @access public

 439           */
 440          function paintStart(&$listener) {
 441              $listener->paintGroupStart($this->getName(), $this->getSize());
 442          }
 443  
 444          /**

 445           *    Signals the appropriate end event on the

 446           *    listener.

 447           *    @param SimpleReporter $listener    Target for events.

 448           *    @access public

 449           */
 450          function paintEnd(&$listener) {
 451              $listener->paintGroupEnd($this->getName());
 452          }
 453  
 454          /**

 455           *    The size in the attributes.

 456           *    @return integer     Value of size attribute or zero.

 457           *    @access public

 458           */
 459          function getSize() {
 460              $attributes = $this->_getAttributes();
 461              if (isset($attributes['SIZE'])) {
 462                  return (integer)$attributes['SIZE'];
 463              }
 464              return 0;
 465          }
 466      }
 467  
 468      /**

 469       *    Parser for importing the output of the XmlReporter.

 470       *    Dispatches that output to another reporter.

 471       *      @package SimpleTest

 472       *      @subpackage UnitTester

 473       */
 474      class SimpleTestXmlParser {
 475          var $_listener;
 476          var $_expat;
 477          var $_tag_stack;
 478          var $_in_content_tag;
 479          var $_content;
 480          var $_attributes;
 481  
 482          /**

 483           *    Loads a listener with the SimpleReporter

 484           *    interface.

 485           *    @param SimpleReporter $listener   Listener of tag events.

 486           *    @access public

 487           */
 488          function SimpleTestXmlParser(&$listener) {
 489              $this->_listener = &$listener;
 490              $this->_expat = &$this->_createParser();
 491              $this->_tag_stack = array();
 492              $this->_in_content_tag = false;
 493              $this->_content = '';
 494              $this->_attributes = array();
 495          }
 496  
 497          /**

 498           *    Parses a block of XML sending the results to

 499           *    the listener.

 500           *    @param string $chunk        Block of text to read.

 501           *    @return boolean             True if valid XML.

 502           *    @access public

 503           */
 504          function parse($chunk) {
 505              if (! xml_parse($this->_expat, $chunk)) {
 506                  trigger_error('XML parse error with ' .
 507                          xml_error_string(xml_get_error_code($this->_expat)));
 508                  return false;
 509              }
 510              return true;
 511          }
 512  
 513          /**

 514           *    Sets up expat as the XML parser.

 515           *    @return resource        Expat handle.

 516           *    @access protected

 517           */
 518          function &_createParser() {
 519              $expat = xml_parser_create();
 520              xml_set_object($expat, $this);
 521              xml_set_element_handler($expat, '_startElement', '_endElement');
 522              xml_set_character_data_handler($expat, '_addContent');
 523              xml_set_default_handler($expat, '_default');
 524              return $expat;
 525          }
 526  
 527          /**

 528           *    Opens a new test nesting level.

 529           *    @return NestedXmlTag     The group, case or method tag

 530           *                             to start.

 531           *    @access private

 532           */
 533          function _pushNestingTag($nested) {
 534              array_unshift($this->_tag_stack, $nested);
 535          }
 536  
 537          /**

 538           *    Accessor for current test structure tag.

 539           *    @return NestedXmlTag     The group, case or method tag

 540           *                             being parsed.

 541           *    @access private

 542           */
 543          function &_getCurrentNestingTag() {
 544              return $this->_tag_stack[0];
 545          }
 546  
 547          /**

 548           *    Ends a nesting tag.

 549           *    @return NestedXmlTag     The group, case or method tag

 550           *                             just finished.

 551           *    @access private

 552           */
 553          function _popNestingTag() {
 554              return array_shift($this->_tag_stack);
 555          }
 556  
 557          /**

 558           *    Test if tag is a leaf node with only text content.

 559           *    @param string $tag        XML tag name.

 560           *    @return @boolean          True if leaf, false if nesting.

 561           *    @private

 562           */
 563          function _isLeaf($tag) {
 564              return in_array($tag, array(
 565                      'NAME', 'PASS', 'FAIL', 'EXCEPTION', 'SKIP', 'MESSAGE', 'FORMATTED', 'SIGNAL'));
 566          }
 567  
 568          /**

 569           *    Handler for start of event element.

 570           *    @param resource $expat     Parser handle.

 571           *    @param string $tag         Element name.

 572           *    @param hash $attributes    Name value pairs.

 573           *                               Attributes without content

 574           *                               are marked as true.

 575           *    @access protected

 576           */
 577          function _startElement($expat, $tag, $attributes) {
 578              $this->_attributes = $attributes;
 579              if ($tag == 'GROUP') {
 580                  $this->_pushNestingTag(new NestingGroupTag($attributes));
 581              } elseif ($tag == 'CASE') {
 582                  $this->_pushNestingTag(new NestingCaseTag($attributes));
 583              } elseif ($tag == 'TEST') {
 584                  $this->_pushNestingTag(new NestingMethodTag($attributes));
 585              } elseif ($this->_isLeaf($tag)) {
 586                  $this->_in_content_tag = true;
 587                  $this->_content = '';
 588              }
 589          }
 590  
 591          /**

 592           *    End of element event.

 593           *    @param resource $expat     Parser handle.

 594           *    @param string $tag         Element name.

 595           *    @access protected

 596           */
 597          function _endElement($expat, $tag) {
 598              $this->_in_content_tag = false;
 599              if (in_array($tag, array('GROUP', 'CASE', 'TEST'))) {
 600                  $nesting_tag = $this->