├── .gitattributes ├── .gitignore ├── CHANGES.txt ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── composer.json ├── generator ├── FactoryCall.php ├── FactoryClass.php ├── FactoryFile.php ├── FactoryGenerator.php ├── FactoryMethod.php ├── FactoryParameter.php ├── GlobalFunctionFile.php ├── StaticMethodFile.php ├── parts │ ├── file_header.txt │ ├── functions_footer.txt │ ├── functions_header.txt │ ├── functions_imports.txt │ ├── matchers_footer.txt │ ├── matchers_header.txt │ └── matchers_imports.txt └── run.php └── hamcrest ├── Hamcrest.php └── Hamcrest ├── Arrays ├── IsArray.php ├── IsArrayContaining.php ├── IsArrayContainingInAnyOrder.php ├── IsArrayContainingInOrder.php ├── IsArrayContainingKey.php ├── IsArrayContainingKeyValuePair.php ├── IsArrayWithSize.php ├── MatchingOnce.php └── SeriesMatchingOnce.php ├── AssertionError.php ├── BaseDescription.php ├── BaseMatcher.php ├── Collection ├── IsEmptyTraversable.php └── IsTraversableWithSize.php ├── Core ├── AllOf.php ├── AnyOf.php ├── CombinableMatcher.php ├── DescribedAs.php ├── Every.php ├── HasToString.php ├── Is.php ├── IsAnything.php ├── IsCollectionContaining.php ├── IsEqual.php ├── IsIdentical.php ├── IsInstanceOf.php ├── IsNot.php ├── IsNull.php ├── IsSame.php ├── IsTypeOf.php ├── Set.php └── ShortcutCombination.php ├── Description.php ├── DiagnosingMatcher.php ├── FeatureMatcher.php ├── Internal └── SelfDescribingValue.php ├── Matcher.php ├── MatcherAssert.php ├── Matchers.php ├── NullDescription.php ├── Number ├── IsCloseTo.php └── OrderingComparison.php ├── SelfDescribing.php ├── StringDescription.php ├── Text ├── IsEmptyString.php ├── IsEqualIgnoringCase.php ├── IsEqualIgnoringWhiteSpace.php ├── MatchesPattern.php ├── StringContains.php ├── StringContainsIgnoringCase.php ├── StringContainsInOrder.php ├── StringEndsWith.php ├── StringStartsWith.php └── SubstringMatcher.php ├── Type ├── IsArray.php ├── IsBoolean.php ├── IsCallable.php ├── IsDouble.php ├── IsInteger.php ├── IsNumeric.php ├── IsObject.php ├── IsResource.php ├── IsScalar.php └── IsString.php ├── TypeSafeDiagnosingMatcher.php ├── TypeSafeMatcher.php ├── Util.php └── Xml └── HasXPath.php /.gitattributes: -------------------------------------------------------------------------------- 1 | /.coveralls.yml export-ignore 2 | /.gush.yml export-ignore 3 | /.travis.yml export-ignore 4 | /.github export-ignore 5 | /tests export-ignore 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | tests/.phpunit.result.cache 3 | vendor 4 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | == Version 2.1.1: Released Apr 30 2025 == 2 | 3 | * Fix implicitly nullable via default value null for PHP 8.4 (#85) 4 | 5 | == Version 2.1.0: Released Apr 29 2025 == 6 | 7 | * Dropped support for PHP <=7.3 8 | 9 | == Version 2.0.1: Released Jul 09 2020 == 10 | 11 | * Added support for PHP 8 12 | 13 | 14 | == Version 2.0: Released Feb 26 2016 == 15 | 16 | * Removed automatic loading of global functions 17 | 18 | 19 | == Version 1.1.0: Released Feb 2 2012 == 20 | 21 | Issues Fixed: 121, 138, 147 22 | 23 | * Added non-empty matchers to complement the emptiness-matching forms. 24 | 25 | - nonEmptyString() 26 | - nonEmptyArray() 27 | - nonEmptyTraversable() 28 | 29 | * Added ability to pass variable arguments to several array-based matcher 30 | factory methods so they work like allOf() et al. 31 | 32 | - anArray() 33 | - arrayContainingInAnyOrder(), containsInAnyOrder() 34 | - arrayContaining(), contains() 35 | - stringContainsInOrder() 36 | 37 | * Matchers that accept an array of matchers now also accept variable arguments. 38 | Any non-matcher arguments are wrapped by IsEqual. 39 | 40 | * Added noneOf() as a shortcut for not(anyOf()). 41 | 42 | 43 | == Version 1.0.0: Released Jan 20 2012 == 44 | 45 | Issues Fixed: 119, 136, 139, 141, 148, 149, 172 46 | 47 | * Moved hamcrest.php into Hamcrest folder and renamed to Hamcrest.php. 48 | This is more in line with PEAR packaging standards. 49 | 50 | * Renamed callable() to callableValue() for compatibility with PHP 5.4. 51 | 52 | * Added Hamcrest_Text_StringContainsIgnoringCase to assert using stripos(). 53 | 54 | assertThat('fOObAr', containsStringIgnoringCase('oba')); 55 | assertThat('fOObAr', containsString('oba')->ignoringCase()); 56 | 57 | * Fixed Hamcrest_Core_IsInstanceOf to return false for native types. 58 | 59 | * Moved string-based matchers to Hamcrest_Text package. 60 | StringContains, StringEndsWith, StringStartsWith, and SubstringMatcher 61 | 62 | * Hamcrest.php and Hamcrest_Matchers.php are now built from @factory doctags. 63 | Added @factory doctag to every static factory method. 64 | 65 | * Hamcrest_Matchers and Hamcrest.php now import each matcher as-needed 66 | and Hamcrest.php calls the matchers directly instead of Hamcrest_Matchers. 67 | 68 | 69 | == Version 0.3.0: Released Jul 26 2010 == 70 | 71 | * Added running count to Hamcrest_MatcherAssert with methods to get and reset it. 72 | This can be used by unit testing frameworks for reporting. 73 | 74 | * Added Hamcrest_Core_HasToString to assert return value of toString() or __toString(). 75 | 76 | assertThat($anObject, hasToString('foo')); 77 | 78 | * Added Hamcrest_Type_IsScalar to assert is_scalar(). 79 | Matches values of type bool, int, float, double, and string. 80 | 81 | assertThat($count, scalarValue()); 82 | assertThat('foo', scalarValue()); 83 | 84 | * Added Hamcrest_Collection package. 85 | 86 | - IsEmptyTraversable 87 | - IsTraversableWithSize 88 | 89 | assertThat($iterator, emptyTraversable()); 90 | assertThat($iterator, traversableWithSize(5)); 91 | 92 | * Added Hamcrest_Xml_HasXPath to assert XPath expressions or the content of nodes in an XML/HTML DOM. 93 | 94 | assertThat($dom, hasXPath('books/book/title')); 95 | assertThat($dom, hasXPath('books/book[contains(title, "Alice")]', 3)); 96 | assertThat($dom, hasXPath('books/book/title', 'Alice in Wonderland')); 97 | assertThat($dom, hasXPath('count(books/book)', greaterThan(10))); 98 | 99 | * Added aliases to match the Java API. 100 | 101 | hasEntry() -> hasKeyValuePair() 102 | hasValue() -> hasItemInArray() 103 | contains() -> arrayContaining() 104 | containsInAnyOrder() -> arrayContainingInAnyOrder() 105 | 106 | * Added optional subtype to Hamcrest_TypeSafeMatcher to enforce object class or resource type. 107 | 108 | * Hamcrest_TypeSafeDiagnosingMatcher now extends Hamcrest_TypeSafeMatcher. 109 | 110 | 111 | == Version 0.2.0: Released Jul 14 2010 == 112 | 113 | Issues Fixed: 109, 111, 114, 115 114 | 115 | * Description::appendValues() and appendValueList() accept Iterator and IteratorAggregate. [111] 116 | BaseDescription::appendValue() handles IteratorAggregate. 117 | 118 | * assertThat() accepts a single boolean parameter and 119 | wraps any non-Matcher third parameter with equalTo(). 120 | 121 | * Removed null return value from assertThat(). [114] 122 | 123 | * Fixed wrong variable name in contains(). [109] 124 | 125 | * Added Hamcrest_Core_IsSet to assert isset(). 126 | 127 | assertThat(array('foo' => 'bar'), set('foo')); 128 | assertThat(array('foo' => 'bar'), notSet('bar')); 129 | 130 | * Added Hamcrest_Core_IsTypeOf to assert built-in types with gettype(). [115] 131 | Types: array, boolean, double, integer, null, object, resource, and string. 132 | Note that gettype() returns "double" for float values. 133 | 134 | assertThat($count, typeOf('integer')); 135 | assertThat(3.14159, typeOf('double')); 136 | assertThat(array('foo', 'bar'), typeOf('array')); 137 | assertThat(new stdClass(), typeOf('object')); 138 | 139 | * Added type-specific matchers in new Hamcrest_Type package. 140 | 141 | - IsArray 142 | - IsBoolean 143 | - IsDouble (includes float values) 144 | - IsInteger 145 | - IsObject 146 | - IsResource 147 | - IsString 148 | 149 | assertThat($count, integerValue()); 150 | assertThat(3.14159, floatValue()); 151 | assertThat('foo', stringValue()); 152 | 153 | * Added Hamcrest_Type_IsNumeric to assert is_numeric(). 154 | Matches values of type int and float/double or strings that are formatted as numbers. 155 | 156 | assertThat(5, numericValue()); 157 | assertThat('-5e+3', numericValue()); 158 | 159 | * Added Hamcrest_Type_IsCallable to assert is_callable(). 160 | 161 | assertThat('preg_match', callable()); 162 | assertThat(array('SomeClass', 'SomeMethod'), callable()); 163 | assertThat(array($object, 'SomeMethod'), callable()); 164 | assertThat($object, callable()); 165 | assertThat(function ($x, $y) { return $x + $y; }, callable()); 166 | 167 | * Added Hamcrest_Text_MatchesPattern for regex matching with preg_match(). 168 | 169 | assertThat('foobar', matchesPattern('/o+b/')); 170 | 171 | * Added aliases: 172 | - atLeast() for greaterThanOrEqualTo() 173 | - atMost() for lessThanOrEqualTo() 174 | 175 | 176 | == Version 0.1.0: Released Jul 7 2010 == 177 | 178 | * Created PEAR package 179 | 180 | * Core matchers 181 | 182 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | hamcrest-php is an open source, community-driven project. If you'd like to contribute, feel free to do this, but remember to follow these few simple rules: 3 | 4 | ## Asking Questions 5 | Feel free to ask any questions and share your experiences in the [Issue tracking system](https://github.com/hamcrest/hamcrest-php/issues/) and help to improve the documentation. 6 | 7 | ## Submitting an issues 8 | - A reproducible example is required for every bug report, otherwise it will most probably be __closed without warning__. 9 | - If you are going to make a big, substantial change, let's discuss it first. 10 | 11 | ## Working with Pull Requests 12 | 1. Create your feature addition or a bug fix branch based on __`master`__ branch in your repository's fork. 13 | 2. Make necessary changes, but __don't mix__ code reformatting with code changes on topic. 14 | 3. Add tests for those changes (please look into `tests/` folder for some examples). This is important so we don't break it in a future version unintentionally. 15 | 4. Check your code using "Coding Standard" (see below). 16 | 5. Commit your code. 17 | 6. Squash your commits by topic to preserve a clean and readable log. 18 | 7. Create Pull Request. 19 | 20 | ## Running the Tests 21 | 22 | ### Installation/Configuration 23 | 24 | 1. Using `git clone https://github.com/hamcrest/hamcrest-php` to clone this repository. 25 | 2. Using the `composer update` to update the dependencies to support your development environment. 26 | 3. Using `vendor/bin/phpunit -c tests/phpunit.xml.dist` command to do unit test works. 27 | 28 | ## Contributor Code of Conduct 29 | 30 | Please note that this project is released with a [Contributor Code of 31 | Conduct](http://contributor-covenant.org/). By participating in this project 32 | you agree to abide by its terms. See [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) file. 33 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | Copyright (c) 2000-2025, www.hamcrest.org 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | Redistributions of source code must retain the above copyright notice, this list of 10 | conditions and the following disclaimer. Redistributions in binary form must reproduce 11 | the above copyright notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution. 13 | 14 | Neither the name of Hamcrest nor the names of its contributors may be used to endorse 15 | or promote products derived from this software without specific prior written 16 | permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 21 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 26 | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27 | DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is the PHP port of Hamcrest Matchers 2 | ========================================= 3 | 4 | [![tests](https://github.com/hamcrest/hamcrest-php/actions/workflows/tests.yml/badge.svg)](https://github.com/hamcrest/hamcrest-php/actions/workflows/tests.yml) 5 | 6 | Hamcrest is a matching library originally written for Java, but 7 | subsequently ported to many other languages. hamcrest-php is the 8 | official PHP port of Hamcrest and essentially follows a literal 9 | translation of the original Java API for Hamcrest, with a few 10 | Exceptions, mostly down to PHP language barriers: 11 | 12 | 1. `instanceOf($theClass)` is actually `anInstanceOf($theClass)` 13 | 14 | 2. `both(containsString('a'))->and(containsString('b'))` 15 | is actually `both(containsString('a'))->andAlso(containsString('b'))` 16 | 17 | 3. `either(containsString('a'))->or(containsString('b'))` 18 | is actually `either(containsString('a'))->orElse(containsString('b'))` 19 | 20 | 4. Unless it would be non-semantic for a matcher to do so, hamcrest-php 21 | allows dynamic typing for it's input, in "the PHP way". Exception are 22 | where semantics surrounding the type itself would suggest otherwise, 23 | such as stringContains() and greaterThan(). 24 | 25 | 5. Several official matchers have not been ported because they don't 26 | make sense or don't apply in PHP: 27 | 28 | - `typeCompatibleWith($theClass)` 29 | - `eventFrom($source)` 30 | - `hasProperty($name)` ** 31 | - `samePropertyValuesAs($obj)` ** 32 | 33 | 6. When most of the collections matchers are finally ported, PHP-specific 34 | aliases will probably be created due to a difference in naming 35 | conventions between Java's Arrays, Collections, Sets and Maps compared 36 | with PHP's Arrays. 37 | 38 | --- 39 | ** [Unless we consider POPO's (Plain Old PHP Objects) akin to JavaBeans] 40 | - The POPO thing is a joke. Java devs coin the term POJO's (Plain Old 41 | Java Objects). 42 | 43 | 44 | Usage 45 | ----- 46 | 47 | Hamcrest matchers are easy to use as: 48 | 49 | ```php 50 | Hamcrest_MatcherAssert::assertThat('a', Hamcrest_Matchers::equalToIgnoringCase('A')); 51 | ``` 52 | 53 | Alternatively, you can use the global proxy-functions: 54 | 55 | ```php 56 | $result = true; 57 | // with an identifier 58 | assertThat("result should be true", $result, equalTo(true)); 59 | 60 | // without an identifier 61 | assertThat($result, equalTo(true)); 62 | 63 | // evaluate a boolean expression 64 | assertThat($result === true); 65 | 66 | // with syntactic sugar is() 67 | assertThat(true, is(true)); 68 | ``` 69 | 70 | :warning: **NOTE:** the global proxy-functions aren't autoloaded by default, so you will need to load them first: 71 | 72 | ```php 73 | \Hamcrest\Util::registerGlobalFunctions(); 74 | ``` 75 | 76 | For brevity, all of the examples below use the proxy-functions. 77 | 78 | 79 | Documentation 80 | ------------- 81 | A tutorial can be found on the [Hamcrest site](https://code.google.com/archive/p/hamcrest/wikis/TutorialPHP.wiki). 82 | 83 | 84 | Available Matchers 85 | ------------------ 86 | * [Array](../master/README.md#array) 87 | * [Collection](../master/README.md#collection) 88 | * [Object](../master/README.md#object) 89 | * [Numbers](../master/README.md#numbers) 90 | * [Type checking](../master/README.md#type-checking) 91 | * [XML](../master/README.md#xml) 92 | 93 | 94 | ### Array 95 | 96 | * `anArray` - evaluates an array 97 | ```php 98 | assertThat([], anArray()); 99 | ``` 100 | 101 | * `hasItemInArray` - check if item exists in array 102 | ```php 103 | $list = range(2, 7, 2); 104 | $item = 4; 105 | assertThat($list, hasItemInArray($item)); 106 | ``` 107 | 108 | * `hasValue` - alias of hasItemInArray 109 | 110 | * `arrayContainingInAnyOrder` - check if array contains elements in any order 111 | ```php 112 | assertThat([2, 4, 6], arrayContainingInAnyOrder([6, 4, 2])); 113 | assertThat([2, 4, 6], arrayContainingInAnyOrder([4, 2, 6])); 114 | ``` 115 | 116 | * `containsInAnyOrder` - alias of arrayContainingInAnyOrder 117 | 118 | * `arrayContaining` - An array with elements that match the given matchers in the same order. 119 | ```php 120 | assertThat([2, 4, 6], arrayContaining([2, 4, 6])); 121 | assertthat([2, 4, 6], not(arrayContaining([6, 4, 2]))); 122 | ``` 123 | 124 | * `contains` - check array in same order 125 | ```php 126 | assertThat([2, 4, 6], contains([2, 4, 6])); 127 | ``` 128 | 129 | * `hasKeyInArray` - check if array has given key 130 | ```php 131 | assertThat(['name'=> 'foobar'], hasKeyInArray('name')); 132 | ``` 133 | 134 | * `hasKey` - alias of hasKeyInArray 135 | 136 | * `hasKeyValuePair` - check if array has given key, value pair 137 | ```php 138 | assertThat(['name'=> 'foobar'], hasKeyValuePair('name', 'foobar')); 139 | ``` 140 | * `hasEntry` - same as hasKeyValuePair 141 | 142 | * `arrayWithSize` - check array has given size 143 | ```php 144 | assertthat([2, 4, 6], arrayWithSize(3)); 145 | ``` 146 | * `emptyArray` - check if array is empty 147 | ```php 148 | assertThat([], emptyArray()); 149 | ``` 150 | 151 | * `nonEmptyArray` 152 | ```php 153 | assertThat([1], nonEmptyArray()); 154 | ``` 155 | 156 | ### Collection 157 | 158 | * `emptyTraversable` - check if traversable is empty 159 | ```php 160 | $empty_it = new EmptyIterator; 161 | assertThat($empty_it, emptyTraversable()); 162 | ``` 163 | 164 | * `nonEmptyTraversable` - check if traversable isn't empty 165 | ```php 166 | $non_empty_it = new ArrayIterator(range(1, 10)); 167 | assertThat($non_empty_it, nonEmptyTraversable()); 168 | a 169 | ``` 170 | 171 | * `traversableWithSize` 172 | ```php 173 | $non_empty_it = new ArrayIterator(range(1, 10)); 174 | assertThat($non_empty_it, traversableWithSize(count(range(1, 10)))); 175 | ` 176 | ``` 177 | 178 | ### Core 179 | 180 | * `allOf` - Evaluates to true only if ALL of the passed in matchers evaluate to true. 181 | ```php 182 | assertThat([2,4,6], allOf(hasValue(2), arrayWithSize(3))); 183 | ``` 184 | 185 | * `anyOf` - Evaluates to true if ANY of the passed in matchers evaluate to true. 186 | ```php 187 | assertThat([2, 4, 6], anyOf(hasValue(8), hasValue(2))); 188 | ``` 189 | 190 | * `noneOf` - Evaluates to false if ANY of the passed in matchers evaluate to true. 191 | ```php 192 | assertThat([2, 4, 6], noneOf(hasValue(1), hasValue(3))); 193 | ``` 194 | 195 | * `both` + `andAlso` - This is useful for fluently combining matchers that must both pass. 196 | ```php 197 | assertThat([2, 4, 6], both(hasValue(2))->andAlso(hasValue(4))); 198 | ``` 199 | 200 | * `either` + `orElse` - This is useful for fluently combining matchers where either may pass, 201 | ```php 202 | assertThat([2, 4, 6], either(hasValue(2))->orElse(hasValue(4))); 203 | ``` 204 | 205 | * `describedAs` - Wraps an existing matcher and overrides the description when it fails. 206 | ```php 207 | $expected = "Dog"; 208 | $found = null; 209 | // this assertion would result error message as Expected: is not null but: was null 210 | //assertThat("Expected {$expected}, got {$found}", $found, is(notNullValue())); 211 | // and this assertion would result error message as Expected: Dog but: was null 212 | //assertThat($found, describedAs($expected, notNullValue())); 213 | ``` 214 | 215 | * `everyItem` - A matcher to apply to every element in an array. 216 | ```php 217 | assertThat([2, 4, 6], everyItem(notNullValue())); 218 | ``` 219 | 220 | * `hasItem` - check array has given item, it can take a matcher argument 221 | ```php 222 | assertThat([2, 4, 6], hasItem(equalTo(2))); 223 | ``` 224 | 225 | * `hasItems` - check array has given items, it can take multiple matcher as arguments 226 | ```php 227 | assertThat([1, 3, 5], hasItems(equalTo(1), equalTo(3))); 228 | ``` 229 | 230 | ### Object 231 | 232 | * `hasToString` - check `__toString` or `toString` method 233 | ```php 234 | class Foo { 235 | public $name = null; 236 | 237 | public function __toString() { 238 | return "[Foo]Instance"; 239 | } 240 | } 241 | $foo = new Foo; 242 | assertThat($foo, hasToString(equalTo("[Foo]Instance"))); 243 | ``` 244 | 245 | * `equalTo` - compares two instances using comparison operator '==' 246 | ```php 247 | $foo = new Foo; 248 | $foo2 = new Foo; 249 | assertThat($foo, equalTo($foo2)); 250 | ``` 251 | 252 | * `identicalTo` - compares two instances using identity operator '===' 253 | ```php 254 | assertThat($foo, is(not(identicalTo($foo2)))); 255 | ``` 256 | 257 | * `anInstanceOf` - check instance is an instance|sub-class of given class 258 | ```php 259 | assertThat($foo, anInstanceOf(Foo::class)); 260 | ``` 261 | 262 | * `any` - alias of `anInstanceOf` 263 | 264 | * `nullValue` check null 265 | ```php 266 | assertThat(null, is(nullValue())); 267 | ``` 268 | 269 | * `notNullValue` check not null 270 | ```php 271 | assertThat("", notNullValue()); 272 | ``` 273 | 274 | * `sameInstance` - check for same instance 275 | ```php 276 | assertThat($foo, is(not(sameInstance($foo2)))); 277 | assertThat($foo, is(sameInstance($foo))); 278 | ``` 279 | 280 | * `typeOf`- check type 281 | ```php 282 | assertThat(1, typeOf("integer")); 283 | ``` 284 | 285 | * `notSet` - check if instance property is not set 286 | ```php 287 | assertThat($foo, notSet("name")); 288 | ``` 289 | 290 | * `set` - check if instance property is set 291 | ```php 292 | $foo->name = "bar"; 293 | assertThat($foo, set("name")); 294 | ``` 295 | 296 | ### Numbers 297 | 298 | * `closeTo` - check value close to a range 299 | ```php 300 | assertThat(3, closeTo(3, 0.5)); 301 | ``` 302 | 303 | * `comparesEqualTo` - check with '==' 304 | ```php 305 | assertThat(2, comparesEqualTo(2)); 306 | ``` 307 | 308 | * `greaterThan` - check '>' 309 | ``` 310 | assertThat(2, greaterThan(1)); 311 | ``` 312 | 313 | * `greaterThanOrEqualTo` 314 | ```php 315 | assertThat(2, greaterThanOrEqualTo(2)); 316 | ``` 317 | 318 | * `atLeast` - The value is >= given value 319 | ```php 320 | assertThat(3, atLeast(2)); 321 | ``` 322 | * `lessThan` 323 | ```php 324 | assertThat(2, lessThan(3)); 325 | ``` 326 | 327 | * `lessThanOrEqualTo` 328 | ```php 329 | assertThat(2, lessThanOrEqualTo(3)); 330 | ``` 331 | 332 | * `atMost` - The value is <= given value 333 | ```php 334 | assertThat(2, atMost(3)); 335 | ``` 336 | 337 | ### String 338 | 339 | * `emptyString` - check for empty string 340 | ```php 341 | assertThat("", emptyString()); 342 | ``` 343 | 344 | * `isEmptyOrNullString` 345 | ```php 346 | assertThat(null, isEmptyOrNullString()); 347 | ``` 348 | 349 | * `nullOrEmptyString` 350 | ```php 351 | assertThat("", nullOrEmptyString()); 352 | ``` 353 | 354 | * `isNonEmptyString` 355 | ```php 356 | assertThat("foo", isNonEmptyString()); 357 | ``` 358 | 359 | * `nonEmptyString` 360 | ```php 361 | assertThat("foo", nonEmptyString()); 362 | ``` 363 | 364 | * `equalToIgnoringCase` 365 | ```php 366 | assertThat("Foo", equalToIgnoringCase("foo")); 367 | ``` 368 | * `equalToIgnoringWhiteSpace` 369 | ```php 370 | assertThat(" Foo ", equalToIgnoringWhiteSpace("Foo")); 371 | ``` 372 | 373 | * `matchesPattern` - matches with regex pattern 374 | ```php 375 | assertThat("foobarbaz", matchesPattern('/(foo)(bar)(baz)/')); 376 | ``` 377 | 378 | * `containsString` - check for substring 379 | ```php 380 | assertThat("foobar", containsString("foo")); 381 | ``` 382 | 383 | * `containsStringIgnoringCase` 384 | ```php 385 | assertThat("fooBar", containsStringIgnoringCase("bar")); 386 | ``` 387 | 388 | * `stringContainsInOrder` 389 | ```php 390 | assertThat("foo", stringContainsInOrder("foo")); 391 | ``` 392 | 393 | * `endsWith` - check string that ends with given value 394 | ```php 395 | assertThat("foo", endsWith("oo")); 396 | ``` 397 | 398 | * `startsWith` - check string that starts with given value 399 | ```php 400 | assertThat("bar", startsWith("ba")); 401 | ``` 402 | 403 | ### Type-checking 404 | 405 | * `arrayValue` - check array type 406 | ```php 407 | assertThat([], arrayValue()); 408 | ``` 409 | 410 | * `booleanValue` 411 | ```php 412 | assertThat(true, booleanValue()); 413 | ``` 414 | * `boolValue` - alias of booleanValue 415 | 416 | * `callableValue` - check if value is callable 417 | ```php 418 | $func = function () {}; 419 | assertThat($func, callableValue()); 420 | ``` 421 | * `doubleValue` 422 | ```php 423 | assertThat(3.14, doubleValue()); 424 | ``` 425 | 426 | * `floatValue` 427 | ```php 428 | assertThat(3.14, floatValue()); 429 | ``` 430 | 431 | * `integerValue` 432 | ```php 433 | assertThat(1, integerValue()); 434 | ``` 435 | 436 | * `intValue` - alias of `integerValue` 437 | 438 | * `numericValue` - check if value is numeric 439 | ```php 440 | assertThat("123", numericValue()); 441 | ``` 442 | 443 | * `objectValue` - check for object 444 | ```php 445 | $obj = new stdClass; 446 | assertThat($obj, objectValue()); 447 | ``` 448 | * `anObject` 449 | ```php 450 | assertThat($obj, anObject()); 451 | ``` 452 | 453 | * `resourceValue` - check resource type 454 | ```php 455 | $fp = fopen("/tmp/foo", "w+"); 456 | assertThat($fp, resourceValue()); 457 | ``` 458 | 459 | * `scalarValue` - check for scalar value 460 | ```php 461 | assertThat(1, scalarValue()); 462 | ``` 463 | 464 | * `stringValue` 465 | ```php 466 | assertThat("", stringValue()); 467 | ``` 468 | 469 | ### XML 470 | 471 | * `hasXPath` - check xml with a xpath 472 | ```php 473 | $xml = << 475 | 476 | 1 477 | 478 | 479 | 2 480 | 481 | 482 | XML; 483 | 484 | $doc = new DOMDocument; 485 | $doc->loadXML($xml); 486 | assertThat($doc, hasXPath("book", 2)); 487 | ``` 488 | 489 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hamcrest/hamcrest-php", 3 | "type": "library", 4 | "description": "This is the PHP port of Hamcrest Matchers", 5 | "keywords": ["test"], 6 | "license": "BSD-3-Clause", 7 | "authors": [ 8 | ], 9 | 10 | "autoload": { 11 | "classmap": ["hamcrest"] 12 | }, 13 | "autoload-dev": { 14 | "classmap": ["tests", "generator"] 15 | }, 16 | 17 | "require": { 18 | "php": "^7.4|^8.0" 19 | }, 20 | 21 | "require-dev": { 22 | "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", 23 | "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" 24 | }, 25 | 26 | "replace": { 27 | "kodova/hamcrest-php": "*", 28 | "davedevelopment/hamcrest-php": "*", 29 | "cordoval/hamcrest-php": "*" 30 | }, 31 | 32 | "extra": { 33 | "branch-alias": { 34 | "dev-master": "2.1-dev" 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /generator/FactoryCall.php: -------------------------------------------------------------------------------- 1 | method = $method; 29 | $this->name = $name; 30 | } 31 | 32 | public function getMethod() 33 | { 34 | return $this->method; 35 | } 36 | 37 | public function getName() 38 | { 39 | return $this->name; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /generator/FactoryClass.php: -------------------------------------------------------------------------------- 1 | file = $file; 27 | $this->reflector = $class; 28 | $this->extractFactoryMethods(); 29 | } 30 | 31 | public function extractFactoryMethods() 32 | { 33 | $this->methods = array(); 34 | foreach ($this->getPublicStaticMethods() as $method) { 35 | if ($method->isFactory()) { 36 | $this->methods[] = $method; 37 | } 38 | } 39 | } 40 | 41 | public function getPublicStaticMethods() 42 | { 43 | $methods = array(); 44 | foreach ($this->reflector->getMethods(ReflectionMethod::IS_STATIC) as $method) { 45 | if ($method->isPublic() && $method->getDeclaringClass() == $this->reflector) { 46 | $methods[] = new FactoryMethod($this, $method); 47 | } 48 | } 49 | return $methods; 50 | } 51 | 52 | public function getFile() 53 | { 54 | return $this->file; 55 | } 56 | 57 | public function getName() 58 | { 59 | return $this->reflector->name; 60 | } 61 | 62 | public function isFactory() 63 | { 64 | return !empty($this->methods); 65 | } 66 | 67 | public function getMethods() 68 | { 69 | return $this->methods; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /generator/FactoryFile.php: -------------------------------------------------------------------------------- 1 | file = $file; 25 | $this->indent = $indent; 26 | } 27 | 28 | abstract public function addCall(FactoryCall $call); 29 | 30 | abstract public function build(); 31 | 32 | public function addFileHeader() 33 | { 34 | $this->code = ''; 35 | $this->addPart('file_header'); 36 | } 37 | 38 | public function addPart($name) 39 | { 40 | $this->addCode($this->readPart($name)); 41 | } 42 | 43 | public function addCode($code) 44 | { 45 | $this->code .= $code; 46 | } 47 | 48 | public function readPart($name) 49 | { 50 | return file_get_contents(__DIR__ . "/parts/$name.txt"); 51 | } 52 | 53 | public function generateFactoryCall(FactoryCall $call) 54 | { 55 | $method = $call->getMethod(); 56 | $code = $method->getComment($this->indent) . "\n"; 57 | $code .= $this->generateDeclaration($call->getName(), $method); 58 | $code .= $this->generateCall($method); 59 | $code .= $this->generateClosing(); 60 | return $code; 61 | } 62 | 63 | public function generateDeclaration($name, FactoryMethod $method) 64 | { 65 | $code = $this->indent . $this->getDeclarationModifiers() 66 | . 'function ' . $name . '(' 67 | . $this->generateDeclarationArguments($method) 68 | . ')' . "\n" . $this->indent . '{' . "\n"; 69 | return $code; 70 | } 71 | 72 | public function getDeclarationModifiers() 73 | { 74 | return ''; 75 | } 76 | 77 | public function generateDeclarationArguments(FactoryMethod $method) 78 | { 79 | if ($method->acceptsVariableArguments()) { 80 | return '/* args... */'; 81 | } else { 82 | return $method->getParameterDeclarations(); 83 | } 84 | } 85 | 86 | public function generateImport(FactoryMethod $method) 87 | { 88 | return $this->indent . self::INDENT . "require_once '" . $method->getClass()->getFile() . "';" . "\n"; 89 | } 90 | 91 | public function generateCall(FactoryMethod $method) 92 | { 93 | $code = ''; 94 | if ($method->acceptsVariableArguments()) { 95 | $code .= $this->indent . self::INDENT . '$args = func_get_args();' . "\n"; 96 | } 97 | 98 | $code .= $this->indent . self::INDENT . 'return '; 99 | if ($method->acceptsVariableArguments()) { 100 | $code .= 'call_user_func_array(array(\'' 101 | . '\\' . $method->getClassName() . '\', \'' 102 | . $method->getName() . '\'), $args);' . "\n"; 103 | } else { 104 | $code .= '\\' . $method->getClassName() . '::' 105 | . $method->getName() . '(' 106 | . $method->getParameterInvocations() . ');' . "\n"; 107 | } 108 | 109 | return $code; 110 | } 111 | 112 | public function generateClosing() 113 | { 114 | return $this->indent . '}' . "\n"; 115 | } 116 | 117 | public function write() 118 | { 119 | file_put_contents($this->file, $this->code); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /generator/FactoryGenerator.php: -------------------------------------------------------------------------------- 1 | path = $path; 30 | $this->factoryFiles = array(); 31 | } 32 | 33 | public function addFactoryFile(FactoryFile $factoryFile) 34 | { 35 | $this->factoryFiles[] = $factoryFile; 36 | } 37 | 38 | public function generate() 39 | { 40 | $classes = $this->getClassesWithFactoryMethods(); 41 | foreach ($classes as $class) { 42 | foreach ($class->getMethods() as $method) { 43 | foreach ($method->getCalls() as $call) { 44 | foreach ($this->factoryFiles as $file) { 45 | $file->addCall($call); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | 52 | public function write() 53 | { 54 | foreach ($this->factoryFiles as $file) { 55 | $file->build(); 56 | $file->write(); 57 | } 58 | } 59 | 60 | public function getClassesWithFactoryMethods() 61 | { 62 | $classes = array(); 63 | $files = $this->getSortedFiles(); 64 | foreach ($files as $file) { 65 | $class = $this->getFactoryClass($file); 66 | if ($class !== null) { 67 | $classes[] = $class; 68 | } 69 | } 70 | 71 | return $classes; 72 | } 73 | 74 | public function getSortedFiles() 75 | { 76 | $iter = $this->getFileIterator(); 77 | $files = array(); 78 | foreach ($iter as $file) { 79 | $files[] = $file; 80 | } 81 | sort($files, SORT_STRING); 82 | 83 | return $files; 84 | } 85 | 86 | private function getFileIterator() 87 | { 88 | $factoryClass = class_exists('File_Iterator_Factory') ? 'File_Iterator_Factory' : 'SebastianBergmann\FileIterator\Factory'; 89 | 90 | $factory = new $factoryClass(); 91 | 92 | return $factory->getFileIterator($this->path, '.php'); 93 | } 94 | 95 | public function getFactoryClass($file) 96 | { 97 | $name = $this->getFactoryClassName($file); 98 | if ($name !== null) { 99 | require_once $file; 100 | 101 | if (class_exists($name)) { 102 | $class = new FactoryClass(substr($file, strpos($file, 'Hamcrest/')), new ReflectionClass($name)); 103 | if ($class->isFactory()) { 104 | return $class; 105 | } 106 | } 107 | } 108 | 109 | return null; 110 | } 111 | 112 | public function getFactoryClassName($file) 113 | { 114 | $content = file_get_contents($file); 115 | if (preg_match('/namespace\s+(.+);/', $content, $namespace) 116 | && preg_match('/\n\s*class\s+(\w+)\s+extends\b/', $content, $className) 117 | && preg_match('/@factory\b/', $content) 118 | ) { 119 | return $namespace[1] . '\\' . $className[1]; 120 | } 121 | 122 | return null; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /generator/FactoryMethod.php: -------------------------------------------------------------------------------- 1 | class = $class; 47 | $this->reflector = $reflector; 48 | $this->extractCommentWithoutLeadingShashesAndStars(); 49 | $this->extractFactoryNamesFromComment(); 50 | $this->extractParameters(); 51 | } 52 | 53 | public function extractCommentWithoutLeadingShashesAndStars() 54 | { 55 | $this->comment = explode("\n", $this->reflector->getDocComment()); 56 | foreach ($this->comment as &$line) { 57 | $line = preg_replace('#^\s*(/\\*+|\\*+/|\\*)\s?#', '', $line); 58 | } 59 | $this->trimLeadingBlankLinesFromComment(); 60 | $this->trimTrailingBlankLinesFromComment(); 61 | } 62 | 63 | public function trimLeadingBlankLinesFromComment() 64 | { 65 | while (count($this->comment) > 0) { 66 | $line = array_shift($this->comment); 67 | if (trim($line) != '') { 68 | array_unshift($this->comment, $line); 69 | break; 70 | } 71 | } 72 | } 73 | 74 | public function trimTrailingBlankLinesFromComment() 75 | { 76 | while (count($this->comment) > 0) { 77 | $line = array_pop($this->comment); 78 | if (trim($line) != '') { 79 | array_push($this->comment, $line); 80 | break; 81 | } 82 | } 83 | } 84 | 85 | public function extractFactoryNamesFromComment() 86 | { 87 | $this->calls = array(); 88 | for ($i = 0; $i < count($this->comment); $i++) { 89 | if ($this->extractFactoryNamesFromLine($this->comment[$i])) { 90 | unset($this->comment[$i]); 91 | } 92 | } 93 | $this->trimTrailingBlankLinesFromComment(); 94 | } 95 | 96 | public function extractFactoryNamesFromLine($line) 97 | { 98 | if (preg_match('/^\s*@factory(\s+(.+))?$/', $line, $match)) { 99 | $this->createCalls( 100 | $this->extractFactoryNamesFromAnnotation( 101 | isset($match[2]) ? trim($match[2]) : null 102 | ) 103 | ); 104 | return true; 105 | } 106 | return false; 107 | } 108 | 109 | public function extractFactoryNamesFromAnnotation($value) 110 | { 111 | $primaryName = $this->reflector->getName(); 112 | if (empty($value)) { 113 | return array($primaryName); 114 | } 115 | preg_match_all('/(\.{3}|-|[a-zA-Z_][a-zA-Z_0-9]*)/', $value, $match); 116 | $names = $match[0]; 117 | if (in_array('...', $names)) { 118 | $this->isVarArgs = true; 119 | } 120 | if (!in_array('-', $names) && !in_array($primaryName, $names)) { 121 | array_unshift($names, $primaryName); 122 | } 123 | return $names; 124 | } 125 | 126 | public function createCalls(array $names) 127 | { 128 | $names = array_unique($names); 129 | foreach ($names as $name) { 130 | if ($name != '-' && $name != '...') { 131 | $this->calls[] = new FactoryCall($this, $name); 132 | } 133 | } 134 | } 135 | 136 | public function extractParameters() 137 | { 138 | $this->parameters = array(); 139 | if (!$this->isVarArgs) { 140 | foreach ($this->reflector->getParameters() as $parameter) { 141 | $this->parameters[] = new FactoryParameter($this, $parameter); 142 | } 143 | } 144 | } 145 | 146 | public function getParameterDeclarations() 147 | { 148 | if ($this->isVarArgs || !$this->hasParameters()) { 149 | return ''; 150 | } 151 | $params = array(); 152 | foreach ($this->parameters as /** @var $parameter FactoryParameter */ 153 | $parameter) { 154 | $params[] = $parameter->getDeclaration(); 155 | } 156 | return implode(', ', $params); 157 | } 158 | 159 | public function getParameterInvocations() 160 | { 161 | if ($this->isVarArgs) { 162 | return ''; 163 | } 164 | $params = array(); 165 | foreach ($this->parameters as $parameter) { 166 | $params[] = $parameter->getInvocation(); 167 | } 168 | return implode(', ', $params); 169 | } 170 | 171 | 172 | public function getClass() 173 | { 174 | return $this->class; 175 | } 176 | 177 | public function getClassName() 178 | { 179 | return $this->class->getName(); 180 | } 181 | 182 | public function getName() 183 | { 184 | return $this->reflector->name; 185 | } 186 | 187 | public function isFactory() 188 | { 189 | return count($this->calls) > 0; 190 | } 191 | 192 | public function getCalls() 193 | { 194 | return $this->calls; 195 | } 196 | 197 | public function acceptsVariableArguments() 198 | { 199 | return $this->isVarArgs; 200 | } 201 | 202 | public function hasParameters() 203 | { 204 | return !empty($this->parameters); 205 | } 206 | 207 | public function getParameters() 208 | { 209 | return $this->parameters; 210 | } 211 | 212 | public function getFullName() 213 | { 214 | return $this->getClassName() . '::' . $this->getName(); 215 | } 216 | 217 | public function getCommentText() 218 | { 219 | return implode("\n", $this->comment); 220 | } 221 | 222 | public function getComment($indent = '') 223 | { 224 | $comment = $indent . '/**'; 225 | foreach ($this->comment as $line) { 226 | $comment .= "\n" . rtrim($indent . ' * ' . $line); 227 | } 228 | $comment .= "\n" . $indent . ' */'; 229 | return $comment; 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /generator/FactoryParameter.php: -------------------------------------------------------------------------------- 1 | method = $method; 22 | $this->reflector = $reflector; 23 | } 24 | 25 | /** 26 | * Compute the declaration code. 27 | * 28 | * @return string 29 | */ 30 | public function getDeclaration() 31 | { 32 | $code = $this->getTypeCode() . $this->getInvocation(); 33 | 34 | if ($this->reflector->isOptional()) { 35 | $default = $this->reflector->getDefaultValue(); 36 | if (is_null($default)) { 37 | $default = 'null'; 38 | } elseif (is_bool($default)) { 39 | $default = $default ? 'true' : 'false'; 40 | } elseif (is_string($default)) { 41 | $default = "'" . $default . "'"; 42 | } elseif (is_numeric($default)) { 43 | $default = strval($default); 44 | } elseif (is_array($default)) { 45 | $default = 'array()'; 46 | } else { 47 | echo 'Warning: unknown default type for ' . $this->getMethod()->getFullName() . "\n"; 48 | var_dump($default); 49 | $default = 'null'; 50 | } 51 | $code .= ' = ' . $default; 52 | } 53 | return $code; 54 | } 55 | 56 | /** 57 | * Compute the type code for the parameter. 58 | * 59 | * @return string 60 | */ 61 | private function getTypeCode() 62 | { 63 | // Handle PHP 5 separately 64 | if (PHP_VERSION_ID < 70000) { 65 | if ($this->reflector->isArray()) { 66 | return 'array'; 67 | } 68 | 69 | $class = $this->reflector->getClass(); 70 | 71 | return $class ? sprintf('\\%s ', $class->getName()) : ''; 72 | } 73 | 74 | if (!$this->reflector->hasType()) { 75 | return ''; 76 | } 77 | 78 | $type = $this->reflector->getType(); 79 | $name = self::getQualifiedName($type); 80 | 81 | // PHP 7.1+ supports nullable types via a leading question mark 82 | return (PHP_VERSION_ID >= 70100 && $type->allowsNull()) ? sprintf('?%s ', $name) : sprintf('%s ', $name); 83 | } 84 | 85 | /** 86 | * Compute qualified name for the given type. 87 | * 88 | * This function knows how to prefix class names with a leading slash and 89 | * also how to handle PHP 8's union types. 90 | * 91 | * @param ReflectionType $type 92 | * 93 | * @return string 94 | */ 95 | private static function getQualifiedName(ReflectionType $type) 96 | { 97 | // PHP 8 union types can be recursively processed 98 | if ($type instanceof ReflectionUnionType) { 99 | return implode('|', array_map(function (ReflectionType $type) { 100 | // The "self::" call within a Closure is fine here because this 101 | // code will only ever be executed on PHP 7.0+ 102 | return self::getQualifiedName($type); 103 | }, $type->getTypes())); 104 | } 105 | 106 | // PHP 7.0 doesn't have named types, but 7.1+ does 107 | $name = $type instanceof ReflectionNamedType ? $type->getName() : (string) $type; 108 | 109 | return $type->isBuiltin() ? $name : sprintf('\\%s', $name); 110 | } 111 | 112 | /** 113 | * Compute the invocation code. 114 | * 115 | * @return string 116 | */ 117 | public function getInvocation() 118 | { 119 | return sprintf('$%s', $this->reflector->getName()); 120 | } 121 | 122 | /** 123 | * Compute the method name. 124 | * 125 | * @return string 126 | */ 127 | public function getMethod() 128 | { 129 | return $this->method; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /generator/GlobalFunctionFile.php: -------------------------------------------------------------------------------- 1 | functions = ''; 18 | } 19 | 20 | public function addCall(FactoryCall $call) 21 | { 22 | $this->functions .= "\n" . $this->generateFactoryCall($call); 23 | } 24 | 25 | public function build() 26 | { 27 | $this->addFileHeader(); 28 | $this->addPart('functions_imports'); 29 | $this->addPart('functions_header'); 30 | $this->addCode($this->functions); 31 | $this->addPart('functions_footer'); 32 | } 33 | 34 | public function generateFactoryCall(FactoryCall $call) 35 | { 36 | $code = "if (!function_exists('{$call->getName()}')) {\n"; 37 | $code.= parent::generateFactoryCall($call); 38 | $code.= "}\n"; 39 | 40 | return $code; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /generator/StaticMethodFile.php: -------------------------------------------------------------------------------- 1 | methods = ''; 18 | } 19 | 20 | public function addCall(FactoryCall $call) 21 | { 22 | $this->methods .= PHP_EOL . $this->generateFactoryCall($call); 23 | } 24 | 25 | public function getDeclarationModifiers() 26 | { 27 | return 'public static '; 28 | } 29 | 30 | public function build() 31 | { 32 | $this->addFileHeader(); 33 | $this->addPart('matchers_imports'); 34 | $this->addPart('matchers_header'); 35 | $this->addCode($this->methods); 36 | $this->addPart('matchers_footer'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /generator/parts/file_header.txt: -------------------------------------------------------------------------------- 1 | 8 | * //With an identifier 9 | * assertThat("assertion identifier", $apple->flavour(), equalTo("tasty")); 10 | * //Without an identifier 11 | * assertThat($apple->flavour(), equalTo("tasty")); 12 | * //Evaluating a boolean expression 13 | * assertThat("some error", $a > $b); 14 | * 15 | */ 16 | function assertThat() 17 | { 18 | $args = func_get_args(); 19 | call_user_func_array( 20 | array('Hamcrest\MatcherAssert', 'assertThat'), 21 | $args 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /generator/parts/functions_imports.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hamcrest/hamcrest-php/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487/generator/parts/functions_imports.txt -------------------------------------------------------------------------------- /generator/parts/matchers_footer.txt: -------------------------------------------------------------------------------- 1 | } 2 | -------------------------------------------------------------------------------- /generator/parts/matchers_header.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * A series of static factories for all hamcrest matchers. 5 | */ 6 | class Matchers 7 | { 8 | -------------------------------------------------------------------------------- /generator/parts/matchers_imports.txt: -------------------------------------------------------------------------------- 1 | 2 | namespace Hamcrest; -------------------------------------------------------------------------------- /generator/run.php: -------------------------------------------------------------------------------- 1 | addFactoryFile(new StaticMethodFile(STATIC_MATCHERS_FILE)); 35 | $generator->addFactoryFile(new GlobalFunctionFile(GLOBAL_FUNCTIONS_FILE)); 36 | $generator->generate(); 37 | $generator->write(); 38 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest.php: -------------------------------------------------------------------------------- 1 | 15 | * //With an identifier 16 | * assertThat("assertion identifier", $apple->flavour(), equalTo("tasty")); 17 | * //Without an identifier 18 | * assertThat($apple->flavour(), equalTo("tasty")); 19 | * //Evaluating a boolean expression 20 | * assertThat("some error", $a > $b); 21 | * 22 | */ 23 | function assertThat() 24 | { 25 | $args = func_get_args(); 26 | call_user_func_array( 27 | array('Hamcrest\MatcherAssert', 'assertThat'), 28 | $args 29 | ); 30 | } 31 | } 32 | 33 | if (!function_exists('anArray')) { 34 | /** 35 | * Evaluates to true only if each $matcher[$i] is satisfied by $array[$i]. 36 | */ 37 | function anArray(/* args... */) 38 | { 39 | $args = func_get_args(); 40 | return call_user_func_array(array('\Hamcrest\Arrays\IsArray', 'anArray'), $args); 41 | } 42 | } 43 | 44 | if (!function_exists('hasItemInArray')) { 45 | /** 46 | * Evaluates to true if any item in an array satisfies the given matcher. 47 | * 48 | * @param mixed $item as a {@link Hamcrest\Matcher} or a value. 49 | * 50 | * @return \Hamcrest\Arrays\IsArrayContaining 51 | */ 52 | function hasItemInArray($item) 53 | { 54 | return \Hamcrest\Arrays\IsArrayContaining::hasItemInArray($item); 55 | } 56 | } 57 | 58 | if (!function_exists('hasValue')) { 59 | /** 60 | * Evaluates to true if any item in an array satisfies the given matcher. 61 | * 62 | * @param mixed $item as a {@link Hamcrest\Matcher} or a value. 63 | * 64 | * @return \Hamcrest\Arrays\IsArrayContaining 65 | */ 66 | function hasValue($item) 67 | { 68 | return \Hamcrest\Arrays\IsArrayContaining::hasItemInArray($item); 69 | } 70 | } 71 | 72 | if (!function_exists('arrayContainingInAnyOrder')) { 73 | /** 74 | * An array with elements that match the given matchers. 75 | */ 76 | function arrayContainingInAnyOrder(/* args... */) 77 | { 78 | $args = func_get_args(); 79 | return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInAnyOrder', 'arrayContainingInAnyOrder'), $args); 80 | } 81 | } 82 | 83 | if (!function_exists('containsInAnyOrder')) { 84 | /** 85 | * An array with elements that match the given matchers. 86 | */ 87 | function containsInAnyOrder(/* args... */) 88 | { 89 | $args = func_get_args(); 90 | return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInAnyOrder', 'arrayContainingInAnyOrder'), $args); 91 | } 92 | } 93 | 94 | if (!function_exists('arrayContaining')) { 95 | /** 96 | * An array with elements that match the given matchers in the same order. 97 | */ 98 | function arrayContaining(/* args... */) 99 | { 100 | $args = func_get_args(); 101 | return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInOrder', 'arrayContaining'), $args); 102 | } 103 | } 104 | 105 | if (!function_exists('contains')) { 106 | /** 107 | * An array with elements that match the given matchers in the same order. 108 | */ 109 | function contains(/* args... */) 110 | { 111 | $args = func_get_args(); 112 | return call_user_func_array(array('\Hamcrest\Arrays\IsArrayContainingInOrder', 'arrayContaining'), $args); 113 | } 114 | } 115 | 116 | if (!function_exists('hasKeyInArray')) { 117 | /** 118 | * Evaluates to true if any key in an array matches the given matcher. 119 | * 120 | * @param mixed $key as a {@link Hamcrest\Matcher} or a value. 121 | * 122 | * @return \Hamcrest\Arrays\IsArrayContainingKey 123 | */ 124 | function hasKeyInArray($key) 125 | { 126 | return \Hamcrest\Arrays\IsArrayContainingKey::hasKeyInArray($key); 127 | } 128 | } 129 | 130 | if (!function_exists('hasKey')) { 131 | /** 132 | * Evaluates to true if any key in an array matches the given matcher. 133 | * 134 | * @param mixed $key as a {@link Hamcrest\Matcher} or a value. 135 | * 136 | * @return \Hamcrest\Arrays\IsArrayContainingKey 137 | */ 138 | function hasKey($key) 139 | { 140 | return \Hamcrest\Arrays\IsArrayContainingKey::hasKeyInArray($key); 141 | } 142 | } 143 | 144 | if (!function_exists('hasKeyValuePair')) { 145 | /** 146 | * Test if an array has both an key and value in parity with each other. 147 | */ 148 | function hasKeyValuePair($key, $value) 149 | { 150 | return \Hamcrest\Arrays\IsArrayContainingKeyValuePair::hasKeyValuePair($key, $value); 151 | } 152 | } 153 | 154 | if (!function_exists('hasEntry')) { 155 | /** 156 | * Test if an array has both an key and value in parity with each other. 157 | */ 158 | function hasEntry($key, $value) 159 | { 160 | return \Hamcrest\Arrays\IsArrayContainingKeyValuePair::hasKeyValuePair($key, $value); 161 | } 162 | } 163 | 164 | if (!function_exists('arrayWithSize')) { 165 | /** 166 | * Does array size satisfy a given matcher? 167 | * 168 | * @param \Hamcrest\Matcher|int $size as a {@link Hamcrest\Matcher} or a value. 169 | * 170 | * @return \Hamcrest\Arrays\IsArrayWithSize 171 | */ 172 | function arrayWithSize($size) 173 | { 174 | return \Hamcrest\Arrays\IsArrayWithSize::arrayWithSize($size); 175 | } 176 | } 177 | 178 | if (!function_exists('emptyArray')) { 179 | /** 180 | * Matches an empty array. 181 | */ 182 | function emptyArray() 183 | { 184 | return \Hamcrest\Arrays\IsArrayWithSize::emptyArray(); 185 | } 186 | } 187 | 188 | if (!function_exists('nonEmptyArray')) { 189 | /** 190 | * Matches an empty array. 191 | */ 192 | function nonEmptyArray() 193 | { 194 | return \Hamcrest\Arrays\IsArrayWithSize::nonEmptyArray(); 195 | } 196 | } 197 | 198 | if (!function_exists('emptyTraversable')) { 199 | /** 200 | * Returns true if traversable is empty. 201 | */ 202 | function emptyTraversable() 203 | { 204 | return \Hamcrest\Collection\IsEmptyTraversable::emptyTraversable(); 205 | } 206 | } 207 | 208 | if (!function_exists('nonEmptyTraversable')) { 209 | /** 210 | * Returns true if traversable is not empty. 211 | */ 212 | function nonEmptyTraversable() 213 | { 214 | return \Hamcrest\Collection\IsEmptyTraversable::nonEmptyTraversable(); 215 | } 216 | } 217 | 218 | if (!function_exists('traversableWithSize')) { 219 | /** 220 | * Does traversable size satisfy a given matcher? 221 | */ 222 | function traversableWithSize($size) 223 | { 224 | return \Hamcrest\Collection\IsTraversableWithSize::traversableWithSize($size); 225 | } 226 | } 227 | 228 | if (!function_exists('allOf')) { 229 | /** 230 | * Evaluates to true only if ALL of the passed in matchers evaluate to true. 231 | */ 232 | function allOf(/* args... */) 233 | { 234 | $args = func_get_args(); 235 | return call_user_func_array(array('\Hamcrest\Core\AllOf', 'allOf'), $args); 236 | } 237 | } 238 | 239 | if (!function_exists('anyOf')) { 240 | /** 241 | * Evaluates to true if ANY of the passed in matchers evaluate to true. 242 | */ 243 | function anyOf(/* args... */) 244 | { 245 | $args = func_get_args(); 246 | return call_user_func_array(array('\Hamcrest\Core\AnyOf', 'anyOf'), $args); 247 | } 248 | } 249 | 250 | if (!function_exists('noneOf')) { 251 | /** 252 | * Evaluates to false if ANY of the passed in matchers evaluate to true. 253 | */ 254 | function noneOf(/* args... */) 255 | { 256 | $args = func_get_args(); 257 | return call_user_func_array(array('\Hamcrest\Core\AnyOf', 'noneOf'), $args); 258 | } 259 | } 260 | 261 | if (!function_exists('both')) { 262 | /** 263 | * This is useful for fluently combining matchers that must both pass. 264 | * For example: 265 | *
266 |      *   assertThat($string, both(containsString("a"))->andAlso(containsString("b")));
267 |      * 
268 | */ 269 | function both(\Hamcrest\Matcher $matcher) 270 | { 271 | return \Hamcrest\Core\CombinableMatcher::both($matcher); 272 | } 273 | } 274 | 275 | if (!function_exists('either')) { 276 | /** 277 | * This is useful for fluently combining matchers where either may pass, 278 | * for example: 279 | *
280 |      *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
281 |      * 
282 | */ 283 | function either(\Hamcrest\Matcher $matcher) 284 | { 285 | return \Hamcrest\Core\CombinableMatcher::either($matcher); 286 | } 287 | } 288 | 289 | if (!function_exists('describedAs')) { 290 | /** 291 | * Wraps an existing matcher and overrides the description when it fails. 292 | */ 293 | function describedAs(/* args... */) 294 | { 295 | $args = func_get_args(); 296 | return call_user_func_array(array('\Hamcrest\Core\DescribedAs', 'describedAs'), $args); 297 | } 298 | } 299 | 300 | if (!function_exists('everyItem')) { 301 | /** 302 | * @param Matcher $itemMatcher 303 | * A matcher to apply to every element in an array. 304 | * 305 | * @return \Hamcrest\Core\Every 306 | * Evaluates to TRUE for a collection in which every item matches $itemMatcher 307 | */ 308 | function everyItem(\Hamcrest\Matcher $itemMatcher) 309 | { 310 | return \Hamcrest\Core\Every::everyItem($itemMatcher); 311 | } 312 | } 313 | 314 | if (!function_exists('hasToString')) { 315 | /** 316 | * Does array size satisfy a given matcher? 317 | */ 318 | function hasToString($matcher) 319 | { 320 | return \Hamcrest\Core\HasToString::hasToString($matcher); 321 | } 322 | } 323 | 324 | if (!function_exists('is')) { 325 | /** 326 | * Decorates another Matcher, retaining the behavior but allowing tests 327 | * to be slightly more expressive. 328 | * 329 | * For example: assertThat($cheese, equalTo($smelly)) 330 | * vs. assertThat($cheese, is(equalTo($smelly))) 331 | */ 332 | function is($value) 333 | { 334 | return \Hamcrest\Core\Is::is($value); 335 | } 336 | } 337 | 338 | if (!function_exists('anything')) { 339 | /** 340 | * This matcher always evaluates to true. 341 | * 342 | * @param string $description A meaningful string used when describing itself. 343 | * 344 | * @return \Hamcrest\Core\IsAnything 345 | */ 346 | function anything($description = 'ANYTHING') 347 | { 348 | return \Hamcrest\Core\IsAnything::anything($description); 349 | } 350 | } 351 | 352 | if (!function_exists('hasItem')) { 353 | /** 354 | * Test if the value is an array containing this matcher. 355 | * 356 | * Example: 357 | *
358 |      * assertThat(array('a', 'b'), hasItem(equalTo('b')));
359 |      * //Convenience defaults to equalTo()
360 |      * assertThat(array('a', 'b'), hasItem('b'));
361 |      * 
362 | */ 363 | function hasItem(/* args... */) 364 | { 365 | $args = func_get_args(); 366 | return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItem'), $args); 367 | } 368 | } 369 | 370 | if (!function_exists('hasItems')) { 371 | /** 372 | * Test if the value is an array containing elements that match all of these 373 | * matchers. 374 | * 375 | * Example: 376 | *
377 |      * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
378 |      * 
379 | */ 380 | function hasItems(/* args... */) 381 | { 382 | $args = func_get_args(); 383 | return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItems'), $args); 384 | } 385 | } 386 | 387 | if (!function_exists('equalTo')) { 388 | /** 389 | * Is the value equal to another value, as tested by the use of the "==" 390 | * comparison operator? 391 | */ 392 | function equalTo($item) 393 | { 394 | return \Hamcrest\Core\IsEqual::equalTo($item); 395 | } 396 | } 397 | 398 | if (!function_exists('identicalTo')) { 399 | /** 400 | * Tests of the value is identical to $value as tested by the "===" operator. 401 | */ 402 | function identicalTo($value) 403 | { 404 | return \Hamcrest\Core\IsIdentical::identicalTo($value); 405 | } 406 | } 407 | 408 | if (!function_exists('anInstanceOf')) { 409 | /** 410 | * Is the value an instance of a particular type? 411 | * This version assumes no relationship between the required type and 412 | * the signature of the method that sets it up, for example in 413 | * assertThat($anObject, anInstanceOf('Thing')); 414 | */ 415 | function anInstanceOf($theClass) 416 | { 417 | return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); 418 | } 419 | } 420 | 421 | if (!function_exists('any')) { 422 | /** 423 | * Is the value an instance of a particular type? 424 | * This version assumes no relationship between the required type and 425 | * the signature of the method that sets it up, for example in 426 | * assertThat($anObject, anInstanceOf('Thing')); 427 | */ 428 | function any($theClass) 429 | { 430 | return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); 431 | } 432 | } 433 | 434 | if (!function_exists('not')) { 435 | /** 436 | * Matches if value does not match $value. 437 | */ 438 | function not($value) 439 | { 440 | return \Hamcrest\Core\IsNot::not($value); 441 | } 442 | } 443 | 444 | if (!function_exists('nullValue')) { 445 | /** 446 | * Matches if value is null. 447 | */ 448 | function nullValue() 449 | { 450 | return \Hamcrest\Core\IsNull::nullValue(); 451 | } 452 | } 453 | 454 | if (!function_exists('notNullValue')) { 455 | /** 456 | * Matches if value is not null. 457 | */ 458 | function notNullValue() 459 | { 460 | return \Hamcrest\Core\IsNull::notNullValue(); 461 | } 462 | } 463 | 464 | if (!function_exists('sameInstance')) { 465 | /** 466 | * Creates a new instance of IsSame. 467 | * 468 | * @param mixed $object 469 | * The predicate evaluates to true only when the argument is 470 | * this object. 471 | * 472 | * @return \Hamcrest\Core\IsSame 473 | */ 474 | function sameInstance($object) 475 | { 476 | return \Hamcrest\Core\IsSame::sameInstance($object); 477 | } 478 | } 479 | 480 | if (!function_exists('typeOf')) { 481 | /** 482 | * Is the value a particular built-in type? 483 | */ 484 | function typeOf($theType) 485 | { 486 | return \Hamcrest\Core\IsTypeOf::typeOf($theType); 487 | } 488 | } 489 | 490 | if (!function_exists('set')) { 491 | /** 492 | * Matches if value (class, object, or array) has named $property. 493 | */ 494 | function set($property) 495 | { 496 | return \Hamcrest\Core\Set::set($property); 497 | } 498 | } 499 | 500 | if (!function_exists('notSet')) { 501 | /** 502 | * Matches if value (class, object, or array) does not have named $property. 503 | */ 504 | function notSet($property) 505 | { 506 | return \Hamcrest\Core\Set::notSet($property); 507 | } 508 | } 509 | 510 | if (!function_exists('closeTo')) { 511 | /** 512 | * Matches if value is a number equal to $value within some range of 513 | * acceptable error $delta. 514 | */ 515 | function closeTo($value, $delta) 516 | { 517 | return \Hamcrest\Number\IsCloseTo::closeTo($value, $delta); 518 | } 519 | } 520 | 521 | if (!function_exists('comparesEqualTo')) { 522 | /** 523 | * The value is not > $value, nor < $value. 524 | */ 525 | function comparesEqualTo($value) 526 | { 527 | return \Hamcrest\Number\OrderingComparison::comparesEqualTo($value); 528 | } 529 | } 530 | 531 | if (!function_exists('greaterThan')) { 532 | /** 533 | * The value is > $value. 534 | */ 535 | function greaterThan($value) 536 | { 537 | return \Hamcrest\Number\OrderingComparison::greaterThan($value); 538 | } 539 | } 540 | 541 | if (!function_exists('greaterThanOrEqualTo')) { 542 | /** 543 | * The value is >= $value. 544 | */ 545 | function greaterThanOrEqualTo($value) 546 | { 547 | return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); 548 | } 549 | } 550 | 551 | if (!function_exists('atLeast')) { 552 | /** 553 | * The value is >= $value. 554 | */ 555 | function atLeast($value) 556 | { 557 | return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); 558 | } 559 | } 560 | 561 | if (!function_exists('lessThan')) { 562 | /** 563 | * The value is < $value. 564 | */ 565 | function lessThan($value) 566 | { 567 | return \Hamcrest\Number\OrderingComparison::lessThan($value); 568 | } 569 | } 570 | 571 | if (!function_exists('lessThanOrEqualTo')) { 572 | /** 573 | * The value is <= $value. 574 | */ 575 | function lessThanOrEqualTo($value) 576 | { 577 | return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); 578 | } 579 | } 580 | 581 | if (!function_exists('atMost')) { 582 | /** 583 | * The value is <= $value. 584 | */ 585 | function atMost($value) 586 | { 587 | return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); 588 | } 589 | } 590 | 591 | if (!function_exists('isEmptyString')) { 592 | /** 593 | * Matches if value is a zero-length string. 594 | */ 595 | function isEmptyString() 596 | { 597 | return \Hamcrest\Text\IsEmptyString::isEmptyString(); 598 | } 599 | } 600 | 601 | if (!function_exists('emptyString')) { 602 | /** 603 | * Matches if value is a zero-length string. 604 | */ 605 | function emptyString() 606 | { 607 | return \Hamcrest\Text\IsEmptyString::isEmptyString(); 608 | } 609 | } 610 | 611 | if (!function_exists('isEmptyOrNullString')) { 612 | /** 613 | * Matches if value is null or a zero-length string. 614 | */ 615 | function isEmptyOrNullString() 616 | { 617 | return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); 618 | } 619 | } 620 | 621 | if (!function_exists('nullOrEmptyString')) { 622 | /** 623 | * Matches if value is null or a zero-length string. 624 | */ 625 | function nullOrEmptyString() 626 | { 627 | return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); 628 | } 629 | } 630 | 631 | if (!function_exists('isNonEmptyString')) { 632 | /** 633 | * Matches if value is a non-zero-length string. 634 | */ 635 | function isNonEmptyString() 636 | { 637 | return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); 638 | } 639 | } 640 | 641 | if (!function_exists('nonEmptyString')) { 642 | /** 643 | * Matches if value is a non-zero-length string. 644 | */ 645 | function nonEmptyString() 646 | { 647 | return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); 648 | } 649 | } 650 | 651 | if (!function_exists('equalToIgnoringCase')) { 652 | /** 653 | * Matches if value is a string equal to $string, regardless of the case. 654 | */ 655 | function equalToIgnoringCase($string) 656 | { 657 | return \Hamcrest\Text\IsEqualIgnoringCase::equalToIgnoringCase($string); 658 | } 659 | } 660 | 661 | if (!function_exists('equalToIgnoringWhiteSpace')) { 662 | /** 663 | * Matches if value is a string equal to $string, regardless of whitespace. 664 | */ 665 | function equalToIgnoringWhiteSpace($string) 666 | { 667 | return \Hamcrest\Text\IsEqualIgnoringWhiteSpace::equalToIgnoringWhiteSpace($string); 668 | } 669 | } 670 | 671 | if (!function_exists('matchesPattern')) { 672 | /** 673 | * Matches if value is a string that matches regular expression $pattern. 674 | */ 675 | function matchesPattern($pattern) 676 | { 677 | return \Hamcrest\Text\MatchesPattern::matchesPattern($pattern); 678 | } 679 | } 680 | 681 | if (!function_exists('containsString')) { 682 | /** 683 | * Matches if value is a string that contains $substring. 684 | */ 685 | function containsString($substring) 686 | { 687 | return \Hamcrest\Text\StringContains::containsString($substring); 688 | } 689 | } 690 | 691 | if (!function_exists('containsStringIgnoringCase')) { 692 | /** 693 | * Matches if value is a string that contains $substring regardless of the case. 694 | */ 695 | function containsStringIgnoringCase($substring) 696 | { 697 | return \Hamcrest\Text\StringContainsIgnoringCase::containsStringIgnoringCase($substring); 698 | } 699 | } 700 | 701 | if (!function_exists('stringContainsInOrder')) { 702 | /** 703 | * Matches if value contains $substrings in a constrained order. 704 | */ 705 | function stringContainsInOrder(/* args... */) 706 | { 707 | $args = func_get_args(); 708 | return call_user_func_array(array('\Hamcrest\Text\StringContainsInOrder', 'stringContainsInOrder'), $args); 709 | } 710 | } 711 | 712 | if (!function_exists('endsWith')) { 713 | /** 714 | * Matches if value is a string that ends with $substring. 715 | */ 716 | function endsWith($substring) 717 | { 718 | return \Hamcrest\Text\StringEndsWith::endsWith($substring); 719 | } 720 | } 721 | 722 | if (!function_exists('startsWith')) { 723 | /** 724 | * Matches if value is a string that starts with $substring. 725 | */ 726 | function startsWith($substring) 727 | { 728 | return \Hamcrest\Text\StringStartsWith::startsWith($substring); 729 | } 730 | } 731 | 732 | if (!function_exists('arrayValue')) { 733 | /** 734 | * Is the value an array? 735 | */ 736 | function arrayValue() 737 | { 738 | return \Hamcrest\Type\IsArray::arrayValue(); 739 | } 740 | } 741 | 742 | if (!function_exists('booleanValue')) { 743 | /** 744 | * Is the value a boolean? 745 | */ 746 | function booleanValue() 747 | { 748 | return \Hamcrest\Type\IsBoolean::booleanValue(); 749 | } 750 | } 751 | 752 | if (!function_exists('boolValue')) { 753 | /** 754 | * Is the value a boolean? 755 | */ 756 | function boolValue() 757 | { 758 | return \Hamcrest\Type\IsBoolean::booleanValue(); 759 | } 760 | } 761 | 762 | if (!function_exists('callableValue')) { 763 | /** 764 | * Is the value callable? 765 | */ 766 | function callableValue() 767 | { 768 | return \Hamcrest\Type\IsCallable::callableValue(); 769 | } 770 | } 771 | 772 | if (!function_exists('doubleValue')) { 773 | /** 774 | * Is the value a float/double? 775 | */ 776 | function doubleValue() 777 | { 778 | return \Hamcrest\Type\IsDouble::doubleValue(); 779 | } 780 | } 781 | 782 | if (!function_exists('floatValue')) { 783 | /** 784 | * Is the value a float/double? 785 | */ 786 | function floatValue() 787 | { 788 | return \Hamcrest\Type\IsDouble::doubleValue(); 789 | } 790 | } 791 | 792 | if (!function_exists('integerValue')) { 793 | /** 794 | * Is the value an integer? 795 | */ 796 | function integerValue() 797 | { 798 | return \Hamcrest\Type\IsInteger::integerValue(); 799 | } 800 | } 801 | 802 | if (!function_exists('intValue')) { 803 | /** 804 | * Is the value an integer? 805 | */ 806 | function intValue() 807 | { 808 | return \Hamcrest\Type\IsInteger::integerValue(); 809 | } 810 | } 811 | 812 | if (!function_exists('numericValue')) { 813 | /** 814 | * Is the value a numeric? 815 | */ 816 | function numericValue() 817 | { 818 | return \Hamcrest\Type\IsNumeric::numericValue(); 819 | } 820 | } 821 | 822 | if (!function_exists('objectValue')) { 823 | /** 824 | * Is the value an object? 825 | */ 826 | function objectValue() 827 | { 828 | return \Hamcrest\Type\IsObject::objectValue(); 829 | } 830 | } 831 | 832 | if (!function_exists('anObject')) { 833 | /** 834 | * Is the value an object? 835 | */ 836 | function anObject() 837 | { 838 | return \Hamcrest\Type\IsObject::objectValue(); 839 | } 840 | } 841 | 842 | if (!function_exists('resourceValue')) { 843 | /** 844 | * Is the value a resource? 845 | */ 846 | function resourceValue() 847 | { 848 | return \Hamcrest\Type\IsResource::resourceValue(); 849 | } 850 | } 851 | 852 | if (!function_exists('scalarValue')) { 853 | /** 854 | * Is the value a scalar (boolean, integer, double, or string)? 855 | */ 856 | function scalarValue() 857 | { 858 | return \Hamcrest\Type\IsScalar::scalarValue(); 859 | } 860 | } 861 | 862 | if (!function_exists('stringValue')) { 863 | /** 864 | * Is the value a string? 865 | */ 866 | function stringValue() 867 | { 868 | return \Hamcrest\Type\IsString::stringValue(); 869 | } 870 | } 871 | 872 | if (!function_exists('hasXPath')) { 873 | /** 874 | * Wraps $matcher with {@link Hamcrest\Core\IsEqual) 875 | * if it's not a matcher and the XPath in count() 876 | * if it's an integer. 877 | */ 878 | function hasXPath($xpath, $matcher = null) 879 | { 880 | return \Hamcrest\Xml\HasXPath::hasXPath($xpath, $matcher); 881 | } 882 | } 883 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Arrays/IsArray.php: -------------------------------------------------------------------------------- 1 | _elementMatchers = $elementMatchers; 32 | } 33 | 34 | protected function matchesSafely($array) 35 | { 36 | if (array_keys($array) != array_keys($this->_elementMatchers)) { 37 | return false; 38 | } 39 | 40 | /** @var $matcher \Hamcrest\Matcher */ 41 | foreach ($this->_elementMatchers as $k => $matcher) { 42 | if (!$matcher->matches($array[$k])) { 43 | return false; 44 | } 45 | } 46 | 47 | return true; 48 | } 49 | 50 | protected function describeMismatchSafely($actual, Description $mismatchDescription) 51 | { 52 | if (count($actual) != count($this->_elementMatchers)) { 53 | $mismatchDescription->appendText('array length was ' . count($actual)); 54 | 55 | return; 56 | } elseif (array_keys($actual) != array_keys($this->_elementMatchers)) { 57 | $mismatchDescription->appendText('array keys were ') 58 | ->appendValueList( 59 | $this->descriptionStart(), 60 | $this->descriptionSeparator(), 61 | $this->descriptionEnd(), 62 | array_keys($actual) 63 | ) 64 | ; 65 | 66 | return; 67 | } 68 | 69 | /** @var $matcher \Hamcrest\Matcher */ 70 | foreach ($this->_elementMatchers as $k => $matcher) { 71 | if (!$matcher->matches($actual[$k])) { 72 | $mismatchDescription->appendText('element ')->appendValue($k) 73 | ->appendText(' was ')->appendValue($actual[$k]); 74 | 75 | return; 76 | } 77 | } 78 | } 79 | 80 | public function describeTo(Description $description) 81 | { 82 | $description->appendList( 83 | $this->descriptionStart(), 84 | $this->descriptionSeparator(), 85 | $this->descriptionEnd(), 86 | $this->_elementMatchers 87 | ); 88 | } 89 | 90 | /** 91 | * Evaluates to true only if each $matcher[$i] is satisfied by $array[$i]. 92 | * 93 | * @factory ... 94 | */ 95 | public static function anArray(/* args... */) 96 | { 97 | $args = func_get_args(); 98 | 99 | return new self(Util::createMatcherArray($args)); 100 | } 101 | 102 | // -- Protected Methods 103 | 104 | protected function descriptionStart() 105 | { 106 | return '['; 107 | } 108 | 109 | protected function descriptionSeparator() 110 | { 111 | return ', '; 112 | } 113 | 114 | protected function descriptionEnd() 115 | { 116 | return ']'; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Arrays/IsArrayContaining.php: -------------------------------------------------------------------------------- 1 | _elementMatcher = $elementMatcher; 25 | } 26 | 27 | protected function matchesSafely($array) 28 | { 29 | foreach ($array as $element) { 30 | if ($this->_elementMatcher->matches($element)) { 31 | return true; 32 | } 33 | } 34 | 35 | return false; 36 | } 37 | 38 | protected function describeMismatchSafely($array, Description $mismatchDescription) 39 | { 40 | $mismatchDescription->appendText('was ')->appendValue($array); 41 | } 42 | 43 | public function describeTo(Description $description) 44 | { 45 | $description 46 | ->appendText('an array containing ') 47 | ->appendDescriptionOf($this->_elementMatcher) 48 | ; 49 | } 50 | 51 | /** 52 | * Evaluates to true if any item in an array satisfies the given matcher. 53 | * 54 | * @param mixed $item as a {@link Hamcrest\Matcher} or a value. 55 | * 56 | * @return \Hamcrest\Arrays\IsArrayContaining 57 | * @factory hasValue 58 | */ 59 | public static function hasItemInArray($item) 60 | { 61 | return new self(Util::wrapValueWithIsEqual($item)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Arrays/IsArrayContainingInAnyOrder.php: -------------------------------------------------------------------------------- 1 | _elementMatchers = $elementMatchers; 26 | } 27 | 28 | protected function matchesSafelyWithDiagnosticDescription($array, Description $mismatchDescription) 29 | { 30 | $matching = new MatchingOnce($this->_elementMatchers, $mismatchDescription); 31 | 32 | foreach ($array as $element) { 33 | if (!$matching->matches($element)) { 34 | return false; 35 | } 36 | } 37 | 38 | return $matching->isFinished($array); 39 | } 40 | 41 | public function describeTo(Description $description) 42 | { 43 | $description->appendList('[', ', ', ']', $this->_elementMatchers) 44 | ->appendText(' in any order') 45 | ; 46 | } 47 | 48 | /** 49 | * An array with elements that match the given matchers. 50 | * 51 | * @factory containsInAnyOrder ... 52 | */ 53 | public static function arrayContainingInAnyOrder(/* args... */) 54 | { 55 | $args = func_get_args(); 56 | 57 | return new self(Util::createMatcherArray($args)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Arrays/IsArrayContainingInOrder.php: -------------------------------------------------------------------------------- 1 | _elementMatchers = $elementMatchers; 26 | } 27 | 28 | protected function matchesSafelyWithDiagnosticDescription($array, Description $mismatchDescription) 29 | { 30 | $series = new SeriesMatchingOnce($this->_elementMatchers, $mismatchDescription); 31 | 32 | foreach ($array as $element) { 33 | if (!$series->matches($element)) { 34 | return false; 35 | } 36 | } 37 | 38 | return $series->isFinished(); 39 | } 40 | 41 | public function describeTo(Description $description) 42 | { 43 | $description->appendList('[', ', ', ']', $this->_elementMatchers); 44 | } 45 | 46 | /** 47 | * An array with elements that match the given matchers in the same order. 48 | * 49 | * @factory contains ... 50 | */ 51 | public static function arrayContaining(/* args... */) 52 | { 53 | $args = func_get_args(); 54 | 55 | return new self(Util::createMatcherArray($args)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Arrays/IsArrayContainingKey.php: -------------------------------------------------------------------------------- 1 | _keyMatcher = $keyMatcher; 25 | } 26 | 27 | protected function matchesSafely($array) 28 | { 29 | foreach ($array as $key => $element) { 30 | if ($this->_keyMatcher->matches($key)) { 31 | return true; 32 | } 33 | } 34 | 35 | return false; 36 | } 37 | 38 | protected function describeMismatchSafely($array, Description $mismatchDescription) 39 | { 40 | //Not using appendValueList() so that keys can be shown 41 | $mismatchDescription->appendText('array was ') 42 | ->appendText('[') 43 | ; 44 | $loop = false; 45 | foreach ($array as $key => $value) { 46 | if ($loop) { 47 | $mismatchDescription->appendText(', '); 48 | } 49 | $mismatchDescription->appendValue($key)->appendText(' => ')->appendValue($value); 50 | $loop = true; 51 | } 52 | $mismatchDescription->appendText(']'); 53 | } 54 | 55 | public function describeTo(Description $description) 56 | { 57 | $description 58 | ->appendText('array with key ') 59 | ->appendDescriptionOf($this->_keyMatcher) 60 | ; 61 | } 62 | 63 | /** 64 | * Evaluates to true if any key in an array matches the given matcher. 65 | * 66 | * @param mixed $key as a {@link Hamcrest\Matcher} or a value. 67 | * 68 | * @return \Hamcrest\Arrays\IsArrayContainingKey 69 | * @factory hasKey 70 | */ 71 | public static function hasKeyInArray($key) 72 | { 73 | return new self(Util::wrapValueWithIsEqual($key)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Arrays/IsArrayContainingKeyValuePair.php: -------------------------------------------------------------------------------- 1 | _keyMatcher = $keyMatcher; 27 | $this->_valueMatcher = $valueMatcher; 28 | } 29 | 30 | protected function matchesSafely($array) 31 | { 32 | foreach ($array as $key => $value) { 33 | if ($this->_keyMatcher->matches($key) && $this->_valueMatcher->matches($value)) { 34 | return true; 35 | } 36 | } 37 | 38 | return false; 39 | } 40 | 41 | protected function describeMismatchSafely($array, Description $mismatchDescription) 42 | { 43 | //Not using appendValueList() so that keys can be shown 44 | $mismatchDescription->appendText('array was ') 45 | ->appendText('[') 46 | ; 47 | $loop = false; 48 | foreach ($array as $key => $value) { 49 | if ($loop) { 50 | $mismatchDescription->appendText(', '); 51 | } 52 | $mismatchDescription->appendValue($key)->appendText(' => ')->appendValue($value); 53 | $loop = true; 54 | } 55 | $mismatchDescription->appendText(']'); 56 | } 57 | 58 | public function describeTo(Description $description) 59 | { 60 | $description->appendText('array containing [') 61 | ->appendDescriptionOf($this->_keyMatcher) 62 | ->appendText(' => ') 63 | ->appendDescriptionOf($this->_valueMatcher) 64 | ->appendText(']') 65 | ; 66 | } 67 | 68 | /** 69 | * Test if an array has both an key and value in parity with each other. 70 | * 71 | * @factory hasEntry 72 | */ 73 | public static function hasKeyValuePair($key, $value) 74 | { 75 | return new self( 76 | Util::wrapValueWithIsEqual($key), 77 | Util::wrapValueWithIsEqual($value) 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Arrays/IsArrayWithSize.php: -------------------------------------------------------------------------------- 1 | _elementMatchers = $elementMatchers; 19 | $this->_mismatchDescription = $mismatchDescription; 20 | } 21 | 22 | public function matches($item) 23 | { 24 | return $this->_isNotSurplus($item) && $this->_isMatched($item); 25 | } 26 | 27 | public function isFinished($items) 28 | { 29 | if (empty($this->_elementMatchers)) { 30 | return true; 31 | } 32 | 33 | $this->_mismatchDescription 34 | ->appendText('No item matches: ')->appendList('', ', ', '', $this->_elementMatchers) 35 | ->appendText(' in ')->appendValueList('[', ', ', ']', $items) 36 | ; 37 | 38 | return false; 39 | } 40 | 41 | // -- Private Methods 42 | 43 | private function _isNotSurplus($item) 44 | { 45 | if (empty($this->_elementMatchers)) { 46 | $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); 47 | 48 | return false; 49 | } 50 | 51 | return true; 52 | } 53 | 54 | private function _isMatched($item) 55 | { 56 | /** @var $matcher \Hamcrest\Matcher */ 57 | foreach ($this->_elementMatchers as $i => $matcher) { 58 | if ($matcher->matches($item)) { 59 | unset($this->_elementMatchers[$i]); 60 | 61 | return true; 62 | } 63 | } 64 | 65 | $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); 66 | 67 | return false; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Arrays/SeriesMatchingOnce.php: -------------------------------------------------------------------------------- 1 | _elementMatchers = $elementMatchers; 22 | $this->_keys = array_keys($elementMatchers); 23 | $this->_mismatchDescription = $mismatchDescription; 24 | } 25 | 26 | public function matches($item) 27 | { 28 | return $this->_isNotSurplus($item) && $this->_isMatched($item); 29 | } 30 | 31 | public function isFinished() 32 | { 33 | if (!empty($this->_elementMatchers)) { 34 | $nextMatcher = current($this->_elementMatchers); 35 | $this->_mismatchDescription->appendText('No item matched: ')->appendDescriptionOf($nextMatcher); 36 | 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | 43 | // -- Private Methods 44 | 45 | private function _isNotSurplus($item) 46 | { 47 | if (empty($this->_elementMatchers)) { 48 | $this->_mismatchDescription->appendText('Not matched: ')->appendValue($item); 49 | 50 | return false; 51 | } 52 | 53 | return true; 54 | } 55 | 56 | private function _isMatched($item) 57 | { 58 | $this->_nextMatchKey = array_shift($this->_keys); 59 | $nextMatcher = array_shift($this->_elementMatchers); 60 | 61 | if (!$nextMatcher->matches($item)) { 62 | $this->_describeMismatch($nextMatcher, $item); 63 | 64 | return false; 65 | } 66 | 67 | return true; 68 | } 69 | 70 | private function _describeMismatch(Matcher $matcher, $item) 71 | { 72 | $this->_mismatchDescription->appendText('item with key ' . $this->_nextMatchKey . ': '); 73 | $matcher->describeMismatch($item, $this->_mismatchDescription); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/AssertionError.php: -------------------------------------------------------------------------------- 1 | append($text); 18 | 19 | return $this; 20 | } 21 | 22 | public function appendDescriptionOf(SelfDescribing $value) 23 | { 24 | $value->describeTo($this); 25 | 26 | return $this; 27 | } 28 | 29 | public function appendValue($value) 30 | { 31 | if (is_null($value)) { 32 | $this->append('null'); 33 | } elseif (is_string($value)) { 34 | $this->_toPhpSyntax($value); 35 | } elseif (is_float($value)) { 36 | $this->append('<'); 37 | $this->append($value); 38 | $this->append('F>'); 39 | } elseif (is_bool($value)) { 40 | $this->append('<'); 41 | $this->append($value ? 'true' : 'false'); 42 | $this->append('>'); 43 | } elseif (is_array($value) || $value instanceof \Iterator || $value instanceof \IteratorAggregate) { 44 | $this->appendValueList('[', ', ', ']', $value); 45 | } elseif (is_object($value) && !method_exists($value, '__toString')) { 46 | $this->append('<'); 47 | $this->append(get_class($value)); 48 | $this->append('>'); 49 | } else { 50 | $this->append('<'); 51 | $this->append($value); 52 | $this->append('>'); 53 | } 54 | 55 | return $this; 56 | } 57 | 58 | public function appendValueList($start, $separator, $end, $values) 59 | { 60 | $list = array(); 61 | foreach ($values as $v) { 62 | $list[] = new SelfDescribingValue($v); 63 | } 64 | 65 | $this->appendList($start, $separator, $end, $list); 66 | 67 | return $this; 68 | } 69 | 70 | public function appendList($start, $separator, $end, $values) 71 | { 72 | $this->append($start); 73 | 74 | $separate = false; 75 | 76 | foreach ($values as $value) { 77 | /*if (!($value instanceof Hamcrest\SelfDescribing)) { 78 | $value = new Hamcrest\Internal\SelfDescribingValue($value); 79 | }*/ 80 | 81 | if ($separate) { 82 | $this->append($separator); 83 | } 84 | 85 | $this->appendDescriptionOf($value); 86 | 87 | $separate = true; 88 | } 89 | 90 | $this->append($end); 91 | 92 | return $this; 93 | } 94 | 95 | // -- Protected Methods 96 | 97 | /** 98 | * Append the String $str to the description. 99 | */ 100 | abstract protected function append($str); 101 | 102 | // -- Private Methods 103 | 104 | private function _toPhpSyntax($value) 105 | { 106 | $str = '"'; 107 | for ($i = 0, $len = strlen($value); $i < $len; ++$i) { 108 | switch ($value[$i]) { 109 | case '"': 110 | $str .= '\\"'; 111 | break; 112 | 113 | case "\t": 114 | $str .= '\\t'; 115 | break; 116 | 117 | case "\r": 118 | $str .= '\\r'; 119 | break; 120 | 121 | case "\n": 122 | $str .= '\\n'; 123 | break; 124 | 125 | default: 126 | $str .= $value[$i]; 127 | } 128 | } 129 | $str .= '"'; 130 | $this->append($str); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/BaseMatcher.php: -------------------------------------------------------------------------------- 1 | appendText('was ')->appendValue($item); 19 | } 20 | 21 | public function __toString() 22 | { 23 | return StringDescription::toString($this); 24 | } 25 | 26 | public function __invoke() 27 | { 28 | return call_user_func_array(array($this, 'matches'), func_get_args()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Collection/IsEmptyTraversable.php: -------------------------------------------------------------------------------- 1 | _empty = $empty; 24 | } 25 | 26 | public function matches($item) 27 | { 28 | if (!$item instanceof \Traversable) { 29 | return false; 30 | } 31 | 32 | foreach ($item as $value) { 33 | return !$this->_empty; 34 | } 35 | 36 | return $this->_empty; 37 | } 38 | 39 | public function describeTo(Description $description) 40 | { 41 | $description->appendText($this->_empty ? 'an empty traversable' : 'a non-empty traversable'); 42 | } 43 | 44 | /** 45 | * Returns true if traversable is empty. 46 | * 47 | * @factory 48 | */ 49 | public static function emptyTraversable() 50 | { 51 | if (!self::$_INSTANCE) { 52 | self::$_INSTANCE = new self; 53 | } 54 | 55 | return self::$_INSTANCE; 56 | } 57 | 58 | /** 59 | * Returns true if traversable is not empty. 60 | * 61 | * @factory 62 | */ 63 | public static function nonEmptyTraversable() 64 | { 65 | if (!self::$_NOT_INSTANCE) { 66 | self::$_NOT_INSTANCE = new self(false); 67 | } 68 | 69 | return self::$_NOT_INSTANCE; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Collection/IsTraversableWithSize.php: -------------------------------------------------------------------------------- 1 | false. 15 | */ 16 | class AllOf extends DiagnosingMatcher 17 | { 18 | 19 | private $_matchers; 20 | 21 | public function __construct(array $matchers) 22 | { 23 | Util::checkAllAreMatchers($matchers); 24 | 25 | $this->_matchers = $matchers; 26 | } 27 | 28 | public function matchesWithDiagnosticDescription($item, Description $mismatchDescription) 29 | { 30 | /** @var $matcher \Hamcrest\Matcher */ 31 | foreach ($this->_matchers as $matcher) { 32 | if (!$matcher->matches($item)) { 33 | $mismatchDescription->appendDescriptionOf($matcher)->appendText(' '); 34 | $matcher->describeMismatch($item, $mismatchDescription); 35 | 36 | return false; 37 | } 38 | } 39 | 40 | return true; 41 | } 42 | 43 | public function describeTo(Description $description) 44 | { 45 | $description->appendList('(', ' and ', ')', $this->_matchers); 46 | } 47 | 48 | /** 49 | * Evaluates to true only if ALL of the passed in matchers evaluate to true. 50 | * 51 | * @factory ... 52 | */ 53 | public static function allOf(/* args... */) 54 | { 55 | $args = func_get_args(); 56 | 57 | return new self(Util::createMatcherArray($args)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/AnyOf.php: -------------------------------------------------------------------------------- 1 | true. 14 | */ 15 | class AnyOf extends ShortcutCombination 16 | { 17 | 18 | public function __construct(array $matchers) 19 | { 20 | parent::__construct($matchers); 21 | } 22 | 23 | public function matches($item) 24 | { 25 | return $this->matchesWithShortcut($item, true); 26 | } 27 | 28 | public function describeTo(Description $description) 29 | { 30 | $this->describeToWithOperator($description, 'or'); 31 | } 32 | 33 | /** 34 | * Evaluates to true if ANY of the passed in matchers evaluate to true. 35 | * 36 | * @factory ... 37 | */ 38 | public static function anyOf(/* args... */) 39 | { 40 | $args = func_get_args(); 41 | 42 | return new self(Util::createMatcherArray($args)); 43 | } 44 | 45 | /** 46 | * Evaluates to false if ANY of the passed in matchers evaluate to true. 47 | * 48 | * @factory ... 49 | */ 50 | public static function noneOf(/* args... */) 51 | { 52 | $args = func_get_args(); 53 | 54 | return IsNot::not( 55 | new self(Util::createMatcherArray($args)) 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/CombinableMatcher.php: -------------------------------------------------------------------------------- 1 | _matcher = $matcher; 20 | } 21 | 22 | public function matches($item) 23 | { 24 | return $this->_matcher->matches($item); 25 | } 26 | 27 | public function describeTo(Description $description) 28 | { 29 | $description->appendDescriptionOf($this->_matcher); 30 | } 31 | 32 | /** Diversion from Hamcrest-Java... Logical "and" not permitted */ 33 | public function andAlso(Matcher $other) 34 | { 35 | return new self(new AllOf($this->_templatedListWith($other))); 36 | } 37 | 38 | /** Diversion from Hamcrest-Java... Logical "or" not permitted */ 39 | public function orElse(Matcher $other) 40 | { 41 | return new self(new AnyOf($this->_templatedListWith($other))); 42 | } 43 | 44 | /** 45 | * This is useful for fluently combining matchers that must both pass. 46 | * For example: 47 | *
48 |      *   assertThat($string, both(containsString("a"))->andAlso(containsString("b")));
49 |      * 
50 | * 51 | * @factory 52 | */ 53 | public static function both(Matcher $matcher) 54 | { 55 | return new self($matcher); 56 | } 57 | 58 | /** 59 | * This is useful for fluently combining matchers where either may pass, 60 | * for example: 61 | *
62 |      *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
63 |      * 
64 | * 65 | * @factory 66 | */ 67 | public static function either(Matcher $matcher) 68 | { 69 | return new self($matcher); 70 | } 71 | 72 | // -- Private Methods 73 | 74 | private function _templatedListWith(Matcher $other) 75 | { 76 | return array($this->_matcher, $other); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/DescribedAs.php: -------------------------------------------------------------------------------- 1 | _descriptionTemplate = $descriptionTemplate; 26 | $this->_matcher = $matcher; 27 | $this->_values = $values; 28 | } 29 | 30 | public function matches($item) 31 | { 32 | return $this->_matcher->matches($item); 33 | } 34 | 35 | public function describeTo(Description $description) 36 | { 37 | $textStart = 0; 38 | while (preg_match(self::ARG_PATTERN, $this->_descriptionTemplate, $matches, PREG_OFFSET_CAPTURE, $textStart)) { 39 | $text = $matches[0][0]; 40 | $index = $matches[1][0]; 41 | $offset = $matches[0][1]; 42 | 43 | $description->appendText(substr($this->_descriptionTemplate, $textStart, $offset - $textStart)); 44 | $description->appendValue($this->_values[$index]); 45 | 46 | $textStart = $offset + strlen($text); 47 | } 48 | 49 | if ($textStart < strlen($this->_descriptionTemplate)) { 50 | $description->appendText(substr($this->_descriptionTemplate, $textStart)); 51 | } 52 | } 53 | 54 | /** 55 | * Wraps an existing matcher and overrides the description when it fails. 56 | * 57 | * @factory ... 58 | */ 59 | public static function describedAs(/* $description, Hamcrest\Matcher $matcher, $values... */) 60 | { 61 | $args = func_get_args(); 62 | $description = array_shift($args); 63 | $matcher = array_shift($args); 64 | $values = $args; 65 | 66 | return new self($description, $matcher, $values); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/Every.php: -------------------------------------------------------------------------------- 1 | _matcher = $matcher; 22 | } 23 | 24 | protected function matchesSafelyWithDiagnosticDescription($items, Description $mismatchDescription) 25 | { 26 | foreach ($items as $item) { 27 | if (!$this->_matcher->matches($item)) { 28 | $mismatchDescription->appendText('an item '); 29 | $this->_matcher->describeMismatch($item, $mismatchDescription); 30 | 31 | return false; 32 | } 33 | } 34 | 35 | return true; 36 | } 37 | 38 | public function describeTo(Description $description) 39 | { 40 | $description->appendText('every item is ')->appendDescriptionOf($this->_matcher); 41 | } 42 | 43 | /** 44 | * @param Matcher $itemMatcher 45 | * A matcher to apply to every element in an array. 46 | * 47 | * @return \Hamcrest\Core\Every 48 | * Evaluates to TRUE for a collection in which every item matches $itemMatcher 49 | * 50 | * @factory 51 | */ 52 | public static function everyItem(Matcher $itemMatcher) 53 | { 54 | return new self($itemMatcher); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/HasToString.php: -------------------------------------------------------------------------------- 1 | toString(); 42 | } 43 | 44 | return (string) $actual; 45 | } 46 | 47 | /** 48 | * Does array size satisfy a given matcher? 49 | * 50 | * @factory 51 | */ 52 | public static function hasToString($matcher) 53 | { 54 | return new self(Util::wrapValueWithIsEqual($matcher)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/Is.php: -------------------------------------------------------------------------------- 1 | _matcher = $matcher; 27 | } 28 | 29 | public function matches($arg) 30 | { 31 | return $this->_matcher->matches($arg); 32 | } 33 | 34 | public function describeTo(Description $description) 35 | { 36 | $description->appendText('is ')->appendDescriptionOf($this->_matcher); 37 | } 38 | 39 | public function describeMismatch($item, Description $mismatchDescription) 40 | { 41 | $this->_matcher->describeMismatch($item, $mismatchDescription); 42 | } 43 | 44 | /** 45 | * Decorates another Matcher, retaining the behavior but allowing tests 46 | * to be slightly more expressive. 47 | * 48 | * For example: assertThat($cheese, equalTo($smelly)) 49 | * vs. assertThat($cheese, is(equalTo($smelly))) 50 | * 51 | * @factory 52 | */ 53 | public static function is($value) 54 | { 55 | return new self(Util::wrapValueWithIsEqual($value)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsAnything.php: -------------------------------------------------------------------------------- 1 | true. 12 | */ 13 | class IsAnything extends BaseMatcher 14 | { 15 | 16 | private $_message; 17 | 18 | public function __construct($message = 'ANYTHING') 19 | { 20 | $this->_message = $message; 21 | } 22 | 23 | public function matches($item) 24 | { 25 | return true; 26 | } 27 | 28 | public function describeTo(Description $description) 29 | { 30 | $description->appendText($this->_message); 31 | } 32 | 33 | /** 34 | * This matcher always evaluates to true. 35 | * 36 | * @param string $description A meaningful string used when describing itself. 37 | * 38 | * @return \Hamcrest\Core\IsAnything 39 | * @factory 40 | */ 41 | public static function anything($description = 'ANYTHING') 42 | { 43 | return new self($description); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsCollectionContaining.php: -------------------------------------------------------------------------------- 1 | _elementMatcher = $elementMatcher; 25 | } 26 | 27 | protected function matchesSafely($items) 28 | { 29 | foreach ($items as $item) { 30 | if ($this->_elementMatcher->matches($item)) { 31 | return true; 32 | } 33 | } 34 | 35 | return false; 36 | } 37 | 38 | protected function describeMismatchSafely($items, Description $mismatchDescription) 39 | { 40 | $mismatchDescription->appendText('was ')->appendValue($items); 41 | } 42 | 43 | public function describeTo(Description $description) 44 | { 45 | $description 46 | ->appendText('a collection containing ') 47 | ->appendDescriptionOf($this->_elementMatcher) 48 | ; 49 | } 50 | 51 | /** 52 | * Test if the value is an array containing this matcher. 53 | * 54 | * Example: 55 | *
56 |      * assertThat(array('a', 'b'), hasItem(equalTo('b')));
57 |      * //Convenience defaults to equalTo()
58 |      * assertThat(array('a', 'b'), hasItem('b'));
59 |      * 
60 | * 61 | * @factory ... 62 | */ 63 | public static function hasItem() 64 | { 65 | $args = func_get_args(); 66 | $firstArg = array_shift($args); 67 | 68 | return new self(Util::wrapValueWithIsEqual($firstArg)); 69 | } 70 | 71 | /** 72 | * Test if the value is an array containing elements that match all of these 73 | * matchers. 74 | * 75 | * Example: 76 | *
77 |      * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
78 |      * 
79 | * 80 | * @factory ... 81 | */ 82 | public static function hasItems(/* args... */) 83 | { 84 | $args = func_get_args(); 85 | $matchers = array(); 86 | 87 | foreach ($args as $arg) { 88 | $matchers[] = self::hasItem($arg); 89 | } 90 | 91 | return AllOf::allOf($matchers); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsEqual.php: -------------------------------------------------------------------------------- 1 | _item = $item; 22 | } 23 | 24 | public function matches($arg) 25 | { 26 | return (($arg == $this->_item) && ($this->_item == $arg)); 27 | } 28 | 29 | public function describeTo(Description $description) 30 | { 31 | $description->appendValue($this->_item); 32 | } 33 | 34 | /** 35 | * Is the value equal to another value, as tested by the use of the "==" 36 | * comparison operator? 37 | * 38 | * @factory 39 | */ 40 | public static function equalTo($item) 41 | { 42 | return new self($item); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsIdentical.php: -------------------------------------------------------------------------------- 1 | _value = $value; 22 | } 23 | 24 | public function describeTo(Description $description) 25 | { 26 | $description->appendValue($this->_value); 27 | } 28 | 29 | /** 30 | * Tests of the value is identical to $value as tested by the "===" operator. 31 | * 32 | * @factory 33 | */ 34 | public static function identicalTo($value) 35 | { 36 | return new self($value); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsInstanceOf.php: -------------------------------------------------------------------------------- 1 | _theClass = $theClass; 28 | } 29 | 30 | protected function matchesWithDiagnosticDescription($item, Description $mismatchDescription) 31 | { 32 | if (!is_object($item)) { 33 | $mismatchDescription->appendText('was ')->appendValue($item); 34 | 35 | return false; 36 | } 37 | 38 | if (!($item instanceof $this->_theClass)) { 39 | $mismatchDescription->appendText('[' . get_class($item) . '] ') 40 | ->appendValue($item); 41 | 42 | return false; 43 | } 44 | 45 | return true; 46 | } 47 | 48 | public function describeTo(Description $description) 49 | { 50 | $description->appendText('an instance of ') 51 | ->appendText($this->_theClass) 52 | ; 53 | } 54 | 55 | /** 56 | * Is the value an instance of a particular type? 57 | * This version assumes no relationship between the required type and 58 | * the signature of the method that sets it up, for example in 59 | * assertThat($anObject, anInstanceOf('Thing')); 60 | * 61 | * @factory any 62 | */ 63 | public static function anInstanceOf($theClass) 64 | { 65 | return new self($theClass); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsNot.php: -------------------------------------------------------------------------------- 1 | _matcher = $matcher; 23 | } 24 | 25 | public function matches($arg) 26 | { 27 | return !$this->_matcher->matches($arg); 28 | } 29 | 30 | public function describeTo(Description $description) 31 | { 32 | $description->appendText('not ')->appendDescriptionOf($this->_matcher); 33 | } 34 | 35 | /** 36 | * Matches if value does not match $value. 37 | * 38 | * @factory 39 | */ 40 | public static function not($value) 41 | { 42 | return new self(Util::wrapValueWithIsEqual($value)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsNull.php: -------------------------------------------------------------------------------- 1 | appendText('null'); 27 | } 28 | 29 | /** 30 | * Matches if value is null. 31 | * 32 | * @factory 33 | */ 34 | public static function nullValue() 35 | { 36 | if (!self::$_INSTANCE) { 37 | self::$_INSTANCE = new self(); 38 | } 39 | 40 | return self::$_INSTANCE; 41 | } 42 | 43 | /** 44 | * Matches if value is not null. 45 | * 46 | * @factory 47 | */ 48 | public static function notNullValue() 49 | { 50 | if (!self::$_NOT_INSTANCE) { 51 | self::$_NOT_INSTANCE = IsNot::not(self::nullValue()); 52 | } 53 | 54 | return self::$_NOT_INSTANCE; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsSame.php: -------------------------------------------------------------------------------- 1 | _object = $object; 22 | } 23 | 24 | public function matches($object) 25 | { 26 | return ($object === $this->_object) && ($this->_object === $object); 27 | } 28 | 29 | public function describeTo(Description $description) 30 | { 31 | $description->appendText('sameInstance(') 32 | ->appendValue($this->_object) 33 | ->appendText(')') 34 | ; 35 | } 36 | 37 | /** 38 | * Creates a new instance of IsSame. 39 | * 40 | * @param mixed $object 41 | * The predicate evaluates to true only when the argument is 42 | * this object. 43 | * 44 | * @return \Hamcrest\Core\IsSame 45 | * @factory 46 | */ 47 | public static function sameInstance($object) 48 | { 49 | return new self($object); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/IsTypeOf.php: -------------------------------------------------------------------------------- 1 | _theType = strtolower($theType); 27 | } 28 | 29 | public function matches($item) 30 | { 31 | return strtolower(gettype($item)) == $this->_theType; 32 | } 33 | 34 | public function describeTo(Description $description) 35 | { 36 | $description->appendText(self::getTypeDescription($this->_theType)); 37 | } 38 | 39 | public function describeMismatch($item, Description $description) 40 | { 41 | if ($item === null) { 42 | $description->appendText('was null'); 43 | } else { 44 | $description->appendText('was ') 45 | ->appendText(self::getTypeDescription(strtolower(gettype($item)))) 46 | ->appendText(' ') 47 | ->appendValue($item) 48 | ; 49 | } 50 | } 51 | 52 | public static function getTypeDescription($type) 53 | { 54 | if ($type == 'null') { 55 | return 'null'; 56 | } 57 | 58 | return (strpos('aeiou', substr($type, 0, 1)) === false ? 'a ' : 'an ') 59 | . $type; 60 | } 61 | 62 | /** 63 | * Is the value a particular built-in type? 64 | * 65 | * @factory 66 | */ 67 | public static function typeOf($theType) 68 | { 69 | return new self($theType); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/Set.php: -------------------------------------------------------------------------------- 1 | 15 | * assertThat(array('a', 'b'), set('b')); 16 | * assertThat($foo, set('bar')); 17 | * assertThat('Server', notSet('defaultPort')); 18 | * 19 | * 20 | * @todo Replace $property with a matcher and iterate all property names. 21 | */ 22 | class Set extends BaseMatcher 23 | { 24 | 25 | private $_property; 26 | private $_not; 27 | 28 | public function __construct($property, $not = false) 29 | { 30 | $this->_property = $property; 31 | $this->_not = $not; 32 | } 33 | 34 | public function matches($item) 35 | { 36 | if ($item === null) { 37 | return false; 38 | } 39 | $property = $this->_property; 40 | if (is_array($item)) { 41 | $result = isset($item[$property]); 42 | } elseif (is_object($item)) { 43 | $result = isset($item->$property); 44 | } elseif (is_string($item)) { 45 | $result = isset($item::$$property); 46 | } else { 47 | throw new \InvalidArgumentException('Must pass an object, array, or class name'); 48 | } 49 | 50 | return $this->_not ? !$result : $result; 51 | } 52 | 53 | public function describeTo(Description $description) 54 | { 55 | $description->appendText($this->_not ? 'unset property ' : 'set property ')->appendText($this->_property); 56 | } 57 | 58 | public function describeMismatch($item, Description $description) 59 | { 60 | $value = ''; 61 | if (!$this->_not) { 62 | $description->appendText('was not set'); 63 | } else { 64 | $property = $this->_property; 65 | if (is_array($item)) { 66 | $value = $item[$property]; 67 | } elseif (is_object($item)) { 68 | $value = $item->$property; 69 | } elseif (is_string($item)) { 70 | $value = $item::$$property; 71 | } 72 | parent::describeMismatch($value, $description); 73 | } 74 | } 75 | 76 | /** 77 | * Matches if value (class, object, or array) has named $property. 78 | * 79 | * @factory 80 | */ 81 | public static function set($property) 82 | { 83 | return new self($property); 84 | } 85 | 86 | /** 87 | * Matches if value (class, object, or array) does not have named $property. 88 | * 89 | * @factory 90 | */ 91 | public static function notSet($property) 92 | { 93 | return new self($property, true); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Core/ShortcutCombination.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | private $_matchers; 19 | 20 | public function __construct(array $matchers) 21 | { 22 | Util::checkAllAreMatchers($matchers); 23 | 24 | $this->_matchers = $matchers; 25 | } 26 | 27 | protected function matchesWithShortcut($item, $shortcut) 28 | { 29 | /** @var $matcher \Hamcrest\Matcher */ 30 | foreach ($this->_matchers as $matcher) { 31 | if ($matcher->matches($item) == $shortcut) { 32 | return $shortcut; 33 | } 34 | } 35 | 36 | return !$shortcut; 37 | } 38 | 39 | public function describeToWithOperator(Description $description, $operator) 40 | { 41 | $description->appendList('(', ' ' . $operator . ' ', ')', $this->_matchers); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Description.php: -------------------------------------------------------------------------------- 1 | matchesWithDiagnosticDescription($item, new NullDescription()); 17 | } 18 | 19 | public function describeMismatch($item, Description $mismatchDescription) 20 | { 21 | $this->matchesWithDiagnosticDescription($item, $mismatchDescription); 22 | } 23 | 24 | abstract protected function matchesWithDiagnosticDescription($item, Description $mismatchDescription); 25 | } 26 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/FeatureMatcher.php: -------------------------------------------------------------------------------- 1 | featureValueOf() in a subclass to pull out the feature to be 11 | * matched against. 12 | */ 13 | abstract class FeatureMatcher extends TypeSafeDiagnosingMatcher 14 | { 15 | 16 | private $_subMatcher; 17 | private $_featureDescription; 18 | private $_featureName; 19 | 20 | /** 21 | * Constructor. 22 | * 23 | * @param string $type 24 | * @param string $subtype 25 | * @param \Hamcrest\Matcher $subMatcher The matcher to apply to the feature 26 | * @param string $featureDescription Descriptive text to use in describeTo 27 | * @param string $featureName Identifying text for mismatch message 28 | */ 29 | public function __construct($type, $subtype, Matcher $subMatcher, $featureDescription, $featureName) 30 | { 31 | parent::__construct($type, $subtype); 32 | 33 | $this->_subMatcher = $subMatcher; 34 | $this->_featureDescription = $featureDescription; 35 | $this->_featureName = $featureName; 36 | } 37 | 38 | /** 39 | * Implement this to extract the interesting feature. 40 | * 41 | * @param mixed $actual the target object 42 | * 43 | * @return mixed the feature to be matched 44 | */ 45 | abstract protected function featureValueOf($actual); 46 | 47 | public function matchesSafelyWithDiagnosticDescription($actual, Description $mismatchDescription) 48 | { 49 | $featureValue = $this->featureValueOf($actual); 50 | 51 | if (!$this->_subMatcher->matches($featureValue)) { 52 | $mismatchDescription->appendText($this->_featureName) 53 | ->appendText(' was ')->appendValue($featureValue); 54 | 55 | return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | final public function describeTo(Description $description) 62 | { 63 | $description->appendText($this->_featureDescription)->appendText(' ') 64 | ->appendDescriptionOf($this->_subMatcher) 65 | ; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Internal/SelfDescribingValue.php: -------------------------------------------------------------------------------- 1 | _value = $value; 21 | } 22 | 23 | public function describeTo(Description $description) 24 | { 25 | $description->appendValue($this->_value); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Matcher.php: -------------------------------------------------------------------------------- 1 | 12 | * Matcher implementations should NOT directly implement this interface. 13 | * Instead, extend the {@link Hamcrest\BaseMatcher} abstract class, 14 | * which will ensure that the Matcher API can grow to support 15 | * new features and remain compatible with all Matcher implementations. 16 | *

17 | * For easy access to common Matcher implementations, use the static factory 18 | * methods in {@link Hamcrest\CoreMatchers}. 19 | * 20 | * @see Hamcrest\CoreMatchers 21 | * @see Hamcrest\BaseMatcher 22 | */ 23 | interface Matcher extends SelfDescribing 24 | { 25 | 26 | /** 27 | * Evaluates the matcher for argument $item. 28 | * 29 | * @param mixed $item the object against which the matcher is evaluated. 30 | * 31 | * @return boolean true if $item matches, 32 | * otherwise false. 33 | * 34 | * @see Hamcrest\BaseMatcher 35 | */ 36 | public function matches($item); 37 | 38 | /** 39 | * Generate a description of why the matcher has not accepted the item. 40 | * The description will be part of a larger description of why a matching 41 | * failed, so it should be concise. 42 | * This method assumes that matches($item) is false, but 43 | * will not check this. 44 | * 45 | * @param mixed $item The item that the Matcher has rejected. 46 | * @param Description $description 47 | * @return 48 | */ 49 | public function describeMismatch($item, Description $description); 50 | } 51 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/MatcherAssert.php: -------------------------------------------------------------------------------- 1 | 29 | * // With an identifier 30 | * assertThat("apple flavour", $apple->flavour(), equalTo("tasty")); 31 | * // Without an identifier 32 | * assertThat($apple->flavour(), equalTo("tasty")); 33 | * // Evaluating a boolean expression 34 | * assertThat("some error", $a > $b); 35 | * assertThat($a > $b); 36 | * 37 | */ 38 | public static function assertThat(/* $args ... */) 39 | { 40 | $args = func_get_args(); 41 | switch (count($args)) { 42 | case 1: 43 | self::$_count++; 44 | if (!$args[0]) { 45 | throw new AssertionError(); 46 | } 47 | break; 48 | 49 | case 2: 50 | self::$_count++; 51 | if ($args[1] instanceof Matcher) { 52 | self::doAssert('', $args[0], $args[1]); 53 | } elseif (!$args[1]) { 54 | throw new AssertionError($args[0]); 55 | } 56 | break; 57 | 58 | case 3: 59 | self::$_count++; 60 | self::doAssert( 61 | $args[0], 62 | $args[1], 63 | Util::wrapValueWithIsEqual($args[2]) 64 | ); 65 | break; 66 | 67 | default: 68 | throw new \InvalidArgumentException('assertThat() requires one to three arguments'); 69 | } 70 | } 71 | 72 | /** 73 | * Returns the number of assertions performed. 74 | * 75 | * @return int 76 | */ 77 | public static function getCount() 78 | { 79 | return self::$_count; 80 | } 81 | 82 | /** 83 | * Resets the number of assertions performed to zero. 84 | */ 85 | public static function resetCount() 86 | { 87 | self::$_count = 0; 88 | } 89 | 90 | /** 91 | * Performs the actual assertion logic. 92 | * 93 | * If $matcher doesn't match $actual, 94 | * throws a {@link Hamcrest\AssertionError} with a description 95 | * of the failure along with the optional $identifier. 96 | * 97 | * @param string $identifier added to the message upon failure 98 | * @param mixed $actual value to compare against $matcher 99 | * @param \Hamcrest\Matcher $matcher applied to $actual 100 | * @throws AssertionError 101 | */ 102 | private static function doAssert($identifier, $actual, Matcher $matcher) 103 | { 104 | if (!$matcher->matches($actual)) { 105 | $description = new StringDescription(); 106 | if (!empty($identifier)) { 107 | $description->appendText($identifier . PHP_EOL); 108 | } 109 | $description->appendText('Expected: ') 110 | ->appendDescriptionOf($matcher) 111 | ->appendText(PHP_EOL . ' but: '); 112 | 113 | $matcher->describeMismatch($actual, $description); 114 | 115 | throw new AssertionError((string) $description); 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Matchers.php: -------------------------------------------------------------------------------- 1 | 209 | * assertThat($string, both(containsString("a"))->andAlso(containsString("b"))); 210 | * 211 | */ 212 | public static function both(\Hamcrest\Matcher $matcher) 213 | { 214 | return \Hamcrest\Core\CombinableMatcher::both($matcher); 215 | } 216 | 217 | /** 218 | * This is useful for fluently combining matchers where either may pass, 219 | * for example: 220 | *

221 |      *   assertThat($string, either(containsString("a"))->orElse(containsString("b")));
222 |      * 
223 | */ 224 | public static function either(\Hamcrest\Matcher $matcher) 225 | { 226 | return \Hamcrest\Core\CombinableMatcher::either($matcher); 227 | } 228 | 229 | /** 230 | * Wraps an existing matcher and overrides the description when it fails. 231 | */ 232 | public static function describedAs(/* args... */) 233 | { 234 | $args = func_get_args(); 235 | return call_user_func_array(array('\Hamcrest\Core\DescribedAs', 'describedAs'), $args); 236 | } 237 | 238 | /** 239 | * @param Matcher $itemMatcher 240 | * A matcher to apply to every element in an array. 241 | * 242 | * @return \Hamcrest\Core\Every 243 | * Evaluates to TRUE for a collection in which every item matches $itemMatcher 244 | */ 245 | public static function everyItem(\Hamcrest\Matcher $itemMatcher) 246 | { 247 | return \Hamcrest\Core\Every::everyItem($itemMatcher); 248 | } 249 | 250 | /** 251 | * Does array size satisfy a given matcher? 252 | */ 253 | public static function hasToString($matcher) 254 | { 255 | return \Hamcrest\Core\HasToString::hasToString($matcher); 256 | } 257 | 258 | /** 259 | * Decorates another Matcher, retaining the behavior but allowing tests 260 | * to be slightly more expressive. 261 | * 262 | * For example: assertThat($cheese, equalTo($smelly)) 263 | * vs. assertThat($cheese, is(equalTo($smelly))) 264 | */ 265 | public static function is($value) 266 | { 267 | return \Hamcrest\Core\Is::is($value); 268 | } 269 | 270 | /** 271 | * This matcher always evaluates to true. 272 | * 273 | * @param string $description A meaningful string used when describing itself. 274 | * 275 | * @return \Hamcrest\Core\IsAnything 276 | */ 277 | public static function anything($description = 'ANYTHING') 278 | { 279 | return \Hamcrest\Core\IsAnything::anything($description); 280 | } 281 | 282 | /** 283 | * Test if the value is an array containing this matcher. 284 | * 285 | * Example: 286 | *
287 |      * assertThat(array('a', 'b'), hasItem(equalTo('b')));
288 |      * //Convenience defaults to equalTo()
289 |      * assertThat(array('a', 'b'), hasItem('b'));
290 |      * 
291 | */ 292 | public static function hasItem(/* args... */) 293 | { 294 | $args = func_get_args(); 295 | return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItem'), $args); 296 | } 297 | 298 | /** 299 | * Test if the value is an array containing elements that match all of these 300 | * matchers. 301 | * 302 | * Example: 303 | *
304 |      * assertThat(array('a', 'b', 'c'), hasItems(equalTo('a'), equalTo('b')));
305 |      * 
306 | */ 307 | public static function hasItems(/* args... */) 308 | { 309 | $args = func_get_args(); 310 | return call_user_func_array(array('\Hamcrest\Core\IsCollectionContaining', 'hasItems'), $args); 311 | } 312 | 313 | /** 314 | * Is the value equal to another value, as tested by the use of the "==" 315 | * comparison operator? 316 | */ 317 | public static function equalTo($item) 318 | { 319 | return \Hamcrest\Core\IsEqual::equalTo($item); 320 | } 321 | 322 | /** 323 | * Tests of the value is identical to $value as tested by the "===" operator. 324 | */ 325 | public static function identicalTo($value) 326 | { 327 | return \Hamcrest\Core\IsIdentical::identicalTo($value); 328 | } 329 | 330 | /** 331 | * Is the value an instance of a particular type? 332 | * This version assumes no relationship between the required type and 333 | * the signature of the method that sets it up, for example in 334 | * assertThat($anObject, anInstanceOf('Thing')); 335 | */ 336 | public static function anInstanceOf($theClass) 337 | { 338 | return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); 339 | } 340 | 341 | /** 342 | * Is the value an instance of a particular type? 343 | * This version assumes no relationship between the required type and 344 | * the signature of the method that sets it up, for example in 345 | * assertThat($anObject, anInstanceOf('Thing')); 346 | */ 347 | public static function any($theClass) 348 | { 349 | return \Hamcrest\Core\IsInstanceOf::anInstanceOf($theClass); 350 | } 351 | 352 | /** 353 | * Matches if value does not match $value. 354 | */ 355 | public static function not($value) 356 | { 357 | return \Hamcrest\Core\IsNot::not($value); 358 | } 359 | 360 | /** 361 | * Matches if value is null. 362 | */ 363 | public static function nullValue() 364 | { 365 | return \Hamcrest\Core\IsNull::nullValue(); 366 | } 367 | 368 | /** 369 | * Matches if value is not null. 370 | */ 371 | public static function notNullValue() 372 | { 373 | return \Hamcrest\Core\IsNull::notNullValue(); 374 | } 375 | 376 | /** 377 | * Creates a new instance of IsSame. 378 | * 379 | * @param mixed $object 380 | * The predicate evaluates to true only when the argument is 381 | * this object. 382 | * 383 | * @return \Hamcrest\Core\IsSame 384 | */ 385 | public static function sameInstance($object) 386 | { 387 | return \Hamcrest\Core\IsSame::sameInstance($object); 388 | } 389 | 390 | /** 391 | * Is the value a particular built-in type? 392 | */ 393 | public static function typeOf($theType) 394 | { 395 | return \Hamcrest\Core\IsTypeOf::typeOf($theType); 396 | } 397 | 398 | /** 399 | * Matches if value (class, object, or array) has named $property. 400 | */ 401 | public static function set($property) 402 | { 403 | return \Hamcrest\Core\Set::set($property); 404 | } 405 | 406 | /** 407 | * Matches if value (class, object, or array) does not have named $property. 408 | */ 409 | public static function notSet($property) 410 | { 411 | return \Hamcrest\Core\Set::notSet($property); 412 | } 413 | 414 | /** 415 | * Matches if value is a number equal to $value within some range of 416 | * acceptable error $delta. 417 | */ 418 | public static function closeTo($value, $delta) 419 | { 420 | return \Hamcrest\Number\IsCloseTo::closeTo($value, $delta); 421 | } 422 | 423 | /** 424 | * The value is not > $value, nor < $value. 425 | */ 426 | public static function comparesEqualTo($value) 427 | { 428 | return \Hamcrest\Number\OrderingComparison::comparesEqualTo($value); 429 | } 430 | 431 | /** 432 | * The value is > $value. 433 | */ 434 | public static function greaterThan($value) 435 | { 436 | return \Hamcrest\Number\OrderingComparison::greaterThan($value); 437 | } 438 | 439 | /** 440 | * The value is >= $value. 441 | */ 442 | public static function greaterThanOrEqualTo($value) 443 | { 444 | return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); 445 | } 446 | 447 | /** 448 | * The value is >= $value. 449 | */ 450 | public static function atLeast($value) 451 | { 452 | return \Hamcrest\Number\OrderingComparison::greaterThanOrEqualTo($value); 453 | } 454 | 455 | /** 456 | * The value is < $value. 457 | */ 458 | public static function lessThan($value) 459 | { 460 | return \Hamcrest\Number\OrderingComparison::lessThan($value); 461 | } 462 | 463 | /** 464 | * The value is <= $value. 465 | */ 466 | public static function lessThanOrEqualTo($value) 467 | { 468 | return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); 469 | } 470 | 471 | /** 472 | * The value is <= $value. 473 | */ 474 | public static function atMost($value) 475 | { 476 | return \Hamcrest\Number\OrderingComparison::lessThanOrEqualTo($value); 477 | } 478 | 479 | /** 480 | * Matches if value is a zero-length string. 481 | */ 482 | public static function isEmptyString() 483 | { 484 | return \Hamcrest\Text\IsEmptyString::isEmptyString(); 485 | } 486 | 487 | /** 488 | * Matches if value is a zero-length string. 489 | */ 490 | public static function emptyString() 491 | { 492 | return \Hamcrest\Text\IsEmptyString::isEmptyString(); 493 | } 494 | 495 | /** 496 | * Matches if value is null or a zero-length string. 497 | */ 498 | public static function isEmptyOrNullString() 499 | { 500 | return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); 501 | } 502 | 503 | /** 504 | * Matches if value is null or a zero-length string. 505 | */ 506 | public static function nullOrEmptyString() 507 | { 508 | return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString(); 509 | } 510 | 511 | /** 512 | * Matches if value is a non-zero-length string. 513 | */ 514 | public static function isNonEmptyString() 515 | { 516 | return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); 517 | } 518 | 519 | /** 520 | * Matches if value is a non-zero-length string. 521 | */ 522 | public static function nonEmptyString() 523 | { 524 | return \Hamcrest\Text\IsEmptyString::isNonEmptyString(); 525 | } 526 | 527 | /** 528 | * Matches if value is a string equal to $string, regardless of the case. 529 | */ 530 | public static function equalToIgnoringCase($string) 531 | { 532 | return \Hamcrest\Text\IsEqualIgnoringCase::equalToIgnoringCase($string); 533 | } 534 | 535 | /** 536 | * Matches if value is a string equal to $string, regardless of whitespace. 537 | */ 538 | public static function equalToIgnoringWhiteSpace($string) 539 | { 540 | return \Hamcrest\Text\IsEqualIgnoringWhiteSpace::equalToIgnoringWhiteSpace($string); 541 | } 542 | 543 | /** 544 | * Matches if value is a string that matches regular expression $pattern. 545 | */ 546 | public static function matchesPattern($pattern) 547 | { 548 | return \Hamcrest\Text\MatchesPattern::matchesPattern($pattern); 549 | } 550 | 551 | /** 552 | * Matches if value is a string that contains $substring. 553 | */ 554 | public static function containsString($substring) 555 | { 556 | return \Hamcrest\Text\StringContains::containsString($substring); 557 | } 558 | 559 | /** 560 | * Matches if value is a string that contains $substring regardless of the case. 561 | */ 562 | public static function containsStringIgnoringCase($substring) 563 | { 564 | return \Hamcrest\Text\StringContainsIgnoringCase::containsStringIgnoringCase($substring); 565 | } 566 | 567 | /** 568 | * Matches if value contains $substrings in a constrained order. 569 | */ 570 | public static function stringContainsInOrder(/* args... */) 571 | { 572 | $args = func_get_args(); 573 | return call_user_func_array(array('\Hamcrest\Text\StringContainsInOrder', 'stringContainsInOrder'), $args); 574 | } 575 | 576 | /** 577 | * Matches if value is a string that ends with $substring. 578 | */ 579 | public static function endsWith($substring) 580 | { 581 | return \Hamcrest\Text\StringEndsWith::endsWith($substring); 582 | } 583 | 584 | /** 585 | * Matches if value is a string that starts with $substring. 586 | */ 587 | public static function startsWith($substring) 588 | { 589 | return \Hamcrest\Text\StringStartsWith::startsWith($substring); 590 | } 591 | 592 | /** 593 | * Is the value an array? 594 | */ 595 | public static function arrayValue() 596 | { 597 | return \Hamcrest\Type\IsArray::arrayValue(); 598 | } 599 | 600 | /** 601 | * Is the value a boolean? 602 | */ 603 | public static function booleanValue() 604 | { 605 | return \Hamcrest\Type\IsBoolean::booleanValue(); 606 | } 607 | 608 | /** 609 | * Is the value a boolean? 610 | */ 611 | public static function boolValue() 612 | { 613 | return \Hamcrest\Type\IsBoolean::booleanValue(); 614 | } 615 | 616 | /** 617 | * Is the value callable? 618 | */ 619 | public static function callableValue() 620 | { 621 | return \Hamcrest\Type\IsCallable::callableValue(); 622 | } 623 | 624 | /** 625 | * Is the value a float/double? 626 | */ 627 | public static function doubleValue() 628 | { 629 | return \Hamcrest\Type\IsDouble::doubleValue(); 630 | } 631 | 632 | /** 633 | * Is the value a float/double? 634 | */ 635 | public static function floatValue() 636 | { 637 | return \Hamcrest\Type\IsDouble::doubleValue(); 638 | } 639 | 640 | /** 641 | * Is the value an integer? 642 | */ 643 | public static function integerValue() 644 | { 645 | return \Hamcrest\Type\IsInteger::integerValue(); 646 | } 647 | 648 | /** 649 | * Is the value an integer? 650 | */ 651 | public static function intValue() 652 | { 653 | return \Hamcrest\Type\IsInteger::integerValue(); 654 | } 655 | 656 | /** 657 | * Is the value a numeric? 658 | */ 659 | public static function numericValue() 660 | { 661 | return \Hamcrest\Type\IsNumeric::numericValue(); 662 | } 663 | 664 | /** 665 | * Is the value an object? 666 | */ 667 | public static function objectValue() 668 | { 669 | return \Hamcrest\Type\IsObject::objectValue(); 670 | } 671 | 672 | /** 673 | * Is the value an object? 674 | */ 675 | public static function anObject() 676 | { 677 | return \Hamcrest\Type\IsObject::objectValue(); 678 | } 679 | 680 | /** 681 | * Is the value a resource? 682 | */ 683 | public static function resourceValue() 684 | { 685 | return \Hamcrest\Type\IsResource::resourceValue(); 686 | } 687 | 688 | /** 689 | * Is the value a scalar (boolean, integer, double, or string)? 690 | */ 691 | public static function scalarValue() 692 | { 693 | return \Hamcrest\Type\IsScalar::scalarValue(); 694 | } 695 | 696 | /** 697 | * Is the value a string? 698 | */ 699 | public static function stringValue() 700 | { 701 | return \Hamcrest\Type\IsString::stringValue(); 702 | } 703 | 704 | /** 705 | * Wraps $matcher with {@link Hamcrest\Core\IsEqual) 706 | * if it's not a matcher and the XPath in count() 707 | * if it's an integer. 708 | */ 709 | public static function hasXPath($xpath, $matcher = null) 710 | { 711 | return \Hamcrest\Xml\HasXPath::hasXPath($xpath, $matcher); 712 | } 713 | } 714 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/NullDescription.php: -------------------------------------------------------------------------------- 1 | _value = $value; 25 | $this->_delta = $delta; 26 | } 27 | 28 | protected function matchesSafely($item) 29 | { 30 | return $this->_actualDelta($item) <= 0.0; 31 | } 32 | 33 | protected function describeMismatchSafely($item, Description $mismatchDescription) 34 | { 35 | $mismatchDescription->appendValue($item) 36 | ->appendText(' differed by ') 37 | ->appendValue($this->_actualDelta($item)) 38 | ; 39 | } 40 | 41 | public function describeTo(Description $description) 42 | { 43 | $description->appendText('a numeric value within ') 44 | ->appendValue($this->_delta) 45 | ->appendText(' of ') 46 | ->appendValue($this->_value) 47 | ; 48 | } 49 | 50 | /** 51 | * Matches if value is a number equal to $value within some range of 52 | * acceptable error $delta. 53 | * 54 | * @factory 55 | */ 56 | public static function closeTo($value, $delta) 57 | { 58 | return new self($value, $delta); 59 | } 60 | 61 | // -- Private Methods 62 | 63 | private function _actualDelta($item) 64 | { 65 | return (abs(($item - $this->_value)) - $this->_delta); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Number/OrderingComparison.php: -------------------------------------------------------------------------------- 1 | _value = $value; 23 | $this->_minCompare = $minCompare; 24 | $this->_maxCompare = $maxCompare; 25 | } 26 | 27 | protected function matchesSafely($other) 28 | { 29 | $compare = $this->_compare($this->_value, $other); 30 | 31 | return ($this->_minCompare <= $compare) && ($compare <= $this->_maxCompare); 32 | } 33 | 34 | protected function describeMismatchSafely($item, Description $mismatchDescription) 35 | { 36 | $mismatchDescription 37 | ->appendValue($item)->appendText(' was ') 38 | ->appendText($this->_comparison($this->_compare($this->_value, $item))) 39 | ->appendText(' ')->appendValue($this->_value) 40 | ; 41 | } 42 | 43 | public function describeTo(Description $description) 44 | { 45 | $description->appendText('a value ') 46 | ->appendText($this->_comparison($this->_minCompare)) 47 | ; 48 | if ($this->_minCompare != $this->_maxCompare) { 49 | $description->appendText(' or ') 50 | ->appendText($this->_comparison($this->_maxCompare)) 51 | ; 52 | } 53 | $description->appendText(' ')->appendValue($this->_value); 54 | } 55 | 56 | /** 57 | * The value is not > $value, nor < $value. 58 | * 59 | * @factory 60 | */ 61 | public static function comparesEqualTo($value) 62 | { 63 | return new self($value, 0, 0); 64 | } 65 | 66 | /** 67 | * The value is > $value. 68 | * 69 | * @factory 70 | */ 71 | public static function greaterThan($value) 72 | { 73 | return new self($value, -1, -1); 74 | } 75 | 76 | /** 77 | * The value is >= $value. 78 | * 79 | * @factory atLeast 80 | */ 81 | public static function greaterThanOrEqualTo($value) 82 | { 83 | return new self($value, -1, 0); 84 | } 85 | 86 | /** 87 | * The value is < $value. 88 | * 89 | * @factory 90 | */ 91 | public static function lessThan($value) 92 | { 93 | return new self($value, 1, 1); 94 | } 95 | 96 | /** 97 | * The value is <= $value. 98 | * 99 | * @factory atMost 100 | */ 101 | public static function lessThanOrEqualTo($value) 102 | { 103 | return new self($value, 0, 1); 104 | } 105 | 106 | // -- Private Methods 107 | 108 | private function _compare($left, $right) 109 | { 110 | $a = $left; 111 | $b = $right; 112 | 113 | if ($a < $b) { 114 | return -1; 115 | } elseif ($a == $b) { 116 | return 0; 117 | } else { 118 | return 1; 119 | } 120 | } 121 | 122 | private function _comparison($compare) 123 | { 124 | if ($compare > 0) { 125 | return 'less than'; 126 | } elseif ($compare == 0) { 127 | return 'equal to'; 128 | } else { 129 | return 'greater than'; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/SelfDescribing.php: -------------------------------------------------------------------------------- 1 | _out = (string) $out; 19 | } 20 | 21 | public function __toString() 22 | { 23 | return $this->_out; 24 | } 25 | 26 | /** 27 | * Return the description of a {@link Hamcrest\SelfDescribing} object as a 28 | * String. 29 | * 30 | * @param \Hamcrest\SelfDescribing $selfDescribing 31 | * The object to be described. 32 | * 33 | * @return string 34 | * The description of the object. 35 | */ 36 | public static function toString(SelfDescribing $selfDescribing) 37 | { 38 | $self = new self(); 39 | 40 | return (string) $self->appendDescriptionOf($selfDescribing); 41 | } 42 | 43 | /** 44 | * Alias for {@link toString()}. 45 | */ 46 | public static function asString(SelfDescribing $selfDescribing) 47 | { 48 | return self::toString($selfDescribing); 49 | } 50 | 51 | // -- Protected Methods 52 | 53 | protected function append($str) 54 | { 55 | $this->_out .= $str; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/IsEmptyString.php: -------------------------------------------------------------------------------- 1 | _empty = $empty; 27 | } 28 | 29 | public function matches($item) 30 | { 31 | return $this->_empty 32 | ? ($item === '') 33 | : is_string($item) && $item !== ''; 34 | } 35 | 36 | public function describeTo(Description $description) 37 | { 38 | $description->appendText($this->_empty ? 'an empty string' : 'a non-empty string'); 39 | } 40 | 41 | /** 42 | * Matches if value is a zero-length string. 43 | * 44 | * @factory emptyString 45 | */ 46 | public static function isEmptyString() 47 | { 48 | if (!self::$_INSTANCE) { 49 | self::$_INSTANCE = new self(true); 50 | } 51 | 52 | return self::$_INSTANCE; 53 | } 54 | 55 | /** 56 | * Matches if value is null or a zero-length string. 57 | * 58 | * @factory nullOrEmptyString 59 | */ 60 | public static function isEmptyOrNullString() 61 | { 62 | if (!self::$_NULL_OR_EMPTY_INSTANCE) { 63 | self::$_NULL_OR_EMPTY_INSTANCE = AnyOf::anyOf( 64 | IsNull::nullvalue(), 65 | self::isEmptyString() 66 | ); 67 | } 68 | 69 | return self::$_NULL_OR_EMPTY_INSTANCE; 70 | } 71 | 72 | /** 73 | * Matches if value is a non-zero-length string. 74 | * 75 | * @factory nonEmptyString 76 | */ 77 | public static function isNonEmptyString() 78 | { 79 | if (!self::$_NOT_INSTANCE) { 80 | self::$_NOT_INSTANCE = new self(false); 81 | } 82 | 83 | return self::$_NOT_INSTANCE; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/IsEqualIgnoringCase.php: -------------------------------------------------------------------------------- 1 | _string = $string; 23 | } 24 | 25 | protected function matchesSafely($item) 26 | { 27 | return strtolower($this->_string) === strtolower($item); 28 | } 29 | 30 | protected function describeMismatchSafely($item, Description $mismatchDescription) 31 | { 32 | $mismatchDescription->appendText('was ')->appendText($item); 33 | } 34 | 35 | public function describeTo(Description $description) 36 | { 37 | $description->appendText('equalToIgnoringCase(') 38 | ->appendValue($this->_string) 39 | ->appendText(')') 40 | ; 41 | } 42 | 43 | /** 44 | * Matches if value is a string equal to $string, regardless of the case. 45 | * 46 | * @factory 47 | */ 48 | public static function equalToIgnoringCase($string) 49 | { 50 | return new self($string); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/IsEqualIgnoringWhiteSpace.php: -------------------------------------------------------------------------------- 1 | _string = $string; 24 | } 25 | 26 | protected function matchesSafely($item) 27 | { 28 | return (strtolower($this->_stripSpace($item)) 29 | === strtolower($this->_stripSpace($this->_string))); 30 | } 31 | 32 | protected function describeMismatchSafely($item, Description $mismatchDescription) 33 | { 34 | $mismatchDescription->appendText('was ')->appendText($item); 35 | } 36 | 37 | public function describeTo(Description $description) 38 | { 39 | $description->appendText('equalToIgnoringWhiteSpace(') 40 | ->appendValue($this->_string) 41 | ->appendText(')') 42 | ; 43 | } 44 | 45 | /** 46 | * Matches if value is a string equal to $string, regardless of whitespace. 47 | * 48 | * @factory 49 | */ 50 | public static function equalToIgnoringWhiteSpace($string) 51 | { 52 | return new self($string); 53 | } 54 | 55 | // -- Private Methods 56 | 57 | private function _stripSpace($string) 58 | { 59 | $parts = preg_split("/[\r\n\t ]+/", $string); 60 | foreach ($parts as $i => $part) { 61 | $parts[$i] = trim($part, " \r\n\t"); 62 | } 63 | 64 | return trim(implode(' ', $parts), " \r\n\t"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/MatchesPattern.php: -------------------------------------------------------------------------------- 1 | _substring, (string) $item) >= 1; 34 | } 35 | 36 | protected function relationship() 37 | { 38 | return 'matching'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/StringContains.php: -------------------------------------------------------------------------------- 1 | _substring); 22 | } 23 | 24 | /** 25 | * Matches if value is a string that contains $substring. 26 | * 27 | * @factory 28 | */ 29 | public static function containsString($substring) 30 | { 31 | return new self($substring); 32 | } 33 | 34 | // -- Protected Methods 35 | 36 | protected function evalSubstringOf($item) 37 | { 38 | return (false !== strpos((string) $item, $this->_substring)); 39 | } 40 | 41 | protected function relationship() 42 | { 43 | return 'containing'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/StringContainsIgnoringCase.php: -------------------------------------------------------------------------------- 1 | _substring)); 34 | } 35 | 36 | protected function relationship() 37 | { 38 | return 'containing in any case'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/StringContainsInOrder.php: -------------------------------------------------------------------------------- 1 | _substrings = $substrings; 23 | } 24 | 25 | protected function matchesSafely($item) 26 | { 27 | $fromIndex = 0; 28 | 29 | foreach ($this->_substrings as $substring) { 30 | if (false === $fromIndex = strpos($item, $substring, $fromIndex)) { 31 | return false; 32 | } 33 | } 34 | 35 | return true; 36 | } 37 | 38 | protected function describeMismatchSafely($item, Description $mismatchDescription) 39 | { 40 | $mismatchDescription->appendText('was ')->appendText($item); 41 | } 42 | 43 | public function describeTo(Description $description) 44 | { 45 | $description->appendText('a string containing ') 46 | ->appendValueList('', ', ', '', $this->_substrings) 47 | ->appendText(' in order') 48 | ; 49 | } 50 | 51 | /** 52 | * Matches if value contains $substrings in a constrained order. 53 | * 54 | * @factory ... 55 | */ 56 | public static function stringContainsInOrder(/* args... */) 57 | { 58 | $args = func_get_args(); 59 | 60 | if (isset($args[0]) && is_array($args[0])) { 61 | $args = $args[0]; 62 | } 63 | 64 | return new self($args); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/StringEndsWith.php: -------------------------------------------------------------------------------- 1 | _substring))) === $this->_substring); 34 | } 35 | 36 | protected function relationship() 37 | { 38 | return 'ending with'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/StringStartsWith.php: -------------------------------------------------------------------------------- 1 | _substring)) === $this->_substring); 34 | } 35 | 36 | protected function relationship() 37 | { 38 | return 'starting with'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Text/SubstringMatcher.php: -------------------------------------------------------------------------------- 1 | _substring = $substring; 21 | } 22 | 23 | protected function matchesSafely($item) 24 | { 25 | return $this->evalSubstringOf($item); 26 | } 27 | 28 | protected function describeMismatchSafely($item, Description $mismatchDescription) 29 | { 30 | $mismatchDescription->appendText('was "')->appendText($item)->appendText('"'); 31 | } 32 | 33 | public function describeTo(Description $description) 34 | { 35 | $description->appendText('a string ') 36 | ->appendText($this->relationship()) 37 | ->appendText(' ') 38 | ->appendValue($this->_substring) 39 | ; 40 | } 41 | 42 | abstract protected function evalSubstringOf($string); 43 | 44 | abstract protected function relationship(); 45 | } 46 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Type/IsArray.php: -------------------------------------------------------------------------------- 1 | isHexadecimal($item)) { 23 | return true; 24 | } 25 | 26 | return is_numeric($item); 27 | } 28 | 29 | /** 30 | * Return if the string passed is a valid hexadecimal number. 31 | * This check is necessary because PHP 7 doesn't recognize hexadecimal string as numeric anymore. 32 | * 33 | * @param mixed $item 34 | * @return boolean 35 | */ 36 | private function isHexadecimal($item) 37 | { 38 | if (is_string($item) && preg_match('/^0x(.*)$/', $item, $matches)) { 39 | return ctype_xdigit($matches[1]); 40 | } 41 | 42 | return false; 43 | } 44 | 45 | /** 46 | * Is the value a numeric? 47 | * 48 | * @factory 49 | */ 50 | public static function numericValue() 51 | { 52 | return new self; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Type/IsObject.php: -------------------------------------------------------------------------------- 1 | matchesSafelyWithDiagnosticDescription($item, new NullDescription()); 15 | } 16 | 17 | final public function describeMismatchSafely($item, Description $mismatchDescription) 18 | { 19 | $this->matchesSafelyWithDiagnosticDescription($item, $mismatchDescription); 20 | } 21 | 22 | // -- Protected Methods 23 | 24 | /** 25 | * Subclasses should implement these. The item will already have been checked for 26 | * the specific type. 27 | */ 28 | abstract protected function matchesSafelyWithDiagnosticDescription($item, Description $mismatchDescription); 29 | } 30 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/TypeSafeMatcher.php: -------------------------------------------------------------------------------- 1 | _expectedType = $expectedType; 42 | $this->_expectedSubtype = $expectedSubtype; 43 | } 44 | 45 | final public function matches($item) 46 | { 47 | return $this->_isSafeType($item) && $this->matchesSafely($item); 48 | } 49 | 50 | final public function describeMismatch($item, Description $mismatchDescription) 51 | { 52 | if (!$this->_isSafeType($item)) { 53 | parent::describeMismatch($item, $mismatchDescription); 54 | } else { 55 | $this->describeMismatchSafely($item, $mismatchDescription); 56 | } 57 | } 58 | 59 | // -- Protected Methods 60 | 61 | /** 62 | * The item will already have been checked for the specific type and subtype. 63 | */ 64 | abstract protected function matchesSafely($item); 65 | 66 | /** 67 | * The item will already have been checked for the specific type and subtype. 68 | */ 69 | abstract protected function describeMismatchSafely($item, Description $mismatchDescription); 70 | 71 | // -- Private Methods 72 | 73 | private function _isSafeType($value) 74 | { 75 | switch ($this->_expectedType) { 76 | 77 | case self::TYPE_ANY: 78 | return true; 79 | 80 | case self::TYPE_STRING: 81 | return is_string($value) || is_numeric($value); 82 | 83 | case self::TYPE_NUMERIC: 84 | return is_numeric($value) || is_string($value); 85 | 86 | case self::TYPE_ARRAY: 87 | return is_array($value); 88 | 89 | case self::TYPE_OBJECT: 90 | return is_object($value) 91 | && ($this->_expectedSubtype === null 92 | || $value instanceof $this->_expectedSubtype); 93 | 94 | case self::TYPE_RESOURCE: 95 | return is_resource($value) 96 | && ($this->_expectedSubtype === null 97 | || get_resource_type($value) == $this->_expectedSubtype); 98 | 99 | case self::TYPE_BOOLEAN: 100 | return true; 101 | 102 | default: 103 | return true; 104 | 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Util.php: -------------------------------------------------------------------------------- 1 | all items are 59 | */ 60 | public static function createMatcherArray(array $items) 61 | { 62 | //Extract single array item 63 | if (count($items) == 1 && is_array($items[0])) { 64 | $items = $items[0]; 65 | } 66 | 67 | //Replace non-matchers 68 | foreach ($items as &$item) { 69 | if (!($item instanceof Matcher)) { 70 | $item = Core\IsEqual::equalTo($item); 71 | } 72 | } 73 | 74 | return $items; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /hamcrest/Hamcrest/Xml/HasXPath.php: -------------------------------------------------------------------------------- 1 | _xpath = $xpath; 38 | $this->_matcher = $matcher; 39 | } 40 | 41 | /** 42 | * Matches if the XPath matches against the DOM node and the matcher. 43 | * 44 | * @param string|\DOMNode $actual 45 | * @param Description $mismatchDescription 46 | * @return bool 47 | */ 48 | protected function matchesWithDiagnosticDescription($actual, Description $mismatchDescription) 49 | { 50 | if (is_string($actual)) { 51 | $actual = $this->createDocument($actual); 52 | } elseif (!$actual instanceof \DOMNode) { 53 | $mismatchDescription->appendText('was ')->appendValue($actual); 54 | 55 | return false; 56 | } 57 | $result = $this->evaluate($actual); 58 | if ($result instanceof \DOMNodeList) { 59 | return $this->matchesContent($result, $mismatchDescription); 60 | } else { 61 | return $this->matchesExpression($result, $mismatchDescription); 62 | } 63 | } 64 | 65 | /** 66 | * Creates and returns a DOMDocument from the given 67 | * XML or HTML string. 68 | * 69 | * @param string $text 70 | * @return \DOMDocument built from $text 71 | * @throws \InvalidArgumentException if the document is not valid 72 | */ 73 | protected function createDocument($text) 74 | { 75 | $document = new \DOMDocument(); 76 | if (preg_match('/^\s*<\?xml/', $text)) { 77 | if (!@$document->loadXML($text)) { 78 | throw new \InvalidArgumentException('Must pass a valid XML document'); 79 | } 80 | } else { 81 | if (!@$document->loadHTML($text)) { 82 | throw new \InvalidArgumentException('Must pass a valid HTML or XHTML document'); 83 | } 84 | } 85 | 86 | return $document; 87 | } 88 | 89 | /** 90 | * Applies the configured XPath to the DOM node and returns either 91 | * the result if it's an expression or the node list if it's a query. 92 | * 93 | * @param \DOMNode $node context from which to issue query 94 | * @return mixed result of expression or DOMNodeList from query 95 | */ 96 | protected function evaluate(\DOMNode $node) 97 | { 98 | if ($node instanceof \DOMDocument) { 99 | $xpathDocument = new \DOMXPath($node); 100 | 101 | return $xpathDocument->evaluate($this->_xpath); 102 | } else { 103 | $xpathDocument = new \DOMXPath($node->ownerDocument); 104 | 105 | return $xpathDocument->evaluate($this->_xpath, $node); 106 | } 107 | } 108 | 109 | /** 110 | * Matches if the list of nodes is not empty and the content of at least 111 | * one node matches the configured matcher, if supplied. 112 | * 113 | * @param \DOMNodeList $nodes selected by the XPath query 114 | * @param Description $mismatchDescription 115 | * @return bool 116 | */ 117 | protected function matchesContent(\DOMNodeList $nodes, Description $mismatchDescription) 118 | { 119 | if ($nodes->length == 0) { 120 | $mismatchDescription->appendText('XPath returned no results'); 121 | } elseif ($this->_matcher === null) { 122 | return true; 123 | } else { 124 | foreach ($nodes as $node) { 125 | if ($this->_matcher->matches($node->textContent)) { 126 | return true; 127 | } 128 | } 129 | $content = array(); 130 | foreach ($nodes as $node) { 131 | $content[] = $node->textContent; 132 | } 133 | $mismatchDescription->appendText('XPath returned ') 134 | ->appendValue($content); 135 | } 136 | 137 | return false; 138 | } 139 | 140 | /** 141 | * Matches if the result of the XPath expression matches the configured 142 | * matcher or evaluates to true if there is none. 143 | * 144 | * @param mixed $result result of the XPath expression 145 | * @param Description $mismatchDescription 146 | * @return bool 147 | */ 148 | protected function matchesExpression($result, Description $mismatchDescription) 149 | { 150 | if ($this->_matcher === null) { 151 | if ($result) { 152 | return true; 153 | } 154 | $mismatchDescription->appendText('XPath expression result was ') 155 | ->appendValue($result); 156 | } else { 157 | if ($this->_matcher->matches($result)) { 158 | return true; 159 | } 160 | $mismatchDescription->appendText('XPath expression result '); 161 | $this->_matcher->describeMismatch($result, $mismatchDescription); 162 | } 163 | 164 | return false; 165 | } 166 | 167 | public function describeTo(Description $description) 168 | { 169 | $description->appendText('XML or HTML document with XPath "') 170 | ->appendText($this->_xpath) 171 | ->appendText('"'); 172 | if ($this->_matcher !== null) { 173 | $description->appendText(' '); 174 | $this->_matcher->describeTo($description); 175 | } 176 | } 177 | 178 | /** 179 | * Wraps $matcher with {@link Hamcrest\Core\IsEqual) 180 | * if it's not a matcher and the XPath in count() 181 | * if it's an integer. 182 | * 183 | * @factory 184 | */ 185 | public static function hasXPath($xpath, $matcher = null) 186 | { 187 | if ($matcher === null || $matcher instanceof Matcher) { 188 | return new self($xpath, $matcher); 189 | } elseif (is_int($matcher) && strpos($xpath, 'count(') !== 0) { 190 | $xpath = 'count(' . $xpath . ')'; 191 | } 192 | 193 | return new self($xpath, IsEqual::equalTo($matcher)); 194 | } 195 | } 196 | --------------------------------------------------------------------------------