Fixing file upload params ($_FILES) normalization. Closes #75
[akelos.git] / vendor / simpletest / test_case.php
blobf7b6732d709b646ceea0866b46e0071d63a1ce18
1 <?php
2 /**
3 * Base include file for SimpleTest
4 * @package SimpleTest
5 * @subpackage UnitTester
6 * @version $Id: test_case.php,v 1.21 2006/02/06 06:13:43 lastcraft Exp $
7 */
9 /**#@+
10 * Includes SimpleTest files and defined the root constant
11 * for dependent libraries.
13 require_once(dirname(__FILE__) . '/invoker.php');
14 require_once(dirname(__FILE__) . '/errors.php');
15 require_once(dirname(__FILE__) . '/compatibility.php');
16 require_once(dirname(__FILE__) . '/scorer.php');
17 require_once(dirname(__FILE__) . '/expectation.php');
18 require_once(dirname(__FILE__) . '/dumper.php');
19 require_once(dirname(__FILE__) . '/simpletest.php');
20 if (version_compare(phpversion(), '5') >= 0) {
21 require_once(dirname(__FILE__) . '/exceptions.php');
22 require_once(dirname(__FILE__) . '/reflection_php5.php');
23 } else {
24 require_once(dirname(__FILE__) . '/reflection_php4.php');
26 if (! defined('SIMPLE_TEST')) {
27 /**
28 * @ignore
30 define('SIMPLE_TEST', dirname(__FILE__) . '/');
32 /**#@-*/
34 /**
35 * Basic test case. This is the smallest unit of a test
36 * suite. It searches for
37 * all methods that start with the the string "test" and
38 * runs them. Working test cases extend this class.
39 * @package SimpleTest
40 * @subpackage UnitTester
42 class SimpleTestCase {
43 var $_label = false;
44 var $_reporter;
45 var $_observers;
47 /**
48 * Sets up the test with no display.
49 * @param string $label If no test name is given then
50 * the class name is used.
51 * @access public
53 function SimpleTestCase($label = false) {
54 if ($label) {
55 $this->_label = $label;
59 /**
60 * Accessor for the test name for subclasses.
61 * @return string Name of the test.
62 * @access public
64 function getLabel() {
65 return $this->_label ? $this->_label : get_class($this);
68 /**
69 * Used to invoke the single tests.
70 * @return SimpleInvoker Individual test runner.
71 * @access public
73 function &createInvoker() {
74 $invoker = &new SimpleErrorTrappingInvoker(new SimpleInvoker($this));
75 if (version_compare(phpversion(), '5') >= 0) {
76 $invoker = &new SimpleExceptionTrappingInvoker($invoker);
78 return $invoker;
81 /**
82 * Uses reflection to run every method within itself
83 * starting with the string "test" unless a method
84 * is specified.
85 * @param SimpleReporter $reporter Current test reporter.
86 * @access public
88 function run(&$reporter) {
89 SimpleTest::setCurrent($this);
90 $this->_reporter = &$reporter;
91 $this->_reporter->paintCaseStart($this->getLabel());
92 foreach ($this->getTests() as $method) {
93 if ($this->_reporter->shouldInvoke($this->getLabel(), $method)) {
94 $invoker = &$this->_reporter->createInvoker($this->createInvoker());
95 $invoker->before($method);
96 $invoker->invoke($method);
97 $invoker->after($method);
100 $this->_reporter->paintCaseEnd($this->getLabel());
101 unset($this->_reporter);
102 return $reporter->getStatus();
106 * Gets a list of test names. Normally that will
107 * be all internal methods that start with the
108 * name "test". This method should be overridden
109 * if you want a different rule.
110 * @return array List of test names.
111 * @access public
113 function getTests() {
114 $methods = array();
115 foreach (get_class_methods(get_class($this)) as $method) {
116 if ($this->_isTest($method)) {
117 $methods[] = $method;
120 return $methods;
124 * Tests to see if the method is a test that should
125 * be run. Currently any method that starts with 'test'
126 * is a candidate unless it is the constructor.
127 * @param string $method Method name to try.
128 * @return boolean True if test method.
129 * @access protected
131 function _isTest($method) {
132 if (strtolower(substr($method, 0, 4)) == 'test') {
133 return ! SimpleTestCompatibility::isA($this, strtolower($method));
135 return false;
139 * Announces the start of the test.
140 * @param string $method Test method just started.
141 * @access public
143 function before($method) {
144 $this->_reporter->paintMethodStart($method);
145 $this->_observers = array();
149 * Sets up unit test wide variables at the start
150 * of each test method. To be overridden in
151 * actual user test cases.
152 * @access public
154 function setUp() {
158 * Clears the data set in the setUp() method call.
159 * To be overridden by the user in actual user test cases.
160 * @access public
162 function tearDown() {
166 * Announces the end of the test. Includes private clean up.
167 * @param string $method Test method just finished.
168 * @access public
170 function after($method) {
171 for ($i = 0; $i < count($this->_observers); $i++) {
172 $this->_observers[$i]->atTestEnd($method);
174 $this->_reporter->paintMethodEnd($method);
178 * Sets up an observer for the test end.
179 * @param object $observer Must have atTestEnd()
180 * method.
181 * @access public
183 function tell(&$observer) {
184 $this->_observers[] = &$observer;
188 * Sends a pass event with a message.
189 * @param string $message Message to send.
190 * @access public
192 function pass($message = "Pass") {
193 if (! isset($this->_reporter)) {
194 trigger_error('Can only make assertions within test methods');
196 $this->_reporter->paintPass(
197 $message . $this->getAssertionLine());
198 return true;
202 * Sends a fail event with a message.
203 * @param string $message Message to send.
204 * @access public
206 function fail($message = "Fail") {
207 if (! isset($this->_reporter)) {
208 trigger_error('Can only make assertions within test methods');
210 $this->_reporter->paintFail(
211 $message . $this->getAssertionLine());
212 return false;
216 * Formats a PHP error and dispatches it to the
217 * reporter.
218 * @param integer $severity PHP error code.
219 * @param string $message Text of error.
220 * @param string $file File error occoured in.
221 * @param integer $line Line number of error.
222 * @access public
224 function error($severity, $message, $file, $line) {
225 if (! isset($this->_reporter)) {
226 trigger_error('Can only make assertions within test methods');
228 $this->_reporter->paintError(
229 "Unexpected PHP error [$message] severity [$severity] in [$file] line [$line]");
233 * Formats an exception and dispatches it to the
234 * reporter.
235 * @param Exception $exception Object thrown.
236 * @access public
238 function exception($exception) {
239 $this->_reporter->paintError(
240 'Unexpected exception of type [' . get_class($exception) .
241 '] with message ['. $exception->getMessage() .
242 '] in ['. $exception->getFile() .
243 '] line [' . $exception->getLine() . ']');
247 * Sends a user defined event to the test reporter.
248 * This is for small scale extension where
249 * both the test case and either the reporter or
250 * display are subclassed.
251 * @param string $type Type of event.
252 * @param mixed $payload Object or message to deliver.
253 * @access public
255 function signal($type, &$payload) {
256 if (! isset($this->_reporter)) {
257 trigger_error('Can only make assertions within test methods');
259 $this->_reporter->paintSignal($type, $payload);
263 * Cancels any outstanding errors.
264 * @access public
266 function swallowErrors() {
267 $queue = &SimpleErrorQueue::instance();
268 $queue->clear();
272 * Runs an expectation directly, for extending the
273 * tests with new expectation classes.
274 * @param SimpleExpectation $expectation Expectation subclass.
275 * @param mixed $compare Value to compare.
276 * @param string $message Message to display.
277 * @return boolean True on pass
278 * @access public
280 function assert(&$expectation, $compare, $message = '%s') {
281 return $this->assertTrue(
282 $expectation->test($compare),
283 sprintf($message, $expectation->overlayMessage($compare)));
287 * @deprecated
289 function assertExpectation(&$expectation, $compare, $message = '%s') {
290 return $this->assert($expectation, $compare, $message);
294 * Called from within the test methods to register
295 * passes and failures.
296 * @param boolean $result Pass on true.
297 * @param string $message Message to display describing
298 * the test state.
299 * @return boolean True on pass
300 * @access public
302 function assertTrue($result, $message = false) {
303 if (! $message) {
304 $message = 'True assertion got ' . ($result ? 'True' : 'False');
306 if ($result) {
307 return $this->pass($message);
308 } else {
309 return $this->fail($message);
314 * Will be true on false and vice versa. False
315 * is the PHP definition of false, so that null,
316 * empty strings, zero and an empty array all count
317 * as false.
318 * @param boolean $result Pass on false.
319 * @param string $message Message to display.
320 * @return boolean True on pass
321 * @access public
323 function assertFalse($result, $message = false) {
324 if (! $message) {
325 $message = 'False assertion got ' . ($result ? 'True' : 'False');
327 return $this->assertTrue(! $result, $message);
331 * Uses a stack trace to find the line of an assertion.
332 * @param string $format String formatting.
333 * @param array $stack Stack frames top most first. Only
334 * needed if not using the PHP
335 * backtrace function.
336 * @return string Line number of first assert*
337 * method embedded in format string.
338 * @access public
340 function getAssertionLine($stack = false) {
341 if ($stack === false) {
342 $stack = SimpleTestCompatibility::getStackTrace();
344 return SimpleDumper::getFormattedAssertionLine($stack);
348 * Sends a formatted dump of a variable to the
349 * test suite for those emergency debugging
350 * situations.
351 * @param mixed $variable Variable to display.
352 * @param string $message Message to display.
353 * @return mixed The original variable.
354 * @access public
356 function dump($variable, $message = false) {
357 $formatted = SimpleDumper::dump($variable);
358 if ($message) {
359 $formatted = $message . "\n" . $formatted;
361 $this->_reporter->paintFormattedMessage($formatted);
362 return $variable;
366 * Dispatches a text message straight to the
367 * test suite. Useful for status bar displays.
368 * @param string $message Message to show.
369 * @access public
371 function sendMessage($message) {
372 $this->_reporter->PaintMessage($message);
376 * Accessor for the number of subtests.
377 * @return integer Number of test cases.
378 * @access public
379 * @static
381 function getSize() {
382 return 1;
387 * This is a composite test class for combining
388 * test cases and other RunnableTest classes into
389 * a group test.
390 * @package SimpleTest
391 * @subpackage UnitTester
393 class GroupTest {
394 var $_label;
395 var $_test_cases;
396 var $_old_track_errors;
397 var $_xdebug_is_enabled;
400 * Sets the name of the test suite.
401 * @param string $label Name sent at the start and end
402 * of the test.
403 * @access public
405 function GroupTest($label = false) {
406 $this->_label = $label ? $label : get_class($this);
407 $this->_test_cases = array();
408 $this->_old_track_errors = ini_get('track_errors');
409 $this->_xdebug_is_enabled = function_exists('xdebug_is_enabled') ?
410 xdebug_is_enabled() : false;
414 * Accessor for the test name for subclasses.
415 * @return string Name of the test.
416 * @access public
418 function getLabel() {
419 return $this->_label;
423 * Adds a test into the suite. Can be either a group
424 * test or some other unit test.
425 * @param SimpleTestCase $test_case Suite or individual test
426 * case implementing the
427 * runnable test interface.
428 * @access public
430 function addTestCase(&$test_case) {
431 $this->_test_cases[] = &$test_case;
435 * Adds a test into the suite by class name. The class will
436 * be instantiated as needed.
437 * @param SimpleTestCase $test_case Suite or individual test
438 * case implementing the
439 * runnable test interface.
440 * @access public
442 function addTestClass($class) {
443 if ($this->_getBaseTestCase($class) == 'grouptest') {
444 $this->_test_cases[] = &new $class();
445 } else {
446 $this->_test_cases[] = $class;
451 * Builds a group test from a library of test cases.
452 * The new group is composed into this one.
453 * @param string $test_file File name of library with
454 * test case classes.
455 * @access public
457 function addTestFile($test_file) {
458 $existing_classes = get_declared_classes();
459 if ($error = $this->_requireWithError($test_file)) {
460 $this->addTestCase(new BadGroupTest($test_file, $error));
461 return;
463 $classes = $this->_selectRunnableTests($existing_classes, get_declared_classes());
464 if (count($classes) == 0) {
465 $this->addTestCase(new BadGroupTest($test_file, "No runnable test cases in [$test_file]"));
466 return;
468 $group = &$this->_createGroupFromClasses($test_file, $classes);
469 $this->addTestCase($group);
473 * Requires a source file recording any syntax errors.
474 * @param string $file File name to require in.
475 * @return string/boolean An error message on failure or false
476 * if no errors.
477 * @access private
479 function _requireWithError($file) {
480 $this->_enableErrorReporting();
481 include($file);
482 $error = isset($php_errormsg) ? $php_errormsg : false;
483 $this->_disableErrorReporting();
484 $self_inflicted_errors = array(
485 'Assigning the return value of new by reference is deprecated',
486 'var: Deprecated. Please use the public/private/protected modifiers');
487 if (in_array($error, $self_inflicted_errors)) {
488 return false;
490 return $error;
494 * Sets up detection of parse errors. Note that XDebug
495 * interferes with this and has to be disabled. This is
496 * to make sure the correct error code is returned
497 * from unattended scripts.
498 * @access private
500 function _enableErrorReporting() {
501 if ($this->_xdebug_is_enabled) {
502 xdebug_disable();
504 ini_set('track_errors', true);
508 * Resets detection of parse errors to their old values.
509 * This is to make sure the correct error code is returned
510 * from unattended scripts.
511 * @access private
513 function _disableErrorReporting() {
514 ini_set('track_errors', $this->_old_track_errors);
515 if ($this->_xdebug_is_enabled) {
516 xdebug_enable();
521 * Calculates the incoming test cases from a before
522 * and after list of loaded classes. Skips abstract
523 * classes.
524 * @param array $existing_classes Classes before require().
525 * @param array $new_classes Classes after require().
526 * @return array New classes which are test
527 * cases that shouldn't be ignored.
528 * @access private
530 function _selectRunnableTests($existing_classes, $new_classes) {
531 $classes = array();
532 foreach ($new_classes as $class) {
533 if (in_array($class, $existing_classes)) {
534 continue;
536 if ($this->_getBaseTestCase($class)) {
537 $reflection = new SimpleReflection($class);
538 if ($reflection->isAbstract()) {
539 SimpleTest::ignore($class);
541 $classes[] = $class;
544 return $classes;
548 * Builds a group test from a class list.
549 * @param string $title Title of new group.
550 * @param array $classes Test classes.
551 * @return GroupTest Group loaded with the new
552 * test cases.
553 * @access private
555 function &_createGroupFromClasses($title, $classes) {
556 SimpleTest::ignoreParentsIfIgnored($classes);
557 $group = &new GroupTest($title);
558 foreach ($classes as $class) {
559 if (! SimpleTest::isIgnored($class)) {
560 $group->addTestClass($class);
563 return $group;
567 * Test to see if a class is derived from the
568 * SimpleTestCase class.
569 * @param string $class Class name.
570 * @access private
572 function _getBaseTestCase($class) {
573 while ($class = get_parent_class($class)) {
574 $class = strtolower($class);
575 if ($class == "simpletestcase" || $class == "grouptest") {
576 return $class;
579 return false;
583 * Delegates to a visiting collector to add test
584 * files.
585 * @param string $path Path to scan from.
586 * @param SimpleCollector $collector Directory scanner.
587 * @access public
589 function collect($path, &$collector) {
590 $collector->collect($this, $path);
594 * Invokes run() on all of the held test cases, instantiating
595 * them if necessary.
596 * @param SimpleReporter $reporter Current test reporter.
597 * @access public
599 function run(&$reporter) {
600 $reporter->paintGroupStart($this->getLabel(), $this->getSize());
601 for ($i = 0, $count = count($this->_test_cases); $i < $count; $i++) {
602 if (is_string($this->_test_cases[$i])) {
603 $class = $this->_test_cases[$i];
604 $test = &new $class();
605 $test->run($reporter);
606 } else {
607 $this->_test_cases[$i]->run($reporter);
610 $reporter->paintGroupEnd($this->getLabel());
611 return $reporter->getStatus();
615 * Number of contained test cases.
616 * @return integer Total count of cases in the group.
617 * @access public
619 function getSize() {
620 $count = 0;
621 foreach ($this->_test_cases as $case) {
622 if (is_string($case)) {
623 $count++;
624 } else {
625 $count += $case->getSize();
628 return $count;
633 * This is a failing group test for when a test suite hasn't
634 * loaded properly.
635 * @package SimpleTest
636 * @subpackage UnitTester
638 class BadGroupTest {
639 var $_label;
640 var $_error;
643 * Sets the name of the test suite and error message.
644 * @param string $label Name sent at the start and end
645 * of the test.
646 * @access public
648 function BadGroupTest($label, $error) {
649 $this->_label = $label;
650 $this->_error = $error;
654 * Accessor for the test name for subclasses.
655 * @return string Name of the test.
656 * @access public
658 function getLabel() {
659 return $this->_label;
663 * Sends a single error to the reporter.
664 * @param SimpleReporter $reporter Current test reporter.
665 * @access public
667 function run(&$reporter) {
668 $reporter->paintGroupStart($this->getLabel(), $this->getSize());
669 $reporter->paintFail('Bad GroupTest [' . $this->getLabel() .
670 '] with error [' . $this->_error . ']');
671 $reporter->paintGroupEnd($this->getLabel());
672 return $reporter->getStatus();
676 * Number of contained test cases. Always zero.
677 * @return integer Total count of cases in the group.
678 * @access public
680 function getSize() {
681 return 0;