]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/Framework/Assert.php
Added unit tests.
[Github/sugarcrm.git] / tests / PHPUnit / Framework / Assert.php
1 <?php
2 /**
3  * PHPUnit
4  *
5  * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @category   Testing
38  * @package    PHPUnit
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42
43  * @link       http://www.phpunit.de/
44  * @since      File available since Release 2.0.0
45  */
46
47 require_once 'PHPUnit/Framework.php';
48 require_once 'PHPUnit/Util/Filter.php';
49 require_once 'PHPUnit/Util/Type.php';
50 require_once 'PHPUnit/Util/XML.php';
51
52 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
53
54 if (!class_exists('PHPUnit_Framework_Assert', FALSE)) {
55
56 /**
57  * A set of assert methods.
58  *
59  * @category   Testing
60  * @package    PHPUnit
61  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
62  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
63  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
64  * @version    Release: 3.3.17
65  * @link       http://www.phpunit.de/
66  * @since      Class available since Release 2.0.0
67  * @abstract
68  */
69 abstract class PHPUnit_Framework_Assert
70 {
71     /**
72      * @var integer
73      */
74     private static $count = 0;
75
76     /**
77      * Asserts that an array has a specified key.
78      *
79      * @param  mixed  $key
80      * @param  array  $array
81      * @param  string $message
82      * @since  Method available since Release 3.0.0
83      */
84     public static function assertArrayHasKey($key, array $array, $message = '')
85     {
86         if (!(is_integer($key) || is_string($key))) {
87             throw new InvalidArgumentException;
88         }
89
90         $constraint = new PHPUnit_Framework_Constraint_ArrayHasKey($key);
91
92         self::assertThat($array, $constraint, $message);
93     }
94
95     /**
96      * Asserts that an array does not have a specified key.
97      *
98      * @param  mixed  $key
99      * @param  array  $array
100      * @param  string $message
101      * @since  Method available since Release 3.0.0
102      */
103     public static function assertArrayNotHasKey($key, array $array, $message = '')
104     {
105         if (!(is_integer($key) || is_string($key))) {
106             throw new InvalidArgumentException;
107         }
108
109         $constraint = new PHPUnit_Framework_Constraint_Not(
110           new PHPUnit_Framework_Constraint_ArrayHasKey($key)
111         );
112
113         self::assertThat($array, $constraint, $message);
114     }
115
116     /**
117      * Asserts that a haystack contains a needle.
118      *
119      * @param  mixed   $needle
120      * @param  mixed   $haystack
121      * @param  string  $message
122      * @since  Method available since Release 2.1.0
123      */
124     public static function assertContains($needle, $haystack, $message = '')
125     {
126         if (is_array($haystack) ||
127             is_object($haystack) && $haystack instanceof Iterator) {
128             $constraint = new PHPUnit_Framework_Constraint_TraversableContains($needle);
129         }
130
131         else if (is_string($haystack)) {
132             $constraint = new PHPUnit_Framework_Constraint_StringContains($needle);
133         }
134
135         else {
136             throw new InvalidArgumentException;
137         }
138
139         self::assertThat($haystack, $constraint, $message);
140     }
141
142     /**
143      * Asserts that a haystack that is stored in a static attribute of a class
144      * or an attribute of an object contains a needle.
145      *
146      * @param  mixed   $needle
147      * @param  string  $haystackAttributeName
148      * @param  mixed   $haystackClassOrObject
149      * @param  string  $message
150      * @since  Method available since Release 3.0.0
151      */
152     public static function assertAttributeContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '')
153     {
154         self::assertContains(
155           $needle,
156           self::readAttribute($haystackClassOrObject, $haystackAttributeName),
157           $message
158         );
159     }
160
161     /**
162      * Asserts that a haystack does not contain a needle.
163      *
164      * @param  mixed   $needle
165      * @param  mixed   $haystack
166      * @param  string  $message
167      * @since  Method available since Release 2.1.0
168      */
169     public static function assertNotContains($needle, $haystack, $message = '')
170     {
171         if (is_array($haystack) ||
172             is_object($haystack) && $haystack instanceof Iterator) {
173             $constraint = new PHPUnit_Framework_Constraint_Not(
174               new PHPUnit_Framework_Constraint_TraversableContains($needle)
175             );
176         }
177
178         else if (is_string($haystack)) {
179             $constraint = new PHPUnit_Framework_Constraint_Not(
180               new PHPUnit_Framework_Constraint_StringContains($needle)
181             );
182         }
183
184         else {
185             throw new InvalidArgumentException;
186         }
187
188         self::assertThat($haystack, $constraint, $message);
189     }
190
191     /**
192      * Asserts that a haystack that is stored in a static attribute of a class
193      * or an attribute of an object does not contain a needle.
194      *
195      * @param  mixed   $needle
196      * @param  string  $haystackAttributeName
197      * @param  mixed   $haystackClassOrObject
198      * @param  string  $message
199      * @since  Method available since Release 3.0.0
200      */
201     public static function assertAttributeNotContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '')
202     {
203         self::assertNotContains(
204           $needle,
205           self::readAttribute($haystackClassOrObject, $haystackAttributeName),
206           $message
207         );
208     }
209
210     /**
211      * Asserts that a haystack contains only values of a given type.
212      *
213      * @param  string  $type
214      * @param  mixed   $haystack
215      * @param  boolean $isNativeType
216      * @param  string  $message
217      * @since  Method available since Release 3.1.4
218      */
219     public static function assertContainsOnly($type, $haystack, $isNativeType = NULL, $message = '')
220     {
221         if (!(is_array($haystack) ||
222             is_object($haystack) && $haystack instanceof Iterator)) {
223             throw new InvalidArgumentException;
224         }
225
226         if ($isNativeType == NULL) {
227             $isNativeType = PHPUnit_Util_Type::isType($type);
228         }
229
230         self::assertThat(
231           $haystack,
232           new PHPUnit_Framework_Constraint_TraversableContainsOnly(
233             $type, $isNativeType
234           ),
235           $message
236         );
237     }
238
239     /**
240      * Asserts that a haystack that is stored in a static attribute of a class
241      * or an attribute of an object contains only values of a given type.
242      *
243      * @param  string  $type
244      * @param  string  $haystackAttributeName
245      * @param  mixed   $haystackClassOrObject
246      * @param  boolean $isNativeType
247      * @param  string  $message
248      * @since  Method available since Release 3.1.4
249      */
250     public static function assertAttributeContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = NULL, $message = '')
251     {
252         self::assertContainsOnly(
253           $type,
254           self::readAttribute($haystackClassOrObject, $haystackAttributeName),
255           $isNativeType,
256           $message
257         );
258     }
259
260     /**
261      * Asserts that a haystack does not contain only values of a given type.
262      *
263      * @param  string  $type
264      * @param  mixed   $haystack
265      * @param  boolean $isNativeType
266      * @param  string  $message
267      * @since  Method available since Release 3.1.4
268      */
269     public static function assertNotContainsOnly($type, $haystack, $isNativeType = NULL, $message = '')
270     {
271         if (!(is_array($haystack) ||
272             is_object($haystack) && $haystack instanceof Iterator)) {
273             throw new InvalidArgumentException;
274         }
275
276         if ($isNativeType == NULL) {
277             $isNativeType = PHPUnit_Util_Type::isType($type);
278         }
279
280         self::assertThat(
281           $haystack,
282           new PHPUnit_Framework_Constraint_Not(
283             new PHPUnit_Framework_Constraint_TraversableContainsOnly(
284               $type, $isNativeType
285             )
286           ),
287           $message
288         );
289     }
290
291     /**
292      * Asserts that a haystack that is stored in a static attribute of a class
293      * or an attribute of an object does not contain only values of a given type.
294      *
295      * @param  string  $type
296      * @param  string  $haystackAttributeName
297      * @param  mixed   $haystackClassOrObject
298      * @param  boolean $isNativeType
299      * @param  string  $message
300      * @since  Method available since Release 3.1.4
301      */
302     public static function assertAttributeNotContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = NULL, $message = '')
303     {
304         self::assertNotContainsOnly(
305           $type,
306           self::readAttribute($haystackClassOrObject, $haystackAttributeName),
307           $isNativeType,
308           $message
309         );
310     }
311
312     /**
313      * Asserts that two variables are equal.
314      *
315      * @param  mixed   $expected
316      * @param  mixed   $actual
317      * @param  string  $message
318      * @param  float   $delta
319      * @param  integer $maxDepth
320      * @param  boolean $canonicalizeEol
321      */
322     public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalizeEol = FALSE)
323     {
324         $constraint = new PHPUnit_Framework_Constraint_IsEqual(
325           $expected, $delta, $maxDepth, $canonicalizeEol
326         );
327
328         self::assertThat($actual, $constraint, $message);
329     }
330
331     /**
332      * Asserts that a variable is equal to an attribute of an object.
333      *
334      * @param  mixed   $expected
335      * @param  string  $actualAttributeName
336      * @param  string  $actualClassOrObject
337      * @param  string  $message
338      * @param  float   $delta
339      * @param  integer $maxDepth
340      * @param  boolean $canonicalizeEol
341      */
342     public static function assertAttributeEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0, $maxDepth = 10, $canonicalizeEol = FALSE)
343     {
344         self::assertEquals(
345           $expected,
346           self::readAttribute($actualClassOrObject, $actualAttributeName),
347           $message,
348           $delta,
349           $maxDepth,
350           $canonicalizeEol
351         );
352     }
353
354     /**
355      * Asserts that two variables are not equal.
356      *
357      * @param  mixed   $expected
358      * @param  mixed   $actual
359      * @param  string  $message
360      * @param  float   $delta
361      * @param  integer $maxDepth
362      * @param  boolean $canonicalizeEol
363      * @since  Method available since Release 2.3.0
364      */
365     public static function assertNotEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalizeEol = FALSE)
366     {
367         $constraint = new PHPUnit_Framework_Constraint_Not(
368           new PHPUnit_Framework_Constraint_IsEqual(
369             $expected, $delta, $maxDepth, $canonicalizeEol
370           )
371         );
372
373         self::assertThat($actual, $constraint, $message);
374     }
375
376     /**
377      * Asserts that a variable is not equal to an attribute of an object.
378      *
379      * @param  mixed   $expected
380      * @param  string  $actualAttributeName
381      * @param  string  $actualClassOrObject
382      * @param  string  $message
383      * @param  float   $delta
384      * @param  integer $maxDepth
385      * @param  boolean $canonicalizeEol
386      */
387     public static function assertAttributeNotEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0, $maxDepth = 10, $canonicalizeEol = FALSE)
388     {
389         self::assertNotEquals(
390           $expected,
391           self::readAttribute($actualClassOrObject, $actualAttributeName),
392           $message,
393           $delta,
394           $maxDepth,
395           $canonicalizeEol
396         );
397     }
398
399     /**
400      * Asserts that a value is greater than another value.
401      *
402      * @param  mixed   $expected
403      * @param  mixed   $actual
404      * @param  string  $message
405      * @since  Method available since Release 3.1.0
406      */
407     public static function assertGreaterThan($expected, $actual, $message = '')
408     {
409         self::assertThat($actual, self::greaterThan($expected), $message);
410     }
411
412     /**
413      * Asserts that an attribute is greater than another value.
414      *
415      * @param  mixed   $expected
416      * @param  string  $actualAttributeName
417      * @param  string  $actualClassOrObject
418      * @param  string  $message
419      * @since  Method available since Release 3.1.0
420      */
421     public static function assertAttributeGreaterThan($expected, $actualAttributeName, $actualClassOrObject, $message = '')
422     {
423         self::assertGreaterThan(
424           $expected,
425           self::readAttribute($actualClassOrObject, $actualAttributeName),
426           $message
427         );
428     }
429
430     /**
431      * Asserts that a value is greater than or equal to another value.
432      *
433      * @param  mixed   $expected
434      * @param  mixed   $actual
435      * @param  string  $message
436      * @since  Method available since Release 3.1.0
437      */
438     public static function assertGreaterThanOrEqual($expected, $actual, $message = '')
439     {
440         self::assertThat($actual, self::greaterThanOrEqual($expected), $message);
441     }
442
443     /**
444      * Asserts that an attribute is greater than or equal to another value.
445      *
446      * @param  mixed   $expected
447      * @param  string  $actualAttributeName
448      * @param  string  $actualClassOrObject
449      * @param  string  $message
450      * @since  Method available since Release 3.1.0
451      */
452     public static function assertAttributeGreaterThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '')
453     {
454         self::assertGreaterThanOrEqual(
455           $expected,
456           self::readAttribute($actualClassOrObject, $actualAttributeName),
457           $message
458         );
459     }
460
461     /**
462      * Asserts that a value is smaller than another value.
463      *
464      * @param  mixed   $expected
465      * @param  mixed   $actual
466      * @param  string  $message
467      * @since  Method available since Release 3.1.0
468      */
469     public static function assertLessThan($expected, $actual, $message = '')
470     {
471         self::assertThat($actual, self::lessThan($expected), $message);
472     }
473
474     /**
475      * Asserts that an attribute is smaller than another value.
476      *
477      * @param  mixed   $expected
478      * @param  string  $actualAttributeName
479      * @param  string  $actualClassOrObject
480      * @param  string  $message
481      * @since  Method available since Release 3.1.0
482      */
483     public static function assertAttributeLessThan($expected, $actualAttributeName, $actualClassOrObject, $message = '')
484     {
485         self::assertLessThan(
486           $expected,
487           self::readAttribute($actualClassOrObject, $actualAttributeName),
488           $message
489         );
490     }
491
492     /**
493      * Asserts that a value is smaller than or equal to another value.
494      *
495      * @param  mixed   $expected
496      * @param  mixed   $actual
497      * @param  string  $message
498      * @since  Method available since Release 3.1.0
499      */
500     public static function assertLessThanOrEqual($expected, $actual, $message = '')
501     {
502         self::assertThat($actual, self::lessThanOrEqual($expected), $message);
503     }
504
505     /**
506      * Asserts that an attribute is smaller than or equal to another value.
507      *
508      * @param  mixed   $expected
509      * @param  string  $actualAttributeName
510      * @param  string  $actualClassOrObject
511      * @param  string  $message
512      * @since  Method available since Release 3.1.0
513      */
514     public static function assertAttributeLessThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '')
515     {
516         self::assertLessThanOrEqual(
517           $expected,
518           self::readAttribute($actualClassOrObject, $actualAttributeName),
519           $message
520         );
521     }
522
523     /**
524      * Asserts that the contents of one file is equal to the contents of another
525      * file.
526      *
527      * @param  string  $expected
528      * @param  string  $actual
529      * @param  string  $message
530      * @param  boolean $canonicalizeEol
531      * @since  Method available since Release 3.2.14
532      */
533     public static function assertFileEquals($expected, $actual, $message = '', $canonicalizeEol = FALSE)
534     {
535         self::assertFileExists($expected, $message);
536         self::assertFileExists($actual, $message);
537
538         self::assertEquals(
539           file_get_contents($expected),
540           file_get_contents($actual),
541           $message,
542           0,
543           10,
544           $canonicalizeEol
545         );
546     }
547
548     /**
549      * Asserts that the contents of one file is not equal to the contents of
550      * another file.
551      *
552      * @param  string  $expected
553      * @param  string  $actual
554      * @param  string  $message
555      * @param  boolean $canonicalizeEol
556      * @since  Method available since Release 3.2.14
557      */
558     public static function assertFileNotEquals($expected, $actual, $message = '', $canonicalizeEol = FALSE)
559     {
560         self::assertFileExists($expected, $message);
561         self::assertFileExists($actual, $message);
562
563         self::assertNotEquals(
564           file_get_contents($expected),
565           file_get_contents($actual),
566           $message,
567           0,
568           10,
569           $canonicalizeEol
570         );
571     }
572
573     /**
574      * Asserts that the contents of a string is equal
575      * to the contents of a file.
576      *
577      * @param  string  $expectedFile
578      * @param  string  $actualString
579      * @param  string  $message
580      * @param  boolean $canonicalizeEol
581      * @since  Method available since Release 3.3.0
582      */
583     public static function assertStringEqualsFile($expectedFile, $actualString, $message = '', $canonicalizeEol = FALSE)
584     {
585         self::assertFileExists($expectedFile, $message);
586
587         self::assertEquals(
588           file_get_contents($expectedFile),
589           $actualString,
590           $message,
591           0,
592           10,
593           $canonicalizeEol
594         );
595     }
596
597     /**
598      * Asserts that the contents of a string is not equal
599      * to the contents of a file.
600      *
601      * @param  string  $expectedFile
602      * @param  string  $actualString
603      * @param  string  $message
604      * @param  boolean $canonicalizeEol
605      * @since  Method available since Release 3.3.0
606      */
607     public static function assertStringNotEqualsFile($expectedFile, $actualString, $message = '', $canonicalizeEol = FALSE)
608     {
609         self::assertFileExists($expectedFile, $message);
610
611         self::assertNotEquals(
612           file_get_contents($expectedFile),
613           $actualString,
614           $message,
615           0,
616           10,
617           $canonicalizeEol
618         );
619     }
620
621     /**
622      * Asserts that a file exists.
623      *
624      * @param  string $filename
625      * @param  string $message
626      * @since  Method available since Release 3.0.0
627      */
628     public static function assertFileExists($filename, $message = '')
629     {
630         if (!is_string($filename)) {
631             throw new InvalidArgumentException;
632         }
633
634         $constraint = new PHPUnit_Framework_Constraint_FileExists;
635
636         self::assertThat($filename, $constraint, $message);
637     }
638
639     /**
640      * Asserts that a file does not exist.
641      *
642      * @param  string $filename
643      * @param  string $message
644      * @since  Method available since Release 3.0.0
645      */
646     public static function assertFileNotExists($filename, $message = '')
647     {
648         if (!is_string($filename)) {
649             throw new InvalidArgumentException;
650         }
651
652         $constraint = new PHPUnit_Framework_Constraint_Not(
653           new PHPUnit_Framework_Constraint_FileExists
654         );
655
656         self::assertThat($filename, $constraint, $message);
657     }
658
659     /**
660      * Asserts that a condition is true.
661      *
662      * @param  boolean $condition
663      * @param  string  $message
664      * @throws PHPUnit_Framework_AssertionFailedError
665      */
666     public static function assertTrue($condition, $message = '')
667     {
668         self::assertThat($condition, self::isTrue(), $message);
669     }
670
671     /**
672      * Asserts that a condition is false.
673      *
674      * @param  boolean  $condition
675      * @param  string   $message
676      * @throws PHPUnit_Framework_AssertionFailedError
677      */
678     public static function assertFalse($condition, $message = '')
679     {
680         self::assertThat($condition, self::isFalse(), $message);
681     }
682
683     /**
684      * Asserts that a variable is not NULL.
685      *
686      * @param  mixed  $actual
687      * @param  string $message
688      */
689     public static function assertNotNull($actual, $message = '')
690     {
691         self::assertThat($actual, self::logicalNot(self::isNull()), $message);
692     }
693
694     /**
695      * Asserts that a variable is NULL.
696      *
697      * @param  mixed  $actual
698      * @param  string $message
699      */
700     public static function assertNull($actual, $message = '')
701     {
702         self::assertThat($actual, self::isNull(), $message);
703     }
704
705     /**
706      * Asserts that a class has a specified attribute.
707      *
708      * @param  string $attributeName
709      * @param  string $className
710      * @param  string $message
711      * @since  Method available since Release 3.1.0
712      */
713     public static function assertClassHasAttribute($attributeName, $className, $message = '')
714     {
715         if (!is_string($attributeName) || !is_string($className) || !class_exists($className, FALSE)) {
716             throw new InvalidArgumentException;
717         }
718
719         $constraint = new PHPUnit_Framework_Constraint_ClassHasAttribute($attributeName);
720
721         self::assertThat($className, $constraint, $message);
722     }
723
724     /**
725      * Asserts that a class does not have a specified attribute.
726      *
727      * @param  string $attributeName
728      * @param  string $className
729      * @param  string $message
730      * @since  Method available since Release 3.1.0
731      */
732     public static function assertClassNotHasAttribute($attributeName, $className, $message = '')
733     {
734         if (!is_string($attributeName) || !is_string($className) || !class_exists($className)) {
735             throw new InvalidArgumentException;
736         }
737
738         $constraint = new PHPUnit_Framework_Constraint_Not(
739           new PHPUnit_Framework_Constraint_ClassHasAttribute($attributeName)
740         );
741
742         self::assertThat($className, $constraint, $message);
743     }
744
745     /**
746      * Asserts that a class has a specified static attribute.
747      *
748      * @param  string $attributeName
749      * @param  string $className
750      * @param  string $message
751      * @since  Method available since Release 3.1.0
752      */
753     public static function assertClassHasStaticAttribute($attributeName, $className, $message = '')
754     {
755         if (!is_string($attributeName) || !is_string($className) || !class_exists($className)) {
756             throw new InvalidArgumentException;
757         }
758
759         $constraint = new PHPUnit_Framework_Constraint_ClassHasStaticAttribute($attributeName);
760
761         self::assertThat($className, $constraint, $message);
762     }
763
764     /**
765      * Asserts that a class does not have a specified static attribute.
766      *
767      * @param  string $attributeName
768      * @param  string $className
769      * @param  string $message
770      * @since  Method available since Release 3.1.0
771      */
772     public static function assertClassNotHasStaticAttribute($attributeName, $className, $message = '')
773     {
774         if (!is_string($attributeName) || !is_string($className) || !class_exists($className)) {
775             throw new InvalidArgumentException;
776         }
777
778         $constraint = new PHPUnit_Framework_Constraint_Not(
779           new PHPUnit_Framework_Constraint_ClassHasStaticAttribute($attributeName)
780         );
781
782         self::assertThat($className, $constraint, $message);
783     }
784
785     /**
786      * Asserts that an object has a specified attribute.
787      *
788      * @param  string $attributeName
789      * @param  object $object
790      * @param  string $message
791      * @since  Method available since Release 3.0.0
792      */
793     public static function assertObjectHasAttribute($attributeName, $object, $message = '')
794     {
795         if (!is_string($attributeName) || !is_object($object)) {
796             throw new InvalidArgumentException;
797         }
798
799         $constraint = new PHPUnit_Framework_Constraint_ObjectHasAttribute($attributeName);
800
801         self::assertThat($object, $constraint, $message);
802     }
803
804     /**
805      * Asserts that an object does not have a specified attribute.
806      *
807      * @param  string $attributeName
808      * @param  object $object
809      * @param  string $message
810      * @since  Method available since Release 3.0.0
811      */
812     public static function assertObjectNotHasAttribute($attributeName, $object, $message = '')
813     {
814         if (!is_string($attributeName) || !is_object($object)) {
815             throw new InvalidArgumentException;
816         }
817
818         $constraint = new PHPUnit_Framework_Constraint_Not(
819           new PHPUnit_Framework_Constraint_ObjectHasAttribute($attributeName)
820         );
821
822         self::assertThat($object, $constraint, $message);
823     }
824
825     /**
826      * Asserts that two variables have the same type and value.
827      * Used on objects, it asserts that two variables reference
828      * the same object.
829      *
830      * @param  mixed  $expected
831      * @param  mixed  $actual
832      * @param  string $message
833      */
834     public static function assertSame($expected, $actual, $message = '')
835     {
836         if (is_bool($expected) && is_bool($actual)) {
837             self::assertEquals($expected, $actual, $message);
838         } else {
839             $constraint = new PHPUnit_Framework_Constraint_IsIdentical($expected);
840
841             self::assertThat($actual, $constraint, $message);
842         }
843     }
844
845     /**
846      * Asserts that a variable and an attribute of an object have the same type
847      * and value.
848      *
849      * @param  mixed  $expected
850      * @param  string $actualAttributeName
851      * @param  object $actualClassOrObject
852      * @param  string $message
853      */
854     public static function assertAttributeSame($expected, $actualAttributeName, $actualClassOrObject, $message = '')
855     {
856         self::assertSame(
857           $expected,
858           self::readAttribute($actualClassOrObject, $actualAttributeName),
859           $message
860         );
861     }
862
863     /**
864      * Asserts that two variables do not have the same type and value.
865      * Used on objects, it asserts that two variables do not reference
866      * the same object.
867      *
868      * @param  mixed  $expected
869      * @param  mixed  $actual
870      * @param  string $message
871      */
872     public static function assertNotSame($expected, $actual, $message = '')
873     {
874         if (is_bool($expected) && is_bool($actual)) {
875             self::assertNotEquals($expected, $actual, $message);
876         } else {
877             $constraint = new PHPUnit_Framework_Constraint_Not(
878               new PHPUnit_Framework_Constraint_IsIdentical($expected)
879             );
880
881             self::assertThat($actual, $constraint, $message);
882         }
883     }
884
885     /**
886      * Asserts that a variable and an attribute of an object do not have the
887      * same type and value.
888      *
889      * @param  mixed  $expected
890      * @param  string $actualAttributeName
891      * @param  object $actualClassOrObject
892      * @param  string $message
893      */
894     public static function assertAttributeNotSame($expected, $actualAttributeName, $actualClassOrObject, $message = '')
895     {
896         self::assertNotSame(
897           $expected,
898           self::readAttribute($actualClassOrObject, $actualAttributeName),
899           $message
900         );
901     }
902
903     /**
904      * Asserts that a variable is of a given type.
905      *
906      * @param  string $expected
907      * @param  mixed  $actual
908      * @param  string $message
909      */
910     public static function assertType($expected, $actual, $message = '')
911     {
912         if (is_string($expected)) {
913             if (PHPUnit_Util_Type::isType($expected)) {
914                 $constraint = new PHPUnit_Framework_Constraint_IsType($expected);
915             }
916
917             else if (class_exists($expected) || interface_exists($expected)) {
918                 $constraint = new PHPUnit_Framework_Constraint_IsInstanceOf(
919                   $expected
920                 );
921             }
922
923             else {
924                 throw new InvalidArgumentException;
925             }
926         } else {
927             throw new InvalidArgumentException;
928         }
929
930         self::assertThat($actual, $constraint, $message);
931     }
932
933     /**
934      * Asserts that a variable is not of a given type.
935      *
936      * @param  string $expected
937      * @param  mixed  $actual
938      * @param  string $message
939      * @since  Method available since Release 2.2.0
940      */
941     public static function assertNotType($expected, $actual, $message = '')
942     {
943         if (is_string($expected)) {
944             if (PHPUnit_Util_Type::isType($expected)) {
945                 $constraint = new PHPUnit_Framework_Constraint_Not(
946                   new PHPUnit_Framework_Constraint_IsType($expected)
947                 );
948             }
949
950             else if (class_exists($expected) || interface_exists($expected)) {
951                 $constraint = new PHPUnit_Framework_Constraint_Not(
952                   new PHPUnit_Framework_Constraint_IsInstanceOf($expected)
953                 );
954             }
955
956             else {
957                 throw new InvalidArgumentException;
958             }
959         } else {
960             throw new InvalidArgumentException;
961         }
962
963         self::assertThat($actual, $constraint, $message);
964     }
965
966     /**
967      * Asserts that a string matches a given regular expression.
968      *
969      * @param  string $pattern
970      * @param  string $string
971      * @param  string $message
972      */
973     public static function assertRegExp($pattern, $string, $message = '')
974     {
975         if (!is_string($pattern) || !is_string($string)) {
976             throw new InvalidArgumentException;
977         }
978
979         $constraint = new PHPUnit_Framework_Constraint_PCREMatch($pattern);
980
981         self::assertThat($string, $constraint, $message);
982     }
983
984     /**
985      * Asserts that a string does not match a given regular expression.
986      *
987      * @param  string $pattern
988      * @param  string $string
989      * @param  string $message
990      * @since  Method available since Release 2.1.0
991      */
992     public static function assertNotRegExp($pattern, $string, $message = '')
993     {
994         if (!is_string($pattern) || !is_string($string)) {
995             throw new InvalidArgumentException;
996         }
997
998         $constraint = new PHPUnit_Framework_Constraint_Not(
999           new PHPUnit_Framework_Constraint_PCREMatch($pattern)
1000         );
1001
1002         self::assertThat($string, $constraint, $message);
1003     }
1004
1005     /**
1006      * Asserts that two XML files are equal.
1007      *
1008      * @param  string $expectedFile
1009      * @param  string $actualFile
1010      * @param  string $message
1011      * @since  Method available since Release 3.1.0
1012      */
1013     public static function assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = '')
1014     {
1015         self::assertFileExists($expectedFile);
1016         self::assertFileExists($actualFile);
1017
1018         $expected = new DOMDocument;
1019         $expected->preserveWhiteSpace = FALSE;
1020         $expected->load($expectedFile);
1021
1022         $actual = new DOMDocument;
1023         $actual->preserveWhiteSpace = FALSE;
1024         $actual->load($actualFile);
1025
1026         self::assertEquals($expected, $actual, $message);
1027     }
1028
1029     /**
1030      * Asserts that two XML files are not equal.
1031      *
1032      * @param  string $expectedFile
1033      * @param  string $actualFile
1034      * @param  string $message
1035      * @since  Method available since Release 3.1.0
1036      */
1037     public static function assertXmlFileNotEqualsXmlFile($expectedFile, $actualFile, $message = '')
1038     {
1039         self::assertFileExists($expectedFile);
1040         self::assertFileExists($actualFile);
1041
1042         $expected = new DOMDocument;
1043         $expected->preserveWhiteSpace = FALSE;
1044         $expected->load($expectedFile);
1045
1046         $actual = new DOMDocument;
1047         $actual->preserveWhiteSpace = FALSE;
1048         $actual->load($actualFile);
1049
1050         self::assertNotEquals($expected, $actual, $message);
1051     }
1052
1053     /**
1054      * Asserts that two XML documents are equal.
1055      *
1056      * @param  string $expectedFile
1057      * @param  string $actualXml
1058      * @param  string $message
1059      * @since  Method available since Release 3.3.0
1060      */
1061     public static function assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = '')
1062     {
1063         self::assertFileExists($expectedFile);
1064
1065         $expected = new DOMDocument;
1066         $expected->preserveWhiteSpace = FALSE;
1067         $expected->load($expectedFile);
1068
1069         $actual = new DOMDocument;
1070         $actual->preserveWhiteSpace = FALSE;
1071         $actual->loadXML($actualXml);
1072
1073         self::assertEquals($expected, $actual, $message);
1074     }
1075
1076     /**
1077      * Asserts that two XML documents are not equal.
1078      *
1079      * @param  string $expectedFile
1080      * @param  string $actualXml
1081      * @param  string $message
1082      * @since  Method available since Release 3.3.0
1083      */
1084     public static function assertXmlStringNotEqualsXmlFile($expectedFile, $actualXml, $message = '')
1085     {
1086         self::assertFileExists($expectedFile);
1087
1088         $expected = new DOMDocument;
1089         $expected->preserveWhiteSpace = FALSE;
1090         $expected->load($expectedFile);
1091
1092         $actual = new DOMDocument;
1093         $actual->preserveWhiteSpace = FALSE;
1094         $actual->loadXML($actualXml);
1095
1096         self::assertNotEquals($expected, $actual, $message);
1097     }
1098
1099     /**
1100      * Asserts that two XML documents are equal.
1101      *
1102      * @param  string $expectedXml
1103      * @param  string $actualXml
1104      * @param  string $message
1105      * @since  Method available since Release 3.1.0
1106      */
1107     public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = '')
1108     {
1109         $expected = new DOMDocument;
1110         $expected->preserveWhiteSpace = FALSE;
1111         $expected->loadXML($expectedXml);
1112
1113         $actual = new DOMDocument;
1114         $actual->preserveWhiteSpace = FALSE;
1115         $actual->loadXML($actualXml);
1116
1117         self::assertEquals($expected, $actual, $message);
1118     }
1119
1120     /**
1121      * Asserts that two XML documents are not equal.
1122      *
1123      * @param  string $expectedXml
1124      * @param  string $actualXml
1125      * @param  string $message
1126      * @since  Method available since Release 3.1.0
1127      */
1128     public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, $message = '')
1129     {
1130         $expected = new DOMDocument;
1131         $expected->preserveWhiteSpace = FALSE;
1132         $expected->loadXML($expectedXml);
1133
1134         $actual = new DOMDocument;
1135         $actual->preserveWhiteSpace = FALSE;
1136         $actual->loadXML($actualXml);
1137
1138         self::assertNotEquals($expected, $actual, $message);
1139     }
1140
1141     /**
1142      * Asserts that a hierarchy of DOMNodes matches.
1143      *
1144      * @param DOMNode $expectedNode
1145      * @param DOMNode $actualNode
1146      * @param boolean $checkAttributes
1147      * @param string  $message
1148      * @author Mattis Stordalen Flister <mattis@xait.no>
1149      * @since  Method available since Release 3.3.0
1150      */
1151     public static function assertEqualXMLStructure(DOMNode $expectedNode, DOMNode $actualNode, $checkAttributes = FALSE, $message = '')
1152     {
1153         self::assertEquals(
1154           $expectedNode->tagName,
1155           $actualNode->tagName,
1156           $message
1157         );
1158
1159         if ($checkAttributes) {
1160             self::assertEquals(
1161               $expectedNode->attributes->length,
1162               $actualNode->attributes->length,
1163               sprintf(
1164                 '%s%sNumber of attributes on node "%s" does not match',
1165                 $message,
1166                 !empty($message) ? "\n" : '',
1167                 $expectedNode->tagName
1168               )
1169             );
1170
1171             for ($i = 0 ; $i < $expectedNode->attributes->length; $i++) {
1172                 $expectedAttribute = $expectedNode->attributes->item($i);
1173                 $actualAttribute   = $actualNode->attributes->getNamedItem($expectedAttribute->name);
1174
1175                 if (!$actualAttribute) {
1176                     self::fail(
1177                       sprintf(
1178                         '%s%sCould not find attribute "%s" on node "%s"',
1179                         $message,
1180                         !empty($message) ? "\n" : '',
1181                         $expectedAttribute->name,
1182                         $expectedNode->tagName
1183                       )
1184                     );
1185                 }
1186             }
1187         }
1188
1189         PHPUnit_Util_XML::removeCharacterDataNodes($expectedNode);
1190         PHPUnit_Util_XML::removeCharacterDataNodes($actualNode);
1191
1192         self::assertEquals(
1193           $expectedNode->childNodes->length,
1194           $actualNode->childNodes->length,
1195           sprintf(
1196             '%s%sNumber of child nodes of "%s" differs',
1197             $message,
1198             !empty($message) ? "\n" : '',
1199             $expectedNode->tagName
1200           )
1201         );
1202
1203         for ($i = 0; $i < $expectedNode->childNodes->length; $i++) {
1204             self::assertEqualXMLStructure(
1205               $expectedNode->childNodes->item($i),
1206               $actualNode->childNodes->item($i),
1207               $checkAttributes,
1208               $message
1209             );
1210         }
1211     }
1212
1213     /**
1214      * Assert the presence, absence, or count of elements in a document matching
1215      * the CSS $selector, regardless of the contents of those elements.
1216      *
1217      * The first argument, $selector, is the CSS selector used to match
1218      * the elements in the $actual document.
1219      *
1220      * The second argument, $count, can be either boolean or numeric.  When boolean,
1221      * it asserts for presence of elements matching the selector (TRUE) or absence
1222      * of elements (FALSE).  When numeric, it asserts the count of elements
1223      *
1224      * assertSelectCount("#binder", true, $xml);  // any?
1225      * assertSelectCount(".binder", 3, $xml);     // exactly 3?
1226      *
1227      * @param  array   $selector
1228      * @param  integer $count
1229      * @param  mixed   $actual
1230      * @param  string  $message
1231      * @param  boolean $isHtml
1232      * @since  Method available since Release 3.3.0
1233      * @author Mike Naberezny <mike@maintainable.com>
1234      * @author Derek DeVries <derek@maintainable.com>
1235      */
1236     public static function assertSelectCount($selector, $count, $actual, $message = '', $isHtml = TRUE)
1237     {
1238         self::assertSelectEquals($selector, TRUE, $count, $actual, $message, $isHtml);
1239     }
1240
1241     /**
1242      * assertSelectRegExp("#binder .name", "/Mike|Derek/", true, $xml); // any?
1243      * assertSelectRegExp("#binder .name", "/Mike|Derek/", 3, $xml);    // exactly 3?
1244      *
1245      * @param  array   $selector
1246      * @param  string  $pattern
1247      * @param  integer $count
1248      * @param  mixed   $actual
1249      * @param  string  $message
1250      * @param  boolean $isHtml
1251      * @since  Method available since Release 3.3.0
1252      * @author Mike Naberezny <mike@maintainable.com>
1253      * @author Derek DeVries <derek@maintainable.com>
1254      */
1255     public static function assertSelectRegExp($selector, $pattern, $count, $actual, $message = '', $isHtml = TRUE)
1256     {
1257         self::assertSelectEquals($selector, "regexp:$pattern", $count, $actual, $message, $isHtml);
1258     }
1259
1260     /**
1261      * assertSelectEquals("#binder .name", "Chuck", true,  $xml);  // any?
1262      * assertSelectEquals("#binder .name", "Chuck", false, $xml);  // none?
1263      *
1264      * @param  array   $selector
1265      * @param  string  $content
1266      * @param  integer $count
1267      * @param  mixed   $actual
1268      * @param  string  $message
1269      * @param  boolean $isHtml
1270      * @since  Method available since Release 3.3.0
1271      * @author Mike Naberezny <mike@maintainable.com>
1272      * @author Derek DeVries <derek@maintainable.com>
1273      */
1274     public static function assertSelectEquals($selector, $content, $count, $actual, $message = '', $isHtml = TRUE)
1275     {
1276         $tags = PHPUnit_Util_XML::cssSelect($selector, $content, $actual, $isHtml);
1277
1278         // assert specific number of elements
1279         if (is_numeric($count)) {
1280             $counted = $tags ? count($tags) : 0;
1281             self::assertEquals($count, $counted);
1282
1283         // assert any elements exist if true, assert no elements exist if false
1284         } else if (is_bool($count)) {
1285             $any = count($tags) > 0 && $tags[0] instanceof DOMNode;
1286
1287             if ($count) {
1288                 self::assertTrue($any, $message);
1289             } else {
1290                 self::assertFalse($any, $message);
1291             }
1292
1293         // check for range number of elements
1294         } else if (is_array($count) && (isset($count['>']) || isset($count['<']) ||
1295                 isset($count['>=']) || isset($count['<=']))) {
1296             $counted = $tags ? count($tags) : 0;
1297
1298             if (isset($count['>'])) {
1299                 self::assertTrue($counted > $count['>'], $message);
1300             }
1301
1302             if (isset($count['>='])) {
1303                 self::assertTrue($counted >= $count['>='], $message);
1304             }
1305
1306             if (isset($count['<'])) {
1307                 self::assertTrue($counted < $count['<'], $message);
1308             }
1309
1310             if (isset($count['<='])) {
1311                 self::assertTrue($counted <= $count['<='], $message);
1312             }
1313
1314         } else {
1315             throw new InvalidArgumentException();
1316         }
1317     }
1318
1319     /**
1320      * Evaluate an HTML or XML string and assert its structure and/or contents.
1321      *
1322      * The first argument ($matcher) is an associative array that specifies the
1323      * match criteria for the assertion:
1324      *
1325      *  - `id`           : the node with the given id attribute must match the corresponsing value.
1326      *  - `tag`          : the node type must match the corresponding value.
1327      *  - `attributes`   : a hash. The node's attributres must match the corresponsing values in the hash.
1328      *  - `content`      : The text content must match the given value.
1329      *  - `parent`       : a hash. The node's parent must match the corresponsing hash.
1330      *  - `child`        : a hash. At least one of the node's immediate children must meet the criteria described by the hash.
1331      *  - `ancestor`     : a hash. At least one of the node's ancestors must meet the criteria described by the hash.
1332      *  - `descendant`   : a hash. At least one of the node's descendants must meet the criteria described by the hash.
1333      *  - `children`     : a hash, for counting children of a node. Accepts the keys:
1334      *    - `count`        : a number which must equal the number of children that match
1335      *    - `less_than`    : the number of matching children must be greater than this number
1336      *    - `greater_than` : the number of matching children must be less than this number
1337      *    - `only`         : another hash consisting of the keys to use to match on the children, and only matching children will be counted
1338      *
1339      * <code>
1340      * // Matcher that asserts that there is an element with an id="my_id".
1341      * $matcher = array('id' => 'my_id');
1342      *
1343      * // Matcher that asserts that there is a "span" tag.
1344      * $matcher = array('tag' => 'span');
1345      *
1346      * // Matcher that asserts that there is a "span" tag with the content
1347      * // "Hello World".
1348      * $matcher = array('tag' => 'span', 'content' => 'Hello World');
1349      *
1350      * // Matcher that asserts that there is a "span" tag with content matching the
1351      * // regular expression pattern.
1352      * $matcher = array('tag' => 'span', 'content' => '/Try P(HP|ython)/');
1353      *
1354      * // Matcher that asserts that there is a "span" with an "list" class attribute.
1355      * $matcher = array(
1356      *   'tag'        => 'span',
1357      *   'attributes' => array('class' => 'list')
1358      * );
1359      *
1360      * // Matcher that asserts that there is a "span" inside of a "div".
1361      * $matcher = array(
1362      *   'tag'    => 'span',
1363      *   'parent' => array('tag' => 'div')
1364      * );
1365      *
1366      * // Matcher that asserts that there is a "span" somewhere inside a "table".
1367      * $matcher = array(
1368      *   'tag'      => 'span',
1369      *   'ancestor' => array('tag' => 'table')
1370      * );
1371      *
1372      * // Matcher that asserts that there is a "span" with at least one "em" child.
1373      * $matcher = array(
1374      *   'tag'   => 'span',
1375      *   'child' => array('tag' => 'em')
1376      * );
1377      *
1378      * // Matcher that asserts that there is a "span" containing a (possibly nested)
1379      * // "strong" tag.
1380      * $matcher = array(
1381      *   'tag'        => 'span',
1382      *   'descendant' => array('tag' => 'strong')
1383      * );
1384      *
1385      * // Matcher that asserts that there is a "span" containing 5-10 "em" tags as
1386      * // immediate children.
1387      * $matcher = array(
1388      *   'tag'      => 'span',
1389      *   'children' => array(
1390      *     'less_than'    => 11,
1391      *     'greater_than' => 4,
1392      *     'only'         => array('tag' => 'em')
1393      *   )
1394      * );
1395      *
1396      * // Matcher that asserts that there is a "div", with an "ul" ancestor and a "li"
1397      * // parent (with class="enum"), and containing a "span" descendant that contains
1398      * // an element with id="my_test" and the text "Hello World".
1399      * $matcher = array(
1400      *   'tag'        => 'div',
1401      *   'ancestor'   => array('tag' => 'ul'),
1402      *   'parent'     => array(
1403      *     'tag'        => 'li',
1404      *     'attributes' => array('class' => 'enum')
1405      *   ),
1406      *   'descendant' => array(
1407      *     'tag'   => 'span',
1408      *     'child' => array(
1409      *       'id'      => 'my_test',
1410      *       'content' => 'Hello World'
1411      *     )
1412      *   )
1413      * );
1414      *
1415      * // Use assertTag() to apply a $matcher to a piece of $html.
1416      * $this->assertTag($matcher, $html);
1417      *
1418      * // Use assertTag() to apply a $matcher to a piece of $xml.
1419      * $this->assertTag($matcher, $xml, '', FALSE);
1420      * </code>
1421      *
1422      * The second argument ($actual) is a string containing either HTML or
1423      * XML text to be tested.
1424      *
1425      * The third argument ($message) is an optional message that will be
1426      * used if the assertion fails.
1427      *
1428      * The fourth argument ($html) is an optional flag specifying whether
1429      * to load the $actual string into a DOMDocument using the HTML or
1430      * XML load strategy.  It is TRUE by default, which assumes the HTML
1431      * load strategy.  In many cases, this will be acceptable for XML as well.
1432      *
1433      * @param  array   $matcher
1434      * @param  string  $actual
1435      * @param  string  $message
1436      * @param  boolean $isHtml
1437      * @since  Method available since Release 3.3.0
1438      * @author Mike Naberezny <mike@maintainable.com>
1439      * @author Derek DeVries <derek@maintainable.com>
1440      */
1441     public static function assertTag($matcher, $actual, $message = '', $isHtml = TRUE)
1442     {
1443         $dom     = PHPUnit_Util_XML::load($actual, $isHtml);
1444         $tags    = PHPUnit_Util_XML::findNodes($dom, $matcher);
1445         $matched = count($tags) > 0 && $tags[0] instanceof DOMNode;
1446
1447         self::assertTrue($matched, $message);
1448     }
1449
1450     /**
1451      * This assertion is the exact opposite of assertTag().  Rather than asserting
1452      * that $matcher results in a match, it asserts that $matcher does not match.
1453      *
1454      * @param  array   $matcher
1455      * @param  string  $actual
1456      * @param  string  $message
1457      * @param  boolean $isHtml
1458      * @since  Method available since Release 3.3.0
1459      * @author Mike Naberezny <mike@maintainable.com>
1460      * @author Derek DeVries <derek@maintainable.com>
1461      */
1462     public static function assertNotTag($matcher, $actual, $message = '', $isHtml = TRUE)
1463     {
1464         $dom     = PHPUnit_Util_XML::load($actual, $isHtml);
1465         $tags    = PHPUnit_Util_XML::findNodes($dom, $matcher);
1466         $matched = count($tags) > 0 && $tags[0] instanceof DOMNode;
1467
1468         self::assertFalse($matched, $message);
1469     }
1470
1471     /**
1472      * Evaluates a PHPUnit_Framework_Constraint matcher object.
1473      *
1474      * @param  mixed                        $value
1475      * @param  PHPUnit_Framework_Constraint $constraint
1476      * @param  string                       $message
1477      * @since  Method available since Release 3.0.0
1478      */
1479     public static function assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '')
1480     {
1481         self::$count++;
1482
1483         if (!$constraint->evaluate($value)) {
1484             $constraint->fail($value, $message);
1485         }
1486     }
1487
1488     /**
1489      * Returns a PHPUnit_Framework_Constraint_And matcher object.
1490      *
1491      * @return PHPUnit_Framework_Constraint_And
1492      * @since  Method available since Release 3.0.0
1493      */
1494     public static function logicalAnd()
1495     {
1496         $constraints = func_get_args();
1497
1498         $constraint = new PHPUnit_Framework_Constraint_And;
1499         $constraint->setConstraints($constraints);
1500
1501         return $constraint;
1502     }
1503
1504     /**
1505      * Returns a PHPUnit_Framework_Constraint_Or matcher object.
1506      *
1507      * @return PHPUnit_Framework_Constraint_Or
1508      * @since  Method available since Release 3.0.0
1509      */
1510     public static function logicalOr()
1511     {
1512         $constraints = func_get_args();
1513
1514         $constraint = new PHPUnit_Framework_Constraint_Or;
1515         $constraint->setConstraints($constraints);
1516
1517         return $constraint;
1518     }
1519
1520     /**
1521      * Returns a PHPUnit_Framework_Constraint_Not matcher object.
1522      *
1523      * @param  PHPUnit_Framework_Constraint $constraint
1524      * @return PHPUnit_Framework_Constraint_Not
1525      * @since  Method available since Release 3.0.0
1526      */
1527     public static function logicalNot(PHPUnit_Framework_Constraint $constraint)
1528     {
1529         return new PHPUnit_Framework_Constraint_Not($constraint);
1530     }
1531
1532     /**
1533      * Returns a PHPUnit_Framework_Constraint_Xor matcher object.
1534      *
1535      * @return PHPUnit_Framework_Constraint_Xor
1536      * @since  Method available since Release 3.0.0
1537      */
1538     public static function logicalXor()
1539     {
1540         $constraints = func_get_args();
1541
1542         $constraint = new PHPUnit_Framework_Constraint_Xor;
1543         $constraint->setConstraints($constraints);
1544
1545         return $constraint;
1546     }
1547
1548     /**
1549      * Returns a PHPUnit_Framework_Constraint_IsAnything matcher object.
1550      *
1551      * @return PHPUnit_Framework_Constraint_IsAnything
1552      * @since  Method available since Release 3.0.0
1553      */
1554     public static function anything()
1555     {
1556         return new PHPUnit_Framework_Constraint_IsAnything;
1557     }
1558
1559     /**
1560      * Returns a PHPUnit_Framework_Constraint_IsTrue matcher object.
1561      *
1562      * @return PHPUnit_Framework_Constraint_IsTrue
1563      * @since  Method available since Release 3.3.0
1564      */
1565     public static function isTrue()
1566     {
1567         return new PHPUnit_Framework_Constraint_IsTrue;
1568     }
1569
1570     /**
1571      * Returns a PHPUnit_Framework_Constraint_IsFalse matcher object.
1572      *
1573      * @return PHPUnit_Framework_Constraint_IsFalse
1574      * @since  Method available since Release 3.3.0
1575      */
1576     public static function isFalse()
1577     {
1578         return new PHPUnit_Framework_Constraint_IsFalse;
1579     }
1580
1581     /**
1582      * Returns a PHPUnit_Framework_Constraint_IsNull matcher object.
1583      *
1584      * @return PHPUnit_Framework_Constraint_IsNull
1585      * @since  Method available since Release 3.3.0
1586      */
1587     public static function isNull()
1588     {
1589         return new PHPUnit_Framework_Constraint_IsNull;
1590     }
1591
1592     /**
1593      * Returns a PHPUnit_Framework_Constraint_Attribute matcher object.
1594      *
1595      * @param  PHPUnit_Framework_Constraint $constraint
1596      * @param  string                       $attributeName
1597      * @return PHPUnit_Framework_Constraint_Attribute
1598      * @since  Method available since Release 3.1.0
1599      */
1600     public static function attribute(PHPUnit_Framework_Constraint $constraint, $attributeName)
1601     {
1602         return new PHPUnit_Framework_Constraint_Attribute(
1603           $constraint, $attributeName
1604         );
1605     }
1606
1607     /**
1608      * Returns a PHPUnit_Framework_Constraint_TraversableContains matcher
1609      * object.
1610      *
1611      * @param  mixed $value
1612      * @return PHPUnit_Framework_Constraint_TraversableContains
1613      * @since  Method available since Release 3.0.0
1614      */
1615     public static function contains($value)
1616     {
1617         return new PHPUnit_Framework_Constraint_TraversableContains($value);
1618     }
1619
1620     /**
1621      * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher
1622      * object.
1623      *
1624      * @param  string $type
1625      * @return PHPUnit_Framework_Constraint_TraversableContainsOnly
1626      * @since  Method available since Release 3.1.4
1627      */
1628     public static function containsOnly($type)
1629     {
1630         return new PHPUnit_Framework_Constraint_TraversableContainsOnly($type);
1631     }
1632
1633     /**
1634      * Returns a PHPUnit_Framework_Constraint_ArrayHasKey matcher object.
1635      *
1636      * @param  mixed $key
1637      * @return PHPUnit_Framework_Constraint_ArrayHasKey
1638      * @since  Method available since Release 3.0.0
1639      */
1640     public static function arrayHasKey($key)
1641     {
1642         return new PHPUnit_Framework_Constraint_ArrayHasKey($key);
1643     }
1644
1645     /**
1646      * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object.
1647      *
1648      * @param  mixed   $value
1649      * @param  float   $delta
1650      * @param  integer $maxDepth
1651      * @return PHPUnit_Framework_Constraint_IsEqual
1652      * @since  Method available since Release 3.0.0
1653      */
1654     public static function equalTo($value, $delta = 0, $maxDepth = 10)
1655     {
1656         return new PHPUnit_Framework_Constraint_IsEqual($value, $delta, $maxDepth);
1657     }
1658
1659     /**
1660      * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object
1661      * that is wrapped in a PHPUnit_Framework_Constraint_Attribute matcher
1662      * object.
1663      *
1664      * @param  string  $attributeName
1665      * @param  mixed   $value
1666      * @param  float   $delta
1667      * @param  integer $maxDepth
1668      * @return PHPUnit_Framework_Constraint_Attribute
1669      * @since  Method available since Release 3.1.0
1670      */
1671     public static function attributeEqualTo($attributeName, $value, $delta = 0, $maxDepth = 10)
1672     {
1673         return new PHPUnit_Framework_Constraint_Attribute(
1674           new PHPUnit_Framework_Constraint_IsEqual($value, $delta, $maxDepth),
1675           $attributeName
1676         );
1677     }
1678
1679     /**
1680      * Returns a PHPUnit_Framework_Constraint_FileExists matcher object.
1681      *
1682      * @return PHPUnit_Framework_Constraint_FileExists
1683      * @since  Method available since Release 3.0.0
1684      */
1685     public static function fileExists()
1686     {
1687         return new PHPUnit_Framework_Constraint_FileExists;
1688     }
1689
1690     /**
1691      * Returns a PHPUnit_Framework_Constraint_GreaterThan matcher object.
1692      *
1693      * @param  mixed $value
1694      * @return PHPUnit_Framework_Constraint_GreaterThan
1695      * @since  Method available since Release 3.0.0
1696      */
1697     public static function greaterThan($value)
1698     {
1699         return new PHPUnit_Framework_Constraint_GreaterThan($value);
1700     }
1701
1702     /**
1703      * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps
1704      * a PHPUnit_Framework_Constraint_IsEqual and a
1705      * PHPUnit_Framework_Constraint_GreaterThan matcher object.
1706      *
1707      * @param  mixed $value
1708      * @return PHPUnit_Framework_Constraint_Or
1709      * @since  Method available since Release 3.1.0
1710      */
1711     public static function greaterThanOrEqual($value)
1712     {
1713         return self::logicalOr(
1714           new PHPUnit_Framework_Constraint_IsEqual($value),
1715           new PHPUnit_Framework_Constraint_GreaterThan($value)
1716         );
1717     }
1718
1719     /**
1720      * Returns a PHPUnit_Framework_Constraint_ClassHasAttribute matcher object.
1721      *
1722      * @param  string $attributeName
1723      * @return PHPUnit_Framework_Constraint_ClassHasAttribute
1724      * @since  Method available since Release 3.1.0
1725      */
1726     public static function classHasAttribute($attributeName)
1727     {
1728         return new PHPUnit_Framework_Constraint_ClassHasAttribute($attributeName);
1729     }
1730
1731     /**
1732      * Returns a PHPUnit_Framework_Constraint_ClassHasStaticAttribute matcher
1733      * object.
1734      *
1735      * @param  string $attributeName
1736      * @return PHPUnit_Framework_Constraint_ClassHasStaticAttribute
1737      * @since  Method available since Release 3.1.0
1738      */
1739     public static function classHasStaticAttribute($attributeName)
1740     {
1741         return new PHPUnit_Framework_Constraint_ClassHasStaticAttribute($attributeName);
1742     }
1743
1744     /**
1745      * Returns a PHPUnit_Framework_Constraint_ObjectHasAttribute matcher object.
1746      *
1747      * @param  string $attributeName
1748      * @return PHPUnit_Framework_Constraint_ObjectHasAttribute
1749      * @since  Method available since Release 3.0.0
1750      */
1751     public static function objectHasAttribute($attributeName)
1752     {
1753         return new PHPUnit_Framework_Constraint_ObjectHasAttribute($attributeName);
1754     }
1755
1756     /**
1757      * Returns a PHPUnit_Framework_Constraint_IsIdentical matcher object.
1758      *
1759      * @param  mixed $value
1760      * @return PHPUnit_Framework_Constraint_IsIdentical
1761      * @since  Method available since Release 3.0.0
1762      */
1763     public static function identicalTo($value)
1764     {
1765         return new PHPUnit_Framework_Constraint_IsIdentical($value);
1766     }
1767
1768     /**
1769      * Returns a PHPUnit_Framework_Constraint_IsInstanceOf matcher object.
1770      *
1771      * @param  string $className
1772      * @return PHPUnit_Framework_Constraint_IsInstanceOf
1773      * @since  Method available since Release 3.0.0
1774      */
1775     public static function isInstanceOf($className)
1776     {
1777         return new PHPUnit_Framework_Constraint_IsInstanceOf($className);
1778     }
1779
1780     /**
1781      * Returns a PHPUnit_Framework_Constraint_IsType matcher object.
1782      *
1783      * @param  string $type
1784      * @return PHPUnit_Framework_Constraint_IsType
1785      * @since  Method available since Release 3.0.0
1786      */
1787     public static function isType($type)
1788     {
1789         return new PHPUnit_Framework_Constraint_IsType($type);
1790     }
1791
1792     /**
1793      * Returns a PHPUnit_Framework_Constraint_LessThan matcher object.
1794      *
1795      * @param  mixed $value
1796      * @return PHPUnit_Framework_Constraint_LessThan
1797      * @since  Method available since Release 3.0.0
1798      */
1799     public static function lessThan($value)
1800     {
1801         return new PHPUnit_Framework_Constraint_LessThan($value);
1802     }
1803
1804     /**
1805      * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps
1806      * a PHPUnit_Framework_Constraint_IsEqual and a
1807      * PHPUnit_Framework_Constraint_LessThan matcher object.
1808      *
1809      * @param  mixed $value
1810      * @return PHPUnit_Framework_Constraint_Or
1811      * @since  Method available since Release 3.1.0
1812      */
1813     public static function lessThanOrEqual($value)
1814     {
1815         return self::logicalOr(
1816           new PHPUnit_Framework_Constraint_IsEqual($value),
1817           new PHPUnit_Framework_Constraint_LessThan($value)
1818         );
1819     }
1820
1821     /**
1822      * Returns a PHPUnit_Framework_Constraint_PCREMatch matcher object.
1823      *
1824      * @param  string $pattern
1825      * @return PHPUnit_Framework_Constraint_PCREMatch
1826      * @since  Method available since Release 3.0.0
1827      */
1828     public static function matchesRegularExpression($pattern)
1829     {
1830         return new PHPUnit_Framework_Constraint_PCREMatch($pattern);
1831     }
1832
1833     /**
1834      * Returns a PHPUnit_Framework_Constraint_StringContains matcher object.
1835      *
1836      * @param  string  $string
1837      * @param  boolean $case
1838      * @return PHPUnit_Framework_Constraint_StringContains
1839      * @since  Method available since Release 3.0.0
1840      */
1841     public static function stringContains($string, $case = TRUE)
1842     {
1843         return new PHPUnit_Framework_Constraint_StringContains($string, $case);
1844     }
1845
1846
1847     /**
1848      * Fails a test with the given message.
1849      *
1850      * @param  string $message
1851      * @throws PHPUnit_Framework_AssertionFailedError
1852      */
1853     public static function fail($message = '')
1854     {
1855         throw new PHPUnit_Framework_AssertionFailedError($message);
1856     }
1857
1858     /**
1859      * Returns the value of an attribute of a class or an object.
1860      * This also works for attributes that are declared protected or private.
1861      *
1862      * @param  mixed   $classOrObject
1863      * @param  string  $attributeName
1864      * @return mixed
1865      * @throws InvalidArgumentException
1866      */
1867     public static function readAttribute($classOrObject, $attributeName)
1868     {
1869         if (!is_string($attributeName)) {
1870             throw new InvalidArgumentException;
1871         }
1872
1873         if (is_string($classOrObject)) {
1874             if (!class_exists($classOrObject)) {
1875                 throw new InvalidArgumentException;
1876             }
1877
1878             return self::getStaticAttribute(
1879               $classOrObject,
1880               $attributeName
1881             );
1882         }
1883
1884         else if (is_object($classOrObject)) {
1885             return self::getObjectAttribute(
1886               $classOrObject,
1887               $attributeName
1888             );
1889         }
1890
1891         else {
1892             throw new InvalidArgumentException;
1893         }
1894     }
1895
1896     /**
1897      * Returns the value of a static attribute.
1898      * This also works for attributes that are declared protected or private.
1899      *
1900      * @param  string  $className
1901      * @param  string  $attributeName
1902      * @return mixed
1903      * @throws InvalidArgumentException
1904      * @since  Method available since Release 3.1.0
1905      */
1906     public static function getStaticAttribute($className, $attributeName)
1907     {
1908         if (!is_string($className) || !class_exists($className) || !is_string($attributeName)) {
1909             throw new InvalidArgumentException;
1910         }
1911
1912         $class      = new ReflectionClass($className);
1913         $attributes = $class->getStaticProperties();
1914
1915         if (array_key_exists($attributeName, $attributes)) {
1916             return $attributes[$attributeName];
1917         }
1918
1919         if (version_compare(PHP_VERSION, '5.2', '<')) {
1920             $protectedName = "\0*\0" . $attributeName;
1921         } else {
1922             $protectedName = '*' . $attributeName;
1923         }
1924
1925         if (array_key_exists($protectedName, $attributes)) {
1926             return $attributes[$protectedName];
1927         }
1928
1929         $classes = PHPUnit_Util_Class::getHierarchy($className);
1930
1931         foreach ($classes as $class) {
1932             $privateName = sprintf(
1933               "\0%s\0%s",
1934
1935               $class,
1936               $attributeName
1937             );
1938
1939             if (array_key_exists($privateName, $attributes)) {
1940                 return $attributes[$privateName];
1941             }
1942         }
1943
1944         throw new RuntimeException(
1945           sprintf(
1946             'Attribute "%s" not found in class.',
1947
1948             $attributeName
1949           )
1950         );
1951     }
1952
1953     /**
1954      * Returns the value of an object's attribute.
1955      * This also works for attributes that are declared protected or private.
1956      *
1957      * @param  object  $object
1958      * @param  string  $attributeName
1959      * @return mixed
1960      * @throws InvalidArgumentException
1961      * @since  Method available since Release 3.1.0
1962      */
1963     public static function getObjectAttribute($object, $attributeName)
1964     {
1965         if (!is_object($object) || !is_string($attributeName)) {
1966             throw new InvalidArgumentException;
1967         }
1968
1969         self::assertObjectHasAttribute($attributeName, $object);
1970
1971         try {
1972             $attribute = new ReflectionProperty($object, $attributeName);
1973         }
1974
1975         catch (ReflectionException $e) {
1976             // Workaround for http://bugs.php.net/46064
1977             if (version_compare(PHP_VERSION, '5.2.7', '<')) {
1978                 $reflector  = new ReflectionObject($object);
1979                 $attributes = $reflector->getProperties();
1980
1981                 foreach ($attributes as $_attribute) {
1982                     if ($_attribute->getName() == $attributeName) {
1983                         $attribute = $_attribute;
1984                         break;
1985                     }
1986                 }
1987             }
1988
1989             $reflector = new ReflectionObject($object);
1990
1991             while ($reflector = $reflector->getParentClass()) {
1992                 try {
1993                     $attribute = $reflector->getProperty($attributeName);
1994                     break;
1995                 }
1996
1997                 catch(ReflectionException $e) {
1998                 }
1999             }
2000         }
2001
2002         if ($attribute->isPublic()) {
2003             return $object->$attributeName;
2004         } else {
2005             $array         = (array)$object;
2006             $protectedName = "\0*\0" . $attributeName;
2007
2008             if (array_key_exists($protectedName, $array)) {
2009                 return $array[$protectedName];
2010             } else {
2011                 $classes = PHPUnit_Util_Class::getHierarchy(get_class($object));
2012
2013                 foreach ($classes as $class) {
2014                     $privateName = sprintf(
2015                       "\0%s\0%s",
2016
2017                       $class,
2018                       $attributeName
2019                     );
2020
2021                     if (array_key_exists($privateName, $array)) {
2022                         return $array[$privateName];
2023                     }
2024                 }
2025             }
2026         }
2027
2028         throw new RuntimeException(
2029           sprintf(
2030             'Attribute "%s" not found in object.',
2031
2032             $attributeName
2033           )
2034         );
2035     }
2036
2037     /**
2038      * Mark the test as incomplete.
2039      *
2040      * @param  string  $message
2041      * @throws PHPUnit_Framework_IncompleteTestError
2042      * @since  Method available since Release 3.0.0
2043      */
2044     public static function markTestIncomplete($message = '')
2045     {
2046         throw new PHPUnit_Framework_IncompleteTestError($message);
2047     }
2048
2049     /**
2050      * Mark the test as skipped.
2051      *
2052      * @param  string  $message
2053      * @throws PHPUnit_Framework_SkippedTestError
2054      * @since  Method available since Release 3.0.0
2055      */
2056     public static function markTestSkipped($message = '')
2057     {
2058         throw new PHPUnit_Framework_SkippedTestError($message);
2059     }
2060
2061     /**
2062      * Return the current assertion count.
2063      *
2064      * @return integer
2065      * @since  Method available since Release 3.3.3
2066      */
2067     public static function getCount()
2068     {
2069         return self::$count;
2070     }
2071
2072     /**
2073      * Reset the assertion counter.
2074      *
2075      * @since  Method available since Release 3.3.3
2076      */
2077     public static function resetCount()
2078     {
2079         self::$count = 0;
2080     }
2081 }
2082
2083 }
2084 ?>