[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/simpletestlib/ -> xml.php (source)

   1  <?php
   2      /**
   3       *    base include file for SimpleTest
   4       *    @package    SimpleTest
   5       *    @subpackage    UnitTester
   6       *    @version    $Id$
   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->_popNestingTag();
 601                  $nesting_tag->paintEnd($this->_listener);
 602              } elseif ($tag == 'NAME') {
 603                  $nesting_tag = &$this->_getCurrentNestingTag();
 604                  $nesting_tag->setName($this->_content);
 605                  $nesting_tag->paintStart($this->_listener);
 606              } elseif ($tag == 'PASS') {
 607                  $this->_listener->paintPass($this->_content);
 608              } elseif ($tag == 'FAIL') {
 609                  $this->_listener->paintFail($this->_content);
 610              } elseif ($tag == 'EXCEPTION') {
 611                  $this->_listener->paintError($this->_content);
 612              } elseif ($tag == 'SKIP') {
 613                  $this->_listener->paintSkip($this->_content);
 614              } elseif ($tag == 'SIGNAL') {
 615                  $this->_listener->paintSignal(
 616                          $this->_attributes['TYPE'],
 617                          unserialize($this->_content));
 618              } elseif ($tag == 'MESSAGE') {
 619                  $this->_listener->paintMessage($this->_content);
 620              } elseif ($tag == 'FORMATTED') {
 621                  $this->_listener->paintFormattedMessage($this->_content);
 622              }
 623          }
 624  
 625          /**
 626           *    Content between start and end elements.
 627           *    @param resource $expat     Parser handle.
 628           *    @param string $text        Usually output messages.
 629           *    @access protected
 630           */
 631          function _addContent($expat, $text) {
 632              if ($this->_in_content_tag) {
 633                  $this->_content .= $text;
 634              }
 635              return true;
 636          }
 637  
 638          /**
 639           *    XML and Doctype handler. Discards all such content.
 640           *    @param resource $expat     Parser handle.
 641           *    @param string $default     Text of default content.
 642           *    @access protected
 643           */
 644          function _default($expat, $default) {
 645          }
 646      }
 647  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7