Removed 'base_path' from AkInstaller->setInstalledVersion because Ak:make_dir can...
[akelos.git] / vendor / simpletest / xml.php
blob647643968883bc0166cf88c76aa78aefef9b4f3d
1 <?php
2 /**
3 * base include file for SimpleTest
4 * @package SimpleTest
5 * @subpackage UnitTester
6 * @version $Id: xml.php,v 1.22 2006/02/06 06:05:18 lastcraft Exp $
7 */
9 /**#@+
10 * include other SimpleTest class files
12 require_once(dirname(__FILE__) . '/scorer.php');
13 /**#@-*/
15 /**
16 * Creates the XML needed for remote communication
17 * by SimpleTest.
18 * @package SimpleTest
19 * @subpackage UnitTester
21 class XmlReporter extends SimpleReporter {
22 var $_indent;
23 var $_namespace;
25 /**
26 * Does nothing yet.
27 * @access public
29 function XmlReporter($namespace = false, $indent = ' ') {
30 $this->SimpleReporter();
31 $this->_namespace = ($namespace ? $namespace . ':' : '');
32 $this->_indent = $indent;
35 /**
36 * Calculates the pretty printing indent level
37 * from the current level of nesting.
38 * @param integer $offset Extra indenting level.
39 * @return string Leading space.
40 * @access protected
42 function _getIndent($offset = 0) {
43 return str_repeat(
44 $this->_indent,
45 count($this->getTestList()) + $offset);
48 /**
49 * Converts character string to parsed XML
50 * entities string.
51 * @param string text Unparsed character data.
52 * @return string Parsed character data.
53 * @access public
55 function toParsedXml($text) {
56 return str_replace(
57 array('&', '<', '>', '"', '\''),
58 array('&amp;', '&lt;', '&gt;', '&quot;', '&apos;'),
59 $text);
62 /**
63 * Paints the start of a group test.
64 * @param string $test_name Name of test that is starting.
65 * @param integer $size Number of test cases starting.
66 * @access public
68 function paintGroupStart($test_name, $size) {
69 parent::paintGroupStart($test_name, $size);
70 print $this->_getIndent();
71 print "<" . $this->_namespace . "group size=\"$size\">\n";
72 print $this->_getIndent(1);
73 print "<" . $this->_namespace . "name>" .
74 $this->toParsedXml($test_name) .
75 "</" . $this->_namespace . "name>\n";
78 /**
79 * Paints the end of a group test.
80 * @param string $test_name Name of test that is ending.
81 * @access public
83 function paintGroupEnd($test_name) {
84 print $this->_getIndent();
85 print "</" . $this->_namespace . "group>\n";
86 parent::paintGroupEnd($test_name);
89 /**
90 * Paints the start of a test case.
91 * @param string $test_name Name of test that is starting.
92 * @access public
94 function paintCaseStart($test_name) {
95 parent::paintCaseStart($test_name);
96 print $this->_getIndent();
97 print "<" . $this->_namespace . "case>\n";
98 print $this->_getIndent(1);
99 print "<" . $this->_namespace . "name>" .
100 $this->toParsedXml($test_name) .
101 "</" . $this->_namespace . "name>\n";
105 * Paints the end of a test case.
106 * @param string $test_name Name of test that is ending.
107 * @access public
109 function paintCaseEnd($test_name) {
110 print $this->_getIndent();
111 print "</" . $this->_namespace . "case>\n";
112 parent::paintCaseEnd($test_name);
116 * Paints the start of a test method.
117 * @param string $test_name Name of test that is starting.
118 * @access public
120 function paintMethodStart($test_name) {
121 parent::paintMethodStart($test_name);
122 print $this->_getIndent();
123 print "<" . $this->_namespace . "test>\n";
124 print $this->_getIndent(1);
125 print "<" . $this->_namespace . "name>" .
126 $this->toParsedXml($test_name) .
127 "</" . $this->_namespace . "name>\n";
131 * Paints the end of a test method.
132 * @param string $test_name Name of test that is ending.
133 * @param integer $progress Number of test cases ending.
134 * @access public
136 function paintMethodEnd($test_name) {
137 print $this->_getIndent();
138 print "</" . $this->_namespace . "test>\n";
139 parent::paintMethodEnd($test_name);
143 * Increments the pass count.
144 * @param string $message Message is ignored.
145 * @access public
147 function paintPass($message) {
148 parent::paintPass($message);
149 print $this->_getIndent(1);
150 print "<" . $this->_namespace . "pass>";
151 print $this->toParsedXml($message);
152 print "</" . $this->_namespace . "pass>\n";
156 * Increments the fail count.
157 * @param string $message Message is ignored.
158 * @access public
160 function paintFail($message) {
161 parent::paintFail($message);
162 print $this->_getIndent(1);
163 print "<" . $this->_namespace . "fail>";
164 print $this->toParsedXml($message);
165 print "</" . $this->_namespace . "fail>\n";
169 * Paints a PHP error or exception.
170 * @param string $message Message is ignored.
171 * @access public
172 * @abstract
174 function paintError($message) {
175 parent::paintError($message);
176 print $this->_getIndent(1);
177 print "<" . $this->_namespace . "exception>";
178 print $this->toParsedXml($message);
179 print "</" . $this->_namespace . "exception>\n";
183 * Paints a simple supplementary message.
184 * @param string $message Text to display.
185 * @access public
187 function paintMessage($message) {
188 parent::paintMessage($message);
189 print $this->_getIndent(1);
190 print "<" . $this->_namespace . "message>";
191 print $this->toParsedXml($message);
192 print "</" . $this->_namespace . "message>\n";
196 * Paints a formatted ASCII message such as a
197 * variable dump.
198 * @param string $message Text to display.
199 * @access public
201 function paintFormattedMessage($message) {
202 parent::paintFormattedMessage($message);
203 print $this->_getIndent(1);
204 print "<" . $this->_namespace . "formatted>";
205 print "<![CDATA[$message]]>";
206 print "</" . $this->_namespace . "formatted>\n";
210 * Serialises the event object.
211 * @param string $type Event type as text.
212 * @param mixed $payload Message or object.
213 * @access public
215 function paintSignal($type, &$payload) {
216 parent::paintSignal($type, $payload);
217 print $this->_getIndent(1);
218 print "<" . $this->_namespace . "signal type=\"$type\">";
219 print "<![CDATA[" . serialize($payload) . "]]>";
220 print "</" . $this->_namespace . "signal>\n";
224 * Paints the test document header.
225 * @param string $test_name First test top level
226 * to start.
227 * @access public
228 * @abstract
230 function paintHeader($test_name) {
231 if (! SimpleReporter::inCli()) {
232 header('Content-type: text/xml');
234 print "<?xml version=\"1.0\"";
235 if ($this->_namespace) {
236 print " xmlns:" . $this->_namespace .
237 "=\"www.lastcraft.com/SimpleTest/Beta3/Report\"";
239 print "?>\n";
240 print "<" . $this->_namespace . "run>\n";
244 * Paints the test document footer.
245 * @param string $test_name The top level test.
246 * @access public
247 * @abstract
249 function paintFooter($test_name) {
250 print "</" . $this->_namespace . "run>\n";
255 * Accumulator for incoming tag. Holds the
256 * incoming test structure information for
257 * later dispatch to the reporter.
258 * @package SimpleTest
259 * @subpackage UnitTester
261 class NestingXmlTag {
262 var $_name;
263 var $_attributes;
266 * Sets the basic test information except
267 * the name.
268 * @param hash $attributes Name value pairs.
269 * @access public
271 function NestingXmlTag($attributes) {
272 $this->_name = false;
273 $this->_attributes = $attributes;
277 * Sets the test case/method name.
278 * @param string $name Name of test.
279 * @access public
281 function setName($name) {
282 $this->_name = $name;
286 * Accessor for name.
287 * @return string Name of test.
288 * @access public
290 function getName() {
291 return $this->_name;
295 * Accessor for attributes.
296 * @return hash All attributes.
297 * @access protected
299 function _getAttributes() {
300 return $this->_attributes;
305 * Accumulator for incoming method tag. Holds the
306 * incoming test structure information for
307 * later dispatch to the reporter.
308 * @package SimpleTest
309 * @subpackage UnitTester
311 class NestingMethodTag extends NestingXmlTag {
314 * Sets the basic test information except
315 * the name.
316 * @param hash $attributes Name value pairs.
317 * @access public
319 function NestingMethodTag($attributes) {
320 $this->NestingXmlTag($attributes);
324 * Signals the appropriate start event on the
325 * listener.
326 * @param SimpleReporter $listener Target for events.
327 * @access public
329 function paintStart(&$listener) {
330 $listener->paintMethodStart($this->getName());
334 * Signals the appropriate end event on the
335 * listener.
336 * @param SimpleReporter $listener Target for events.
337 * @access public
339 function paintEnd(&$listener) {
340 $listener->paintMethodEnd($this->getName());
345 * Accumulator for incoming case tag. Holds the
346 * incoming test structure information for
347 * later dispatch to the reporter.
348 * @package SimpleTest
349 * @subpackage UnitTester
351 class NestingCaseTag extends NestingXmlTag {
354 * Sets the basic test information except
355 * the name.
356 * @param hash $attributes Name value pairs.
357 * @access public
359 function NestingCaseTag($attributes) {
360 $this->NestingXmlTag($attributes);
364 * Signals the appropriate start event on the
365 * listener.
366 * @param SimpleReporter $listener Target for events.
367 * @access public
369 function paintStart(&$listener) {
370 $listener->paintCaseStart($this->getName());
374 * Signals the appropriate end event on the
375 * listener.
376 * @param SimpleReporter $listener Target for events.
377 * @access public
379 function paintEnd(&$listener) {
380 $listener->paintCaseEnd($this->getName());
385 * Accumulator for incoming group tag. Holds the
386 * incoming test structure information for
387 * later dispatch to the reporter.
388 * @package SimpleTest
389 * @subpackage UnitTester
391 class NestingGroupTag extends NestingXmlTag {
394 * Sets the basic test information except
395 * the name.
396 * @param hash $attributes Name value pairs.
397 * @access public
399 function NestingGroupTag($attributes) {
400 $this->NestingXmlTag($attributes);
404 * Signals the appropriate start event on the
405 * listener.
406 * @param SimpleReporter $listener Target for events.
407 * @access public
409 function paintStart(&$listener) {
410 $listener->paintGroupStart($this->getName(), $this->getSize());
414 * Signals the appropriate end event on the
415 * listener.
416 * @param SimpleReporter $listener Target for events.
417 * @access public
419 function paintEnd(&$listener) {
420 $listener->paintGroupEnd($this->getName());
424 * The size in the attributes.
425 * @return integer Value of size attribute or zero.
426 * @access public
428 function getSize() {
429 $attributes = $this->_getAttributes();
430 if (isset($attributes['SIZE'])) {
431 return (integer)$attributes['SIZE'];
433 return 0;
438 * Parser for importing the output of the XmlReporter.
439 * Dispatches that output to another reporter.
440 * @package SimpleTest
441 * @subpackage UnitTester
443 class SimpleTestXmlParser {
444 var $_listener;
445 var $_expat;
446 var $_tag_stack;
447 var $_in_content_tag;
448 var $_content;
449 var $_attributes;
452 * Loads a listener with the SimpleReporter
453 * interface.
454 * @param SimpleReporter $listener Listener of tag events.
455 * @access public
457 function SimpleTestXmlParser(&$listener) {
458 $this->_listener = &$listener;
459 $this->_expat = &$this->_createParser();
460 $this->_tag_stack = array();
461 $this->_in_content_tag = false;
462 $this->_content = '';
463 $this->_attributes = array();
467 * Parses a block of XML sending the results to
468 * the listener.
469 * @param string $chunk Block of text to read.
470 * @return boolean True if valid XML.
471 * @access public
473 function parse($chunk) {
474 if (! xml_parse($this->_expat, $chunk)) {
475 trigger_error('XML parse error with ' .
476 xml_error_string(xml_get_error_code($this->_expat)));
477 return false;
479 return true;
483 * Sets up expat as the XML parser.
484 * @return resource Expat handle.
485 * @access protected
487 function &_createParser() {
488 $expat = xml_parser_create();
489 xml_set_object($expat, $this);
490 xml_set_element_handler($expat, '_startElement', '_endElement');
491 xml_set_character_data_handler($expat, '_addContent');
492 xml_set_default_handler($expat, '_default');
493 return $expat;
497 * Opens a new test nesting level.
498 * @return NestedXmlTag The group, case or method tag
499 * to start.
500 * @access private
502 function _pushNestingTag($nested) {
503 array_unshift($this->_tag_stack, $nested);
507 * Accessor for current test structure tag.
508 * @return NestedXmlTag The group, case or method tag
509 * being parsed.
510 * @access private
512 function &_getCurrentNestingTag() {
513 return $this->_tag_stack[0];
517 * Ends a nesting tag.
518 * @return NestedXmlTag The group, case or method tag
519 * just finished.
520 * @access private
522 function _popNestingTag() {
523 return array_shift($this->_tag_stack);
527 * Test if tag is a leaf node with only text content.
528 * @param string $tag XML tag name.
529 * @return @boolean True if leaf, false if nesting.
530 * @private
532 function _isLeaf($tag) {
533 return in_array($tag, array(
534 'NAME', 'PASS', 'FAIL', 'EXCEPTION', 'MESSAGE', 'FORMATTED', 'SIGNAL'));
538 * Handler for start of event element.
539 * @param resource $expat Parser handle.
540 * @param string $tag Element name.
541 * @param hash $attributes Name value pairs.
542 * Attributes without content
543 * are marked as true.
544 * @access protected
546 function _startElement($expat, $tag, $attributes) {
547 $this->_attributes = $attributes;
548 if ($tag == 'GROUP') {
549 $this->_pushNestingTag(new NestingGroupTag($attributes));
550 } elseif ($tag == 'CASE') {
551 $this->_pushNestingTag(new NestingCaseTag($attributes));
552 } elseif ($tag == 'TEST') {
553 $this->_pushNestingTag(new NestingMethodTag($attributes));
554 } elseif ($this->_isLeaf($tag)) {
555 $this->_in_content_tag = true;
556 $this->_content = '';
561 * End of element event.
562 * @param resource $expat Parser handle.
563 * @param string $tag Element name.
564 * @access protected
566 function _endElement($expat, $tag) {
567 $this->_in_content_tag = false;
568 if (in_array($tag, array('GROUP', 'CASE', 'TEST'))) {
569 $nesting_tag = $this->_popNestingTag();
570 $nesting_tag->paintEnd($this->_listener);
571 } elseif ($tag == 'NAME') {
572 $nesting_tag = &$this->_getCurrentNestingTag();
573 $nesting_tag->setName($this->_content);
574 $nesting_tag->paintStart($this->_listener);
575 } elseif ($tag == 'PASS') {
576 $this->_listener->paintPass($this->_content);
577 } elseif ($tag == 'FAIL') {
578 $this->_listener->paintFail($this->_content);
579 } elseif ($tag == 'EXCEPTION') {
580 $this->_listener->paintError($this->_content);
581 } elseif ($tag == 'SIGNAL') {
582 $this->_listener->paintSignal(
583 $this->_attributes['TYPE'],
584 unserialize($this->_content));
585 } elseif ($tag == 'MESSAGE') {
586 $this->_listener->paintMessage($this->_content);
587 } elseif ($tag == 'FORMATTED') {
588 $this->_listener->paintFormattedMessage($this->_content);
593 * Content between start and end elements.
594 * @param resource $expat Parser handle.
595 * @param string $text Usually output messages.
596 * @access protected
598 function _addContent($expat, $text) {
599 if ($this->_in_content_tag) {
600 $this->_content .= $text;
602 return true;
606 * XML and Doctype handler. Discards all such content.
607 * @param resource $expat Parser handle.
608 * @param string $default Text of default content.
609 * @access protected
611 function _default($expat, $default) {