Line # | Frequency | Source Line |
1 | | <?php |
2 | | /** |
3 | | * Global state for SimpleTest and kicker script in future versions. |
4 | | * @package SimpleTest |
5 | | * @subpackage UnitTester |
6 | | * @version $Id: simpletest.php 1672 2008-03-02 04:47:34Z edwardzyang $ |
7 | | */ |
8 | |
|
9 | | /**#@+ |
10 | | * include SimpleTest files |
11 | | */ |
12 | | if (version_compare(phpversion(), '5') >= 0) { |
13 | | require_once(dirname(__FILE__) . '/reflection_php5.php'); |
14 | | } else { |
15 | | require_once(dirname(__FILE__) . '/reflection_php4.php'); |
16 | | } |
17 | | require_once(dirname(__FILE__) . '/default_reporter.php'); |
18 | | require_once(dirname(__FILE__) . '/compatibility.php'); |
19 | | /**#@-*/ |
20 | |
|
21 | | /** |
22 | | * Registry and test context. Includes a few |
23 | | * global options that I'm slowly getting rid of. |
24 | | * @package SimpleTest |
25 | | * @subpackage UnitTester |
26 | | */ |
27 | | class SimpleTest { |
28 | |
|
29 | | /** |
30 | | * Reads the SimpleTest version from the release file. |
31 | | * @return string Version string. |
32 | | * @static |
33 | | * @access public |
34 | | */ |
35 | | function getVersion() { |
36 | | $content = file(dirname(__FILE__) . '/VERSION'); |
37 | | return trim($content[0]); |
38 | | } |
39 | |
|
40 | | /** |
41 | | * Sets the name of a test case to ignore, usually |
42 | | * because the class is an abstract case that should |
43 | | * not be run. Once PHP4 is dropped this will disappear |
44 | | * as a public method and "abstract" will rule. |
45 | | * @param string $class Add a class to ignore. |
46 | | * @static |
47 | | * @access public |
48 | | */ |
49 | | function ignore($class) { |
50 | | $registry = &SimpleTest::_getRegistry(); |
51 | | $registry['IgnoreList'][strtolower($class)] = true; |
52 | | } |
53 | |
|
54 | | /** |
55 | | * Scans the now complete ignore list, and adds |
56 | | * all parent classes to the list. If a class |
57 | | * is not a runnable test case, then it's parents |
58 | | * wouldn't be either. This is syntactic sugar |
59 | | * to cut down on ommissions of ignore()'s or |
60 | | * missing abstract declarations. This cannot |
61 | | * be done whilst loading classes wiithout forcing |
62 | | * a particular order on the class declarations and |
63 | | * the ignore() calls. It's just nice to have the ignore() |
64 | | * calls at the top of the file before the actual declarations. |
65 | | * @param array $classes Class names of interest. |
66 | | * @static |
67 | | * @access public |
68 | | */ |
69 | | function ignoreParentsIfIgnored($classes) { |
70 | | $registry = &SimpleTest::_getRegistry(); |
71 | | foreach ($classes as $class) { |
72 | | if (SimpleTest::isIgnored($class)) { |
73 | | $reflection = new SimpleReflection($class); |
74 | | if ($parent = $reflection->getParent()) { |
75 | | SimpleTest::ignore($parent); |
76 | | } |
77 | | } |
78 | | } |
79 | | } |
80 | |
|
81 | | /** |
82 | | * Puts the object to the global pool of 'preferred' objects |
83 | | * which can be retrieved with SimpleTest :: preferred() method. |
84 | | * Instances of the same class are overwritten. |
85 | | * @param object $object Preferred object |
86 | | * @static |
87 | | * @access public |
88 | | * @see preferred() |
89 | | */ |
90 | | function prefer(&$object) { |
91 | | $registry = &SimpleTest::_getRegistry(); |
92 | | $registry['Preferred'][] = &$object; |
93 | | } |
94 | |
|
95 | | /** |
96 | | * Retrieves 'preferred' objects from global pool. Class filter |
97 | | * can be applied in order to retrieve the object of the specific |
98 | | * class |
99 | | * @param array|string $classes Allowed classes or interfaces. |
100 | | * @static |
101 | | * @access public |
102 | | * @return array|object|null |
103 | | * @see prefer() |
104 | | */ |
105 | | function &preferred($classes) { |
106 | | if (! is_array($classes)) { |
107 | | $classes = array($classes); |
108 | | } |
109 | | $registry = &SimpleTest::_getRegistry(); |
110 | | for ($i = count($registry['Preferred']) - 1; $i >= 0; $i--) { |
111 | | foreach ($classes as $class) { |
112 | | if (SimpleTestCompatibility::isA($registry['Preferred'][$i], $class)) { |
113 | | return $registry['Preferred'][$i]; |
114 | | } |
115 | | } |
116 | | } |
117 | | return null; |
118 | | } |
119 | |
|
120 | | /** |
121 | | * Test to see if a test case is in the ignore |
122 | | * list. Quite obviously the ignore list should |
123 | | * be a separate object and will be one day. |
124 | | * This method is internal to SimpleTest. Don't |
125 | | * use it. |
126 | | * @param string $class Class name to test. |
127 | | * @return boolean True if should not be run. |
128 | | * @access public |
129 | | * @static |
130 | | */ |
131 | | function isIgnored($class) { |
132 | | $registry = &SimpleTest::_getRegistry(); |
133 | | return isset($registry['IgnoreList'][strtolower($class)]); |
134 | | } |
135 | |
|
136 | | /** |
137 | | * @deprecated |
138 | | */ |
139 | | function setMockBaseClass($mock_base) { |
140 | | $registry = &SimpleTest::_getRegistry(); |
141 | | $registry['MockBaseClass'] = $mock_base; |
142 | | } |
143 | |
|
144 | | /** |
145 | | * @deprecated |
146 | | */ |
147 | | function getMockBaseClass() { |
148 | | $registry = &SimpleTest::_getRegistry(); |
149 | | return $registry['MockBaseClass']; |
150 | | } |
151 | |
|
152 | | /** |
153 | | * Sets proxy to use on all requests for when |
154 | | * testing from behind a firewall. Set host |
155 | | * to false to disable. This will take effect |
156 | | * if there are no other proxy settings. |
157 | | * @param string $proxy Proxy host as URL. |
158 | | * @param string $username Proxy username for authentication. |
159 | | * @param string $password Proxy password for authentication. |
160 | | * @access public |
161 | | */ |
162 | | function useProxy($proxy, $username = false, $password = false) { |
163 | | $registry = &SimpleTest::_getRegistry(); |
164 | | $registry['DefaultProxy'] = $proxy; |
165 | | $registry['DefaultProxyUsername'] = $username; |
166 | | $registry['DefaultProxyPassword'] = $password; |
167 | | } |
168 | |
|
169 | | /** |
170 | | * Accessor for default proxy host. |
171 | | * @return string Proxy URL. |
172 | | * @access public |
173 | | */ |
174 | | function getDefaultProxy() { |
175 | | $registry = &SimpleTest::_getRegistry(); |
176 | | return $registry['DefaultProxy']; |
177 | | } |
178 | |
|
179 | | /** |
180 | | * Accessor for default proxy username. |
181 | | * @return string Proxy username for authentication. |
182 | | * @access public |
183 | | */ |
184 | | function getDefaultProxyUsername() { |
185 | | $registry = &SimpleTest::_getRegistry(); |
186 | | return $registry['DefaultProxyUsername']; |
187 | | } |
188 | |
|
189 | | /** |
190 | | * Accessor for default proxy password. |
191 | | * @return string Proxy password for authentication. |
192 | | * @access public |
193 | | */ |
194 | | function getDefaultProxyPassword() { |
195 | | $registry = &SimpleTest::_getRegistry(); |
196 | | return $registry['DefaultProxyPassword']; |
197 | | } |
198 | |
|
199 | | /** |
200 | | * Accessor for global registry of options. |
201 | | * @return hash All stored values. |
202 | | * @access private |
203 | | * @static |
204 | | */ |
205 | | function &_getRegistry() { |
206 | | static $registry = false; |
207 | | if (! $registry) { |
208 | | $registry = SimpleTest::_getDefaults(); |
209 | | } |
210 | | return $registry; |
211 | | } |
212 | |
|
213 | | /** |
214 | | * Accessor for the context of the current |
215 | | * test run. |
216 | | * @return SimpleTestContext Current test run. |
217 | | * @access public |
218 | | * @static |
219 | | */ |
220 | | function &getContext() { |
221 | 1 | static $context = false; |
222 | 1 | if (! $context) { |
223 | 1 | $context = new SimpleTestContext(); |
224 | | } |
225 | 1 | return $context; |
226 | | } |
227 | |
|
228 | | /** |
229 | | * Constant default values. |
230 | | * @return hash All registry defaults. |
231 | | * @access private |
232 | | * @static |
233 | | */ |
234 | | function _getDefaults() { |
235 | | return array( |
236 | | 'StubBaseClass' => 'SimpleStub', |
237 | | 'MockBaseClass' => 'SimpleMock', |
238 | | 'IgnoreList' => array(), |
239 | | 'DefaultProxy' => false, |
240 | | 'DefaultProxyUsername' => false, |
241 | | 'DefaultProxyPassword' => false, |
242 | | 'Preferred' => array(new HtmlReporter(), new TextReporter(), new XmlReporter())); |
243 | | } |
244 | | } |
245 | |
|
246 | | /** |
247 | | * Container for all components for a specific |
248 | | * test run. Makes things like error queues |
249 | | * available to PHP event handlers, and also |
250 | | * gets around some nasty reference issues in |
251 | | * the mocks. |
252 | | * @package SimpleTest |
253 | | */ |
254 | | class SimpleTestContext { |
255 | | var $_test; |
256 | | var $_reporter; |
257 | | var $_resources; |
258 | |
|
259 | | /** |
260 | | * Clears down the current context. |
261 | | * @access public |
262 | | */ |
263 | | function clear() { |
264 | 1 | $this->_resources = array(); |
265 | | } |
266 | |
|
267 | | /** |
268 | | * Sets the current test case instance. This |
269 | | * global instance can be used by the mock objects |
270 | | * to send message to the test cases. |
271 | | * @param SimpleTestCase $test Test case to register. |
272 | | * @access public |
273 | | */ |
274 | | function setTest(&$test) { |
275 | 1 | $this->clear(); |
276 | 1 | $this->_test = &$test; |
277 | | } |
278 | |
|
279 | | /** |
280 | | * Accessor for currently running test case. |
281 | | * @return SimpleTestCase Current test. |
282 | | * @access public |
283 | | */ |
284 | | function &getTest() { |
285 | | return $this->_test; |
286 | | } |
287 | |
|
288 | | /** |
289 | | * Sets the current reporter. This |
290 | | * global instance can be used by the mock objects |
291 | | * to send messages. |
292 | | * @param SimpleReporter $reporter Reporter to register. |
293 | | * @access public |
294 | | */ |
295 | | function setReporter(&$reporter) { |
296 | 1 | $this->clear(); |
297 | 1 | $this->_reporter = &$reporter; |
298 | | } |
299 | |
|
300 | | /** |
301 | | * Accessor for current reporter. |
302 | | * @return SimpleReporter Current reporter. |
303 | | * @access public |
304 | | */ |
305 | | function &getReporter() { |
306 | | return $this->_reporter; |
307 | | } |
308 | |
|
309 | | /** |
310 | | * Accessor for the Singleton resource. |
311 | | * @return object Global resource. |
312 | | * @access public |
313 | | * @static |
314 | | */ |
315 | | function &get($resource) { |
316 | 1 | if (! isset($this->_resources[$resource])) { |
317 | 1 | $this->_resources[$resource] = &new $resource(); |
318 | | } |
319 | 1 | return $this->_resources[$resource]; |
320 | | } |
321 | | } |
322 | |
|
323 | | /** |
324 | | * Interrogates the stack trace to recover the |
325 | | * failure point. |
326 | | * @package SimpleTest |
327 | | * @subpackage UnitTester |
328 | | */ |
329 | | class SimpleStackTrace { |
330 | | var $_prefixes; |
331 | |
|
332 | | /** |
333 | | * Stashes the list of target prefixes. |
334 | | * @param array $prefixes List of method prefixes |
335 | | * to search for. |
336 | | */ |
337 | | function SimpleStackTrace($prefixes) { |
338 | 1 | $this->_prefixes = $prefixes; |
339 | | } |
340 | |
|
341 | | /** |
342 | | * Extracts the last method name that was not within |
343 | | * Simpletest itself. Captures a stack trace if none given. |
344 | | * @param array $stack List of stack frames. |
345 | | * @return string Snippet of test report with line |
346 | | * number and file. |
347 | | * @access public |
348 | | */ |
349 | | function traceMethod($stack = false) { |
350 | 1 | $stack = $stack ? $stack : $this->_captureTrace(); |
351 | 1 | foreach ($stack as $frame) { |
352 | 1 | if ($this->_frameLiesWithinSimpleTestFolder($frame)) { |
353 | | continue; |
354 | | } |
355 | 1 | if ($this->_frameMatchesPrefix($frame)) { |
356 | 1 | return ' at [' . $frame['file'] . ' line ' . $frame['line'] . ']'; |
357 | | } |
358 | | } |
359 | | return ''; |
360 | | } |
361 | |
|
362 | | /** |
363 | | * Test to see if error is generated by SimpleTest itself. |
364 | | * @param array $frame PHP stack frame. |
365 | | * @return boolean True if a SimpleTest file. |
366 | | * @access private |
367 | | */ |
368 | | function _frameLiesWithinSimpleTestFolder($frame) { |
369 | 1 | if (isset($frame['file'])) { |
370 | 1 | $path = substr(SIMPLE_TEST, 0, -1); |
371 | 1 | if (strpos($frame['file'], $path) === 0) { |
372 | | if (dirname($frame['file']) == $path) { |
373 | | return true; |
374 | | } |
375 | | } |
376 | | } |
377 | 1 | return false; |
378 | | } |
379 | |
|
380 | | /** |
381 | | * Tries to determine if the method call is an assert, etc. |
382 | | * @param array $frame PHP stack frame. |
383 | | * @return boolean True if matches a target. |
384 | | * @access private |
385 | | */ |
386 | | function _frameMatchesPrefix($frame) { |
387 | 1 | foreach ($this->_prefixes as $prefix) { |
388 | 1 | if (strncmp($frame['function'], $prefix, strlen($prefix)) == 0) { |
389 | 1 | return true; |
390 | | } |
391 | | } |
392 | 1 | return false; |
393 | | } |
394 | |
|
395 | | /** |
396 | | * Grabs a current stack trace. |
397 | | * @return array Fulle trace. |
398 | | * @access private |
399 | | */ |
400 | | function _captureTrace() { |
401 | 1 | if (function_exists('debug_backtrace')) { |
402 | 1 | return array_reverse(debug_backtrace()); |
403 | | } |
404 | | return array(); |
405 | | } |
406 | | } |
407 | |
|
408 | | /** |
409 | | * @package SimpleTest |
410 | | * @subpackage UnitTester |
411 | | * @deprecated |
412 | | */ |
413 | | class SimpleTestOptions extends SimpleTest { |
414 | |
|
415 | | /** |
416 | | * @deprecated |
417 | | */ |
418 | | function getVersion() { |
419 | | return Simpletest::getVersion(); |
420 | | } |
421 | |
|
422 | | /** |
423 | | * @deprecated |
424 | | */ |
425 | | function ignore($class) { |
426 | | return Simpletest::ignore($class); |
427 | | } |
428 | |
|
429 | | /** |
430 | | * @deprecated |
431 | | */ |
432 | | function isIgnored($class) { |
433 | | return Simpletest::isIgnored($class); |
434 | | } |
435 | |
|
436 | | /** |
437 | | * @deprecated |
438 | | */ |
439 | | function setMockBaseClass($mock_base) { |
440 | | return Simpletest::setMockBaseClass($mock_base); |
441 | | } |
442 | |
|
443 | | /** |
444 | | * @deprecated |
445 | | */ |
446 | | function getMockBaseClass() { |
447 | | return Simpletest::getMockBaseClass(); |
448 | | } |
449 | |
|
450 | | /** |
451 | | * @deprecated |
452 | | */ |
453 | | function useProxy($proxy, $username = false, $password = false) { |
454 | | return Simpletest::useProxy($proxy, $username, $password); |
455 | | } |
456 | |
|
457 | | /** |
458 | | * @deprecated |
459 | | */ |
460 | | function getDefaultProxy() { |
461 | | return Simpletest::getDefaultProxy(); |
462 | | } |
463 | |
|
464 | | /** |
465 | | * @deprecated |
466 | | */ |
467 | | function getDefaultProxyUsername() { |
468 | | return Simpletest::getDefaultProxyUsername(); |
469 | | } |
470 | |
|
471 | | /** |
472 | | * @deprecated |
473 | | */ |
474 | | function getDefaultProxyPassword() { |
475 | | return Simpletest::getDefaultProxyPassword(); |
476 | | } |
477 | | } |
478 | | ?> |