1<?php
2    /**
3     *	base include file for SimpleTest
4     *	@package	SimpleTest
5     *	@subpackage	UnitTester
6     *	@version	$Id: expectation.php,v 1.1 2005/11/09 23:41:18 gsmet Exp $
7     */
8
9    /**#@+
10     *	include other SimpleTest class files
11     */
12    require_once(dirname(__FILE__) . '/dumper.php');
13    require_once(dirname(__FILE__) . '/options.php');
14    /**#@-*/
15
16    /**
17     *    Assertion that can display failure information.
18     *    Also includes various helper methods.
19	 *	  @package SimpleTest
20	 *	  @subpackage UnitTester
21     *    @abstract
22     */
23    class SimpleExpectation {
24        var $_dumper;
25        var $_message;
26
27        /**
28         *    Creates a dumper for displaying values and sets
29         *    the test message.
30         *    @param string $message    Customised message on failure.
31         */
32        function SimpleExpectation($message = '%s') {
33            $this->_dumper = &new SimpleDumper();
34            $this->_message = $message;
35        }
36
37        /**
38         *    Tests the expectation. True if correct.
39         *    @param mixed $compare        Comparison value.
40         *    @return boolean              True if correct.
41         *    @access public
42         *    @abstract
43         */
44        function test($compare) {
45        }
46
47        /**
48         *    Returns a human readable test message.
49         *    @param mixed $compare      Comparison value.
50         *    @return string             Description of success
51         *                               or failure.
52         *    @access public
53         *    @abstract
54         */
55        function testMessage($compare) {
56        }
57
58        /**
59         *    Overlays the generated message onto the stored user
60         *    message.
61         *    @param mixed $compare      Comparison value.
62         *    @return string             Description of success
63         *                               or failure.
64         *    @access public
65         */
66        function overlayMessage($compare) {
67            return sprintf($this->_message, $this->testMessage($compare));
68        }
69
70        /**
71         *    Accessor for the dumper.
72         *    @return SimpleDumper    Current value dumper.
73         *    @access protected
74         */
75        function &_getDumper() {
76            return $this->_dumper;
77        }
78    }
79
80    /**
81     *    Test for equality.
82	 *	  @package SimpleTest
83	 *	  @subpackage UnitTester
84     */
85    class EqualExpectation extends SimpleExpectation {
86        var $_value;
87
88        /**
89         *    Sets the value to compare against.
90         *    @param mixed $value        Test value to match.
91         *    @param string $message     Customised message on failure.
92         *    @access public
93         */
94        function EqualExpectation($value, $message = '%s') {
95            $this->SimpleExpectation($message);
96            $this->_value = $value;
97        }
98
99        /**
100         *    Tests the expectation. True if it matches the
101         *    held value.
102         *    @param mixed $compare        Comparison value.
103         *    @return boolean              True if correct.
104         *    @access public
105         */
106        function test($compare, $nasty = false) {
107            return (($this->_value == $compare) && ($compare == $this->_value));
108        }
109
110        /**
111         *    Returns a human readable test message.
112         *    @param mixed $compare      Comparison value.
113         *    @return string             Description of success
114         *                               or failure.
115         *    @access public
116         */
117        function testMessage($compare) {
118            if ($this->test($compare)) {
119                return "Equal expectation [" . $this->_dumper->describeValue($this->_value) . "]";
120            } else {
121                return "Equal expectation fails " .
122                        $this->_dumper->describeDifference($this->_value, $compare);
123            }
124        }
125
126        /**
127         *    Accessor for comparison value.
128         *    @return mixed       Held value to compare with.
129         *    @access protected
130         */
131        function _getValue() {
132            return $this->_value;
133        }
134    }
135
136    /**
137     *    Test for inequality.
138	 *	  @package SimpleTest
139	 *	  @subpackage UnitTester
140     */
141    class NotEqualExpectation extends EqualExpectation {
142
143        /**
144         *    Sets the value to compare against.
145         *    @param mixed $value       Test value to match.
146         *    @param string $message    Customised message on failure.
147         *    @access public
148         */
149        function NotEqualExpectation($value, $message = '%s') {
150            $this->EqualExpectation($value, $message);
151        }
152
153        /**
154         *    Tests the expectation. True if it differs from the
155         *    held value.
156         *    @param mixed $compare        Comparison value.
157         *    @return boolean              True if correct.
158         *    @access public
159         */
160        function test($compare) {
161            return ! parent::test($compare);
162        }
163
164        /**
165         *    Returns a human readable test message.
166         *    @param mixed $compare      Comparison value.
167         *    @return string             Description of success
168         *                               or failure.
169         *    @access public
170         */
171        function testMessage($compare) {
172            $dumper = &$this->_getDumper();
173            if ($this->test($compare)) {
174                return "Not equal expectation passes " .
175                        $dumper->describeDifference($this->_getValue(), $compare);
176            } else {
177                return "Not equal expectation fails [" .
178                        $dumper->describeValue($this->_getValue()) .
179                        "] matches";
180            }
181        }
182    }
183
184    /**
185     *    Test for identity.
186	 *	  @package SimpleTest
187	 *	  @subpackage UnitTester
188     */
189    class IdenticalExpectation extends EqualExpectation {
190
191        /**
192         *    Sets the value to compare against.
193         *    @param mixed $value       Test value to match.
194         *    @param string $message    Customised message on failure.
195         *    @access public
196         */
197        function IdenticalExpectation($value, $message = '%s') {
198            $this->EqualExpectation($value, $message);
199        }
200
201        /**
202         *    Tests the expectation. True if it exactly
203         *    matches the held value.
204         *    @param mixed $compare        Comparison value.
205         *    @return boolean              True if correct.
206         *    @access public
207         */
208        function test($compare) {
209            return SimpleTestCompatibility::isIdentical($this->_getValue(), $compare);
210        }
211
212        /**
213         *    Returns a human readable test message.
214         *    @param mixed $compare      Comparison value.
215         *    @return string             Description of success
216         *                               or failure.
217         *    @access public
218         */
219        function testMessage($compare) {
220            $dumper = &$this->_getDumper();
221            if ($this->test($compare)) {
222                return "Identical expectation [" . $dumper->describeValue($this->_getValue()) . "]";
223            } else {
224                return "Identical expectation [" . $dumper->describeValue($this->_getValue()) .
225                        "] fails with [" .
226                        $dumper->describeValue($compare) . "] " .
227                        $dumper->describeDifference($this->_getValue(), $compare, TYPE_MATTERS);
228            }
229        }
230    }
231
232    /**
233     *    Test for non-identity.
234	 *	  @package SimpleTest
235	 *	  @subpackage UnitTester
236     */
237    class NotIdenticalExpectation extends IdenticalExpectation {
238
239        /**
240         *    Sets the value to compare against.
241         *    @param mixed $value        Test value to match.
242         *    @param string $message     Customised message on failure.
243         *    @access public
244         */
245        function NotIdenticalExpectation($value, $message = '%s') {
246            $this->IdenticalExpectation($value, $message);
247        }
248
249        /**
250         *    Tests the expectation. True if it differs from the
251         *    held value.
252         *    @param mixed $compare        Comparison value.
253         *    @return boolean              True if correct.
254         *    @access public
255         */
256        function test($compare) {
257            return ! parent::test($compare);
258        }
259
260        /**
261         *    Returns a human readable test message.
262         *    @param mixed $compare      Comparison value.
263         *    @return string             Description of success
264         *                               or failure.
265         *    @access public
266         */
267        function testMessage($compare) {
268            $dumper = &$this->_getDumper();
269            if ($this->test($compare)) {
270                return "Not identical expectation passes " .
271                        $dumper->describeDifference($this->_getValue(), $compare, TYPE_MATTERS);
272            } else {
273                return "Not identical expectation [" . $dumper->describeValue($this->_getValue()) . "] matches";
274            }
275        }
276    }
277
278    /**
279     *    Test for a pattern using Perl regex rules.
280	 *	  @package SimpleTest
281	 *	  @subpackage UnitTester
282     */
283    class WantedPatternExpectation extends SimpleExpectation {
284        var $_pattern;
285
286        /**
287         *    Sets the value to compare against.
288         *    @param string $pattern    Pattern to search for.
289         *    @param string $message    Customised message on failure.
290         *    @access public
291         */
292        function WantedPatternExpectation($pattern, $message = '%s') {
293            $this->SimpleExpectation($message);
294            $this->_pattern = $pattern;
295        }
296
297        /**
298         *    Accessor for the pattern.
299         *    @return string       Perl regex as string.
300         *    @access protected
301         */
302        function _getPattern() {
303            return $this->_pattern;
304        }
305
306        /**
307         *    Tests the expectation. True if the Perl regex
308         *    matches the comparison value.
309         *    @param string $compare        Comparison value.
310         *    @return boolean               True if correct.
311         *    @access public
312         */
313        function test($compare) {
314            return (boolean)preg_match($this->_getPattern(), $compare);
315        }
316
317        /**
318         *    Returns a human readable test message.
319         *    @param mixed $compare      Comparison value.
320         *    @return string             Description of success
321         *                               or failure.
322         *    @access public
323         */
324        function testMessage($compare) {
325            if ($this->test($compare)) {
326                return $this->_describePatternMatch($this->_getPattern(), $compare);
327            } else {
328                $dumper = &$this->_getDumper();
329                return "Pattern [" . $this->_getPattern() .
330                        "] not detected in [" .
331                        $dumper->describeValue($compare) . "]";
332            }
333        }
334
335        /**
336         *    Describes a pattern match including the string
337         *    found and it's position.
338         *    @param string $pattern        Regex to match against.
339         *    @param string $subject        Subject to search.
340         *    @access protected
341         */
342        function _describePatternMatch($pattern, $subject) {
343            preg_match($pattern, $subject, $matches);
344            $position = strpos($subject, $matches[0]);
345            $dumper = &$this->_getDumper();
346            return "Pattern [$pattern] detected at character [$position] in [" .
347                    $dumper->describeValue($subject) . "] as [" .
348                    $matches[0] . "] in region [" .
349                    $dumper->clipString($subject, 100, $position) . "]";
350        }
351    }
352
353    /**
354     *    Fail if a pattern is detected within the
355     *    comparison.
356	 *	  @package SimpleTest
357	 *	  @subpackage UnitTester
358     */
359    class UnwantedPatternExpectation extends WantedPatternExpectation {
360
361        /**
362         *    Sets the reject pattern
363         *    @param string $pattern    Pattern to search for.
364         *    @param string $message    Customised message on failure.
365         *    @access public
366         */
367        function UnwantedPatternExpectation($pattern, $message = '%s') {
368            $this->WantedPatternExpectation($pattern, $message);
369        }
370
371        /**
372         *    Tests the expectation. False if the Perl regex
373         *    matches the comparison value.
374         *    @param string $compare        Comparison value.
375         *    @return boolean               True if correct.
376         *    @access public
377         */
378        function test($compare) {
379            return ! parent::test($compare);
380        }
381
382        /**
383         *    Returns a human readable test message.
384         *    @param string $compare      Comparison value.
385         *    @return string              Description of success
386         *                                or failure.
387         *    @access public
388         */
389        function testMessage($compare) {
390            if ($this->test($compare)) {
391                $dumper = &$this->_getDumper();
392                return "Pattern [" . $this->_getPattern() .
393                        "] not detected in [" .
394                        $dumper->describeValue($compare) . "]";
395            } else {
396                return $this->_describePatternMatch($this->_getPattern(), $compare);
397            }
398        }
399    }
400
401    /**
402     *    Tests either type or class name if it's an object.
403	 *	  @package SimpleTest
404	 *	  @subpackage UnitTester
405     */
406    class IsAExpectation extends SimpleExpectation {
407        var $_type;
408
409        /**
410         *    Sets the type to compare with.
411         *    @param string $type       Type or class name.
412         *    @param string $message    Customised message on failure.
413         *    @access public
414         */
415        function IsAExpectation($type, $message = '%s') {
416            $this->SimpleExpectation($message);
417            $this->_type = $type;
418        }
419
420        /**
421         *    Accessor for type to check against.
422         *    @return string    Type or class name.
423         *    @access protected
424         */
425        function _getType() {
426            return $this->_type;
427        }
428
429        /**
430         *    Tests the expectation. True if the type or
431         *    class matches the string value.
432         *    @param string $compare        Comparison value.
433         *    @return boolean               True if correct.
434         *    @access public
435         */
436        function test($compare) {
437            if (is_object($compare)) {
438                return SimpleTestCompatibility::isA($compare, $this->_type);
439            } else {
440                return (strtolower(gettype($compare)) == $this->_canonicalType($this->_type));
441            }
442        }
443
444        /**
445         *    Coerces type name into a gettype() match.
446         *    @param string $type        User type.
447         *    @return string             Simpler type.
448         *    @access private
449         */
450        function _canonicalType($type) {
451            $type = strtolower($type);
452            $map = array(
453                    'bool' => 'boolean',
454                    'float' => 'double',
455                    'real' => 'double',
456                    'int' => 'integer');
457            if (isset($map[$type])) {
458                $type = $map[$type];
459            }
460            return $type;
461        }
462
463        /**
464         *    Returns a human readable test message.
465         *    @param mixed $compare      Comparison value.
466         *    @return string             Description of success
467         *                               or failure.
468         *    @access public
469         */
470        function testMessage($compare) {
471            $dumper = &$this->_getDumper();
472            return "Value [" . $dumper->describeValue($compare) .
473                    "] should be type [" . $this->_type . "]";
474        }
475    }
476
477    /**
478     *    Tests either type or class name if it's an object.
479     *    Will succeed if the type does not match.
480	 *	  @package SimpleTest
481	 *	  @subpackage UnitTester
482     */
483    class NotAExpectation extends IsAExpectation {
484        var $_type;
485
486        /**
487         *    Sets the type to compare with.
488         *    @param string $type       Type or class name.
489         *    @param string $message    Customised message on failure.
490         *    @access public
491         */
492        function NotAExpectation($type, $message = '%s') {
493            $this->IsAExpectation($type, $message);
494        }
495
496        /**
497         *    Tests the expectation. False if the type or
498         *    class matches the string value.
499         *    @param string $compare        Comparison value.
500         *    @return boolean               True if different.
501         *    @access public
502         */
503        function test($compare) {
504            return ! parent::test($compare);
505        }
506
507        /**
508         *    Returns a human readable test message.
509         *    @param mixed $compare      Comparison value.
510         *    @return string             Description of success
511         *                               or failure.
512         *    @access public
513         */
514        function testMessage($compare) {
515            $dumper = &$this->_getDumper();
516            return "Value [" . $dumper->describeValue($compare) .
517                    "] should not be type [" . $this->_getType() . "]";
518        }
519    }
520
521    /**
522     *    Tests for existance of a method in an object
523	 *	  @package SimpleTest
524	 *	  @subpackage UnitTester
525     */
526    class MethodExistsExpectation extends SimpleExpectation {
527        var $_method;
528
529        /**
530         *    Sets the value to compare against.
531         *    @param string $method     Method to check.
532         *    @param string $message    Customised message on failure.
533         *    @access public
534         *    @return void
535         */
536        function MethodExistsExpectation($method, $message = '%s') {
537            $this->SimpleExpectation($message);
538            $this->_method = &$method;
539        }
540
541        /**
542         *    Tests the expectation. True if the method exists in the test object.
543         *    @param string $compare        Comparison method name.
544         *    @return boolean               True if correct.
545         *    @access public
546         */
547        function test($compare) {
548            return (boolean)(is_object($compare) && method_exists($compare, $this->_method));
549        }
550
551        /**
552         *    Returns a human readable test message.
553         *    @param mixed $compare      Comparison value.
554         *    @return string             Description of success
555         *                               or failure.
556         *    @access public
557         */
558        function testMessage($compare) {
559			$dumper = &$this->_getDumper();
560			if (! is_object($compare)) {
561			    return 'No method on non-object [' . $dumper->describeValue($compare) . ']';
562			}
563			$method = $this->_method;
564			return "Object [" . $dumper->describeValue($compare) .
565					"] should contain method [$method]";
566        }
567    }
568?>