/home/mip/www/img/credit/datatables/Hamcrest.tar
UtilTest.php000066400000005070151520662040007037 0ustar00<?php
namespace Hamcrest;

class UtilTest extends \PhpUnit_Framework_TestCase
{

    public function testWrapValueWithIsEqualLeavesMatchersUntouched()
    {
        $matcher = new \Hamcrest\Text\MatchesPattern('/fo+/');
        $newMatcher = \Hamcrest\Util::wrapValueWithIsEqual($matcher);
        $this->assertSame($matcher, $newMatcher);
    }

    public function testWrapValueWithIsEqualWrapsPrimitive()
    {
        $matcher = \Hamcrest\Util::wrapValueWithIsEqual('foo');
        $this->assertInstanceOf('Hamcrest\Core\IsEqual', $matcher);
        $this->assertTrue($matcher->matches('foo'));
    }

    public function testCheckAllAreMatchersAcceptsMatchers()
    {
        \Hamcrest\Util::checkAllAreMatchers(array(
            new \Hamcrest\Text\MatchesPattern('/fo+/'),
            new \Hamcrest\Core\IsEqual('foo'),
        ));
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testCheckAllAreMatchersFailsForPrimitive()
    {
        \Hamcrest\Util::checkAllAreMatchers(array(
            new \Hamcrest\Text\MatchesPattern('/fo+/'),
            'foo',
        ));
    }

    private function callAndAssertCreateMatcherArray($items)
    {
        $matchers = \Hamcrest\Util::createMatcherArray($items);
        $this->assertInternalType('array', $matchers);
        $this->assertSameSize($items, $matchers);
        foreach ($matchers as $matcher) {
            $this->assertInstanceOf('\Hamcrest\Matcher', $matcher);
        }

        return $matchers;
    }

    public function testCreateMatcherArrayLeavesMatchersUntouched()
    {
        $matcher = new \Hamcrest\Text\MatchesPattern('/fo+/');
        $items = array($matcher);
        $matchers = $this->callAndAssertCreateMatcherArray($items);
        $this->assertSame($matcher, $matchers[0]);
    }

    public function testCreateMatcherArrayWrapsPrimitiveWithIsEqualMatcher()
    {
        $matchers = $this->callAndAssertCreateMatcherArray(array('foo'));
        $this->assertInstanceOf('Hamcrest\Core\IsEqual', $matchers[0]);
        $this->assertTrue($matchers[0]->matches('foo'));
    }

    public function testCreateMatcherArrayDoesntModifyOriginalArray()
    {
        $items = array('foo');
        $this->callAndAssertCreateMatcherArray($items);
        $this->assertSame('foo', $items[0]);
    }

    public function testCreateMatcherArrayUnwrapsSingleArrayElement()
    {
        $matchers = $this->callAndAssertCreateMatcherArray(array(array('foo')));
        $this->assertInstanceOf('Hamcrest\Core\IsEqual', $matchers[0]);
        $this->assertTrue($matchers[0]->matches('foo'));
    }
}
Core/HasToStringTest.php000066400000004476151520662040011230 0ustar00<?php
namespace Hamcrest\Core;

class PhpForm
{
    public function __toString()
    {
        return 'php';
    }
}

class JavaForm
{
    public function toString()
    {
        return 'java';
    }
}

class BothForms
{
    public function __toString()
    {
        return 'php';
    }

    public function toString()
    {
        return 'java';
    }
}

class HasToStringTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\HasToString::hasToString('foo');
    }

    public function testMatchesWhenToStringMatches()
    {
        $this->assertMatches(
            hasToString(equalTo('php')),
            new \Hamcrest\Core\PhpForm(),
            'correct __toString'
        );
        $this->assertMatches(
            hasToString(equalTo('java')),
            new \Hamcrest\Core\JavaForm(),
            'correct toString'
        );
    }

    public function testPicksJavaOverPhpToString()
    {
        $this->assertMatches(
            hasToString(equalTo('java')),
            new \Hamcrest\Core\BothForms(),
            'correct toString'
        );
    }

    public function testDoesNotMatchWhenToStringDoesNotMatch()
    {
        $this->assertDoesNotMatch(
            hasToString(equalTo('mismatch')),
            new \Hamcrest\Core\PhpForm(),
            'incorrect __toString'
        );
        $this->assertDoesNotMatch(
            hasToString(equalTo('mismatch')),
            new \Hamcrest\Core\JavaForm(),
            'incorrect toString'
        );
        $this->assertDoesNotMatch(
            hasToString(equalTo('mismatch')),
            new \Hamcrest\Core\BothForms(),
            'incorrect __toString'
        );
    }

    public function testDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(
            hasToString(equalTo('a')),
            null,
            'should not match null'
        );
    }

    public function testProvidesConvenientShortcutForTraversableWithSizeEqualTo()
    {
        $this->assertMatches(
            hasToString(equalTo('php')),
            new \Hamcrest\Core\PhpForm(),
            'correct __toString'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            'an object with toString() "php"',
            hasToString(equalTo('php'))
        );
    }
}
Core/AnyOfTest.php000066400000004637151520662040010036 0ustar00<?php
namespace Hamcrest\Core;

class AnyOfTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\AnyOf::anyOf('irrelevant');
    }

    public function testAnyOfEvaluatesToTheLogicalDisjunctionOfTwoOtherMatchers()
    {
        assertThat('good', anyOf('bad', 'good'));
        assertThat('good', anyOf('good', 'good'));
        assertThat('good', anyOf('good', 'bad'));

        assertThat('good', not(anyOf('bad', startsWith('b'))));
    }

    public function testAnyOfEvaluatesToTheLogicalDisjunctionOfManyOtherMatchers()
    {
        assertThat('good', anyOf('bad', 'good', 'bad', 'bad', 'bad'));
        assertThat('good', not(anyOf('bad', 'bad', 'bad', 'bad', 'bad')));
    }

    public function testAnyOfSupportsMixedTypes()
    {
        $combined = anyOf(
            equalTo(new \Hamcrest\Core\SampleBaseClass('good')),
            equalTo(new \Hamcrest\Core\SampleBaseClass('ugly')),
            equalTo(new \Hamcrest\Core\SampleSubClass('good'))
        );

        assertThat(new \Hamcrest\Core\SampleSubClass('good'), $combined);
    }

    public function testAnyOfHasAReadableDescription()
    {
        $this->assertDescription(
            '("good" or "bad" or "ugly")',
            anyOf('good', 'bad', 'ugly')
        );
    }

    public function testNoneOfEvaluatesToTheLogicalDisjunctionOfTwoOtherMatchers()
    {
        assertThat('good', not(noneOf('bad', 'good')));
        assertThat('good', not(noneOf('good', 'good')));
        assertThat('good', not(noneOf('good', 'bad')));

        assertThat('good', noneOf('bad', startsWith('b')));
    }

    public function testNoneOfEvaluatesToTheLogicalDisjunctionOfManyOtherMatchers()
    {
        assertThat('good', not(noneOf('bad', 'good', 'bad', 'bad', 'bad')));
        assertThat('good', noneOf('bad', 'bad', 'bad', 'bad', 'bad'));
    }

    public function testNoneOfSupportsMixedTypes()
    {
        $combined = noneOf(
            equalTo(new \Hamcrest\Core\SampleBaseClass('good')),
            equalTo(new \Hamcrest\Core\SampleBaseClass('ugly')),
            equalTo(new \Hamcrest\Core\SampleSubClass('good'))
        );

        assertThat(new \Hamcrest\Core\SampleSubClass('bad'), $combined);
    }

    public function testNoneOfHasAReadableDescription()
    {
        $this->assertDescription(
            'not ("good" or "bad" or "ugly")',
            noneOf('good', 'bad', 'ugly')
        );
    }
}
Core/SampleBaseClass.php000066400000000347151520662040011156 0ustar00<?php
namespace Hamcrest\Core;

class SampleBaseClass
{

    private $_arg;

    public function __construct($arg)
    {
        $this->_arg = $arg;
    }

    public function __toString()
    {
        return $this->_arg;
    }
}
Core/DescribedAsTest.php000066400000002057151520662040011164 0ustar00<?php
namespace Hamcrest\Core;

class DescribedAsTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\DescribedAs::describedAs('irrelevant', anything());
    }

    public function testOverridesDescriptionOfOtherMatcherWithThatPassedToConstructor()
    {
        $m1 = describedAs('m1 description', anything());
        $m2 = describedAs('m2 description', not(anything()));

        $this->assertDescription('m1 description', $m1);
        $this->assertDescription('m2 description', $m2);
    }

    public function testAppendsValuesToDescription()
    {
        $m = describedAs('value 1 = %0, value 2 = %1', anything(), 33, 97);

        $this->assertDescription('value 1 = <33>, value 2 = <97>', $m);
    }

    public function testDelegatesMatchingToAnotherMatcher()
    {
        $m1 = describedAs('irrelevant', anything());
        $m2 = describedAs('irrelevant', not(anything()));

        $this->assertTrue($m1->matches(new \stdClass()));
        $this->assertFalse($m2->matches('hi'));
    }
}
Core/CombinableMatcherTest.php000066400000003352151520662040012352 0ustar00<?php
namespace Hamcrest\Core;

class CombinableMatcherTest extends \Hamcrest\AbstractMatcherTest
{

    private $_either_3_or_4;
    private $_not_3_and_not_4;

    public function setUp()
    {
        $this->_either_3_or_4 = \Hamcrest\Core\CombinableMatcher::either(equalTo(3))->orElse(equalTo(4));
        $this->_not_3_and_not_4 = \Hamcrest\Core\CombinableMatcher::both(not(equalTo(3)))->andAlso(not(equalTo(4)));
    }

    protected function createMatcher()
    {
        return \Hamcrest\Core\CombinableMatcher::either(equalTo('irrelevant'))->orElse(equalTo('ignored'));
    }

    public function testBothAcceptsAndRejects()
    {
        assertThat(2, $this->_not_3_and_not_4);
        assertThat(3, not($this->_not_3_and_not_4));
    }

    public function testAcceptsAndRejectsThreeAnds()
    {
        $tripleAnd = $this->_not_3_and_not_4->andAlso(equalTo(2));
        assertThat(2, $tripleAnd);
        assertThat(3, not($tripleAnd));
    }

    public function testBothDescribesItself()
    {
        $this->assertEquals('(not <3> and not <4>)', (string) $this->_not_3_and_not_4);
        $this->assertMismatchDescription('was <3>', $this->_not_3_and_not_4, 3);
    }

    public function testEitherAcceptsAndRejects()
    {
        assertThat(3, $this->_either_3_or_4);
        assertThat(6, not($this->_either_3_or_4));
    }

    public function testAcceptsAndRejectsThreeOrs()
    {
        $orTriple = $this->_either_3_or_4->orElse(greaterThan(10));

        assertThat(11, $orTriple);
        assertThat(9, not($orTriple));
    }

    public function testEitherDescribesItself()
    {
        $this->assertEquals('(<3> or <4>)', (string) $this->_either_3_or_4);
        $this->assertMismatchDescription('was <6>', $this->_either_3_or_4, 6);
    }
}
Core/IsCollectionContainingTest.php000066400000005106151520662040013413 0ustar00<?php
namespace Hamcrest\Core;

class IsCollectionContainingTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsCollectionContaining::hasItem(equalTo('irrelevant'));
    }

    public function testMatchesACollectionThatContainsAnElementMatchingTheGivenMatcher()
    {
        $itemMatcher = hasItem(equalTo('a'));

        $this->assertMatches(
            $itemMatcher,
            array('a', 'b', 'c'),
            "should match list that contains 'a'"
        );
    }

    public function testDoesNotMatchCollectionThatDoesntContainAnElementMatchingTheGivenMatcher()
    {
        $matcher1 = hasItem(equalTo('a'));
        $this->assertDoesNotMatch(
            $matcher1,
            array('b', 'c'),
            "should not match list that doesn't contain 'a'"
        );

        $matcher2 = hasItem(equalTo('a'));
        $this->assertDoesNotMatch(
            $matcher2,
            array(),
            'should not match the empty list'
        );
    }

    public function testDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(
            hasItem(equalTo('a')),
            null,
            'should not match null'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a collection containing "a"', hasItem(equalTo('a')));
    }

    public function testMatchesAllItemsInCollection()
    {
        $matcher1 = hasItems(equalTo('a'), equalTo('b'), equalTo('c'));
        $this->assertMatches(
            $matcher1,
            array('a', 'b', 'c'),
            'should match list containing all items'
        );

        $matcher2 = hasItems('a', 'b', 'c');
        $this->assertMatches(
            $matcher2,
            array('a', 'b', 'c'),
            'should match list containing all items (without matchers)'
        );

        $matcher3 = hasItems(equalTo('a'), equalTo('b'), equalTo('c'));
        $this->assertMatches(
            $matcher3,
            array('c', 'b', 'a'),
            'should match list containing all items in any order'
        );

        $matcher4 = hasItems(equalTo('a'), equalTo('b'), equalTo('c'));
        $this->assertMatches(
            $matcher4,
            array('e', 'c', 'b', 'a', 'd'),
            'should match list containing all items plus others'
        );

        $matcher5 = hasItems(equalTo('a'), equalTo('b'), equalTo('c'));
        $this->assertDoesNotMatch(
            $matcher5,
            array('e', 'c', 'b', 'd'), // 'a' missing
            'should not match list unless it contains all items'
        );
    }
}
Core/IsTest.php000066400000002122151520662040007360 0ustar00<?php
namespace Hamcrest\Core;

class IsTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\Is::is('something');
    }

    public function testJustMatchesTheSameWayTheUnderylingMatcherDoes()
    {
        $this->assertMatches(is(equalTo(true)), true, 'should match');
        $this->assertMatches(is(equalTo(false)), false, 'should match');
        $this->assertDoesNotMatch(is(equalTo(true)), false, 'should not match');
        $this->assertDoesNotMatch(is(equalTo(false)), true, 'should not match');
    }

    public function testGeneratesIsPrefixInDescription()
    {
        $this->assertDescription('is <true>', is(equalTo(true)));
    }

    public function testProvidesConvenientShortcutForIsEqualTo()
    {
        $this->assertMatches(is('A'), 'A', 'should match');
        $this->assertMatches(is('B'), 'B', 'should match');
        $this->assertDoesNotMatch(is('A'), 'B', 'should not match');
        $this->assertDoesNotMatch(is('B'), 'A', 'should not match');
        $this->assertDescription('is "A"', is('A'));
    }
}
Core/SampleSubClass.php000066400000000140151520662040011024 0ustar00<?php
namespace Hamcrest\Core;

class SampleSubClass extends \Hamcrest\Core\SampleBaseClass
{
}
Core/IsNullTest.php000066400000000744151520662040010223 0ustar00<?php
namespace Hamcrest\Core;

class IsNullTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsNull::nullValue();
    }

    public function testEvaluatesToTrueIfArgumentIsNull()
    {
        assertThat(null, nullValue());
        assertThat(self::ANY_NON_NULL_ARGUMENT, not(nullValue()));

        assertThat(self::ANY_NON_NULL_ARGUMENT, notNullValue());
        assertThat(null, not(notNullValue()));
    }
}
Core/IsIdenticalTest.php000066400000001401151520662040011174 0ustar00<?php
namespace Hamcrest\Core;

class IsIdenticalTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsIdentical::identicalTo('irrelevant');
    }

    public function testEvaluatesToTrueIfArgumentIsReferenceToASpecifiedObject()
    {
        $o1 = new \stdClass();
        $o2 = new \stdClass();

        assertThat($o1, identicalTo($o1));
        assertThat($o2, not(identicalTo($o1)));
    }

    public function testReturnsReadableDescriptionFromToString()
    {
        $this->assertDescription('"ARG"', identicalTo('ARG'));
    }

    public function testReturnsReadableDescriptionFromToStringWhenInitialisedWithNull()
    {
        $this->assertDescription('null', identicalTo(null));
    }
}
Core/IsNotTest.php000066400000001746151520662040010054 0ustar00<?php
namespace Hamcrest\Core;

class IsNotTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsNot::not('something');
    }

    public function testEvaluatesToTheTheLogicalNegationOfAnotherMatcher()
    {
        $this->assertMatches(not(equalTo('A')), 'B', 'should match');
        $this->assertDoesNotMatch(not(equalTo('B')), 'B', 'should not match');
    }

    public function testProvidesConvenientShortcutForNotEqualTo()
    {
        $this->assertMatches(not('A'), 'B', 'should match');
        $this->assertMatches(not('B'), 'A', 'should match');
        $this->assertDoesNotMatch(not('A'), 'A', 'should not match');
        $this->assertDoesNotMatch(not('B'), 'B', 'should not match');
    }

    public function testUsesDescriptionOfNegatedMatcherWithPrefix()
    {
        $this->assertDescription('not a value greater than <2>', not(greaterThan(2)));
        $this->assertDescription('not "A"', not('A'));
    }
}
Core/IsEqualTest.php000066400000005316151520662040010360 0ustar00<?php
namespace Hamcrest\Core;

class DummyToStringClass
{
    private $_arg;

    public function __construct($arg)
    {
        $this->_arg = $arg;
    }

    public function __toString()
    {
        return $this->_arg;
    }
}

class IsEqualTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsEqual::equalTo('irrelevant');
    }

    public function testComparesObjectsUsingEqualityOperator()
    {
        assertThat("hi", equalTo("hi"));
        assertThat("bye", not(equalTo("hi")));

        assertThat(1, equalTo(1));
        assertThat(1, not(equalTo(2)));

        assertThat("2", equalTo(2));
    }

    public function testCanCompareNullValues()
    {
        assertThat(null, equalTo(null));

        assertThat(null, not(equalTo('hi')));
        assertThat('hi', not(equalTo(null)));
    }

    public function testComparesTheElementsOfAnArray()
    {
        $s1 = array('a', 'b');
        $s2 = array('a', 'b');
        $s3 = array('c', 'd');
        $s4 = array('a', 'b', 'c', 'd');

        assertThat($s1, equalTo($s1));
        assertThat($s2, equalTo($s1));
        assertThat($s3, not(equalTo($s1)));
        assertThat($s4, not(equalTo($s1)));
    }

    public function testComparesTheElementsOfAnArrayOfPrimitiveTypes()
    {
        $i1 = array(1, 2);
        $i2 = array(1, 2);
        $i3 = array(3, 4);
        $i4 = array(1, 2, 3, 4);

        assertThat($i1, equalTo($i1));
        assertThat($i2, equalTo($i1));
        assertThat($i3, not(equalTo($i1)));
        assertThat($i4, not(equalTo($i1)));
    }

    public function testRecursivelyTestsElementsOfArrays()
    {
        $i1 = array(array(1, 2), array(3, 4));
        $i2 = array(array(1, 2), array(3, 4));
        $i3 = array(array(5, 6), array(7, 8));
        $i4 = array(array(1, 2, 3, 4), array(3, 4));

        assertThat($i1, equalTo($i1));
        assertThat($i2, equalTo($i1));
        assertThat($i3, not(equalTo($i1)));
        assertThat($i4, not(equalTo($i1)));
    }

    public function testIncludesTheResultOfCallingToStringOnItsArgumentInTheDescription()
    {
        $argumentDescription = 'ARGUMENT DESCRIPTION';
        $argument = new \Hamcrest\Core\DummyToStringClass($argumentDescription);
        $this->assertDescription('<' . $argumentDescription . '>', equalTo($argument));
    }

    public function testReturnsAnObviousDescriptionIfCreatedWithANestedMatcherByMistake()
    {
        $innerMatcher = equalTo('NestedMatcher');
        $this->assertDescription('<' . (string) $innerMatcher . '>', equalTo($innerMatcher));
    }

    public function testReturnsGoodDescriptionIfCreatedWithNullReference()
    {
        $this->assertDescription('null', equalTo(null));
    }
}
Core/IsSameTest.php000066400000001433151520662040010172 0ustar00<?php
namespace Hamcrest\Core;

class IsSameTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsSame::sameInstance(new \stdClass());
    }

    public function testEvaluatesToTrueIfArgumentIsReferenceToASpecifiedObject()
    {
        $o1 = new \stdClass();
        $o2 = new \stdClass();

        assertThat($o1, sameInstance($o1));
        assertThat($o2, not(sameInstance($o1)));
    }

    public function testReturnsReadableDescriptionFromToString()
    {
        $this->assertDescription('sameInstance("ARG")', sameInstance('ARG'));
    }

    public function testReturnsReadableDescriptionFromToStringWhenInitialisedWithNull()
    {
        $this->assertDescription('sameInstance(null)', sameInstance(null));
    }
}
Core/IsAnythingTest.php000066400000001254151520662040011067 0ustar00<?php
namespace Hamcrest\Core;

class IsAnythingTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsAnything::anything();
    }

    public function testAlwaysEvaluatesToTrue()
    {
        assertThat(null, anything());
        assertThat(new \stdClass(), anything());
        assertThat('hi', anything());
    }

    public function testHasUsefulDefaultDescription()
    {
        $this->assertDescription('ANYTHING', anything());
    }

    public function testCanOverrideDescription()
    {
        $description = 'description';
        $this->assertDescription($description, anything($description));
    }
}
Core/SetTest.php000066400000006176151520662040007555 0ustar00<?php
namespace Hamcrest\Core;

class SetTest extends \Hamcrest\AbstractMatcherTest
{

    public static $_classProperty;
    public $_instanceProperty;

    protected function setUp()
    {
        self::$_classProperty = null;
        unset($this->_instanceProperty);
    }

    protected function createMatcher()
    {
        return \Hamcrest\Core\Set::set('property_name');
    }

    public function testEvaluatesToTrueIfArrayPropertyIsSet()
    {
        assertThat(array('foo' => 'bar'), set('foo'));
    }

    public function testNegatedEvaluatesToFalseIfArrayPropertyIsSet()
    {
        assertThat(array('foo' => 'bar'), not(notSet('foo')));
    }

    public function testEvaluatesToTrueIfClassPropertyIsSet()
    {
        self::$_classProperty = 'bar';
        assertThat('Hamcrest\Core\SetTest', set('_classProperty'));
    }

    public function testNegatedEvaluatesToFalseIfClassPropertyIsSet()
    {
        self::$_classProperty = 'bar';
        assertThat('Hamcrest\Core\SetTest', not(notSet('_classProperty')));
    }

    public function testEvaluatesToTrueIfObjectPropertyIsSet()
    {
        $this->_instanceProperty = 'bar';
        assertThat($this, set('_instanceProperty'));
    }

    public function testNegatedEvaluatesToFalseIfObjectPropertyIsSet()
    {
        $this->_instanceProperty = 'bar';
        assertThat($this, not(notSet('_instanceProperty')));
    }

    public function testEvaluatesToFalseIfArrayPropertyIsNotSet()
    {
        assertThat(array('foo' => 'bar'), not(set('baz')));
    }

    public function testNegatedEvaluatesToTrueIfArrayPropertyIsNotSet()
    {
        assertThat(array('foo' => 'bar'), notSet('baz'));
    }

    public function testEvaluatesToFalseIfClassPropertyIsNotSet()
    {
        assertThat('Hamcrest\Core\SetTest', not(set('_classProperty')));
    }

    public function testNegatedEvaluatesToTrueIfClassPropertyIsNotSet()
    {
        assertThat('Hamcrest\Core\SetTest', notSet('_classProperty'));
    }

    public function testEvaluatesToFalseIfObjectPropertyIsNotSet()
    {
        assertThat($this, not(set('_instanceProperty')));
    }

    public function testNegatedEvaluatesToTrueIfObjectPropertyIsNotSet()
    {
        assertThat($this, notSet('_instanceProperty'));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('set property foo', set('foo'));
        $this->assertDescription('unset property bar', notSet('bar'));
    }

    public function testDecribesPropertySettingInMismatchMessage()
    {
        $this->assertMismatchDescription(
            'was not set',
            set('bar'),
            array('foo' => 'bar')
        );
        $this->assertMismatchDescription(
            'was "bar"',
            notSet('foo'),
            array('foo' => 'bar')
        );
        self::$_classProperty = 'bar';
        $this->assertMismatchDescription(
            'was "bar"',
            notSet('_classProperty'),
            'Hamcrest\Core\SetTest'
        );
        $this->_instanceProperty = 'bar';
        $this->assertMismatchDescription(
            'was "bar"',
            notSet('_instanceProperty'),
            $this
        );
    }
}
Core/IsInstanceOfTest.php000066400000003453151520662040011342 0ustar00<?php
namespace Hamcrest\Core;

class IsInstanceOfTest extends \Hamcrest\AbstractMatcherTest
{

    private $_baseClassInstance;
    private $_subClassInstance;

    public function setUp()
    {
        $this->_baseClassInstance = new \Hamcrest\Core\SampleBaseClass('good');
        $this->_subClassInstance = new \Hamcrest\Core\SampleSubClass('good');
    }

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsInstanceOf::anInstanceOf('stdClass');
    }

    public function testEvaluatesToTrueIfArgumentIsInstanceOfASpecificClass()
    {
        assertThat($this->_baseClassInstance, anInstanceOf('Hamcrest\Core\SampleBaseClass'));
        assertThat($this->_subClassInstance, anInstanceOf('Hamcrest\Core\SampleSubClass'));
        assertThat(null, not(anInstanceOf('Hamcrest\Core\SampleBaseClass')));
        assertThat(new \stdClass(), not(anInstanceOf('Hamcrest\Core\SampleBaseClass')));
    }

    public function testEvaluatesToFalseIfArgumentIsNotAnObject()
    {
        assertThat(null, not(anInstanceOf('Hamcrest\Core\SampleBaseClass')));
        assertThat(false, not(anInstanceOf('Hamcrest\Core\SampleBaseClass')));
        assertThat(5, not(anInstanceOf('Hamcrest\Core\SampleBaseClass')));
        assertThat('foo', not(anInstanceOf('Hamcrest\Core\SampleBaseClass')));
        assertThat(array(1, 2, 3), not(anInstanceOf('Hamcrest\Core\SampleBaseClass')));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('an instance of stdClass', anInstanceOf('stdClass'));
    }

    public function testDecribesActualClassInMismatchMessage()
    {
        $this->assertMismatchDescription(
            '[Hamcrest\Core\SampleBaseClass] <good>',
            anInstanceOf('Hamcrest\Core\SampleSubClass'),
            $this->_baseClassInstance
        );
    }
}
Core/AllOfTest.php000066400000003033151520662040010004 0ustar00<?php
namespace Hamcrest\Core;

class AllOfTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\AllOf::allOf('irrelevant');
    }

    public function testEvaluatesToTheLogicalConjunctionOfTwoOtherMatchers()
    {
        assertThat('good', allOf('good', 'good'));

        assertThat('good', not(allOf('bad', 'good')));
        assertThat('good', not(allOf('good', 'bad')));
        assertThat('good', not(allOf('bad', 'bad')));
    }

    public function testEvaluatesToTheLogicalConjunctionOfManyOtherMatchers()
    {
        assertThat('good', allOf('good', 'good', 'good', 'good', 'good'));
        assertThat('good', not(allOf('good', endsWith('d'), 'bad', 'good', 'good')));
    }

    public function testSupportsMixedTypes()
    {
        $all = allOf(
            equalTo(new \Hamcrest\Core\SampleBaseClass('good')),
            equalTo(new \Hamcrest\Core\SampleBaseClass('good')),
            equalTo(new \Hamcrest\Core\SampleSubClass('ugly'))
        );

        $negated = not($all);

        assertThat(new \Hamcrest\Core\SampleSubClass('good'), $negated);
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            '("good" and "bad" and "ugly")',
            allOf('good', 'bad', 'ugly')
        );
    }

    public function testMismatchDescriptionDescribesFirstFailingMatch()
    {
        $this->assertMismatchDescription(
            '"good" was "bad"',
            allOf('bad', 'good'),
            'bad'
        );
    }
}
Core/EveryTest.php000066400000001502151520662040010100 0ustar00<?php
namespace Hamcrest\Core;

class EveryTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\Every::everyItem(anything());
    }

    public function testIsTrueWhenEveryValueMatches()
    {
        assertThat(array('AaA', 'BaB', 'CaC'), everyItem(containsString('a')));
        assertThat(array('AbA', 'BbB', 'CbC'), not(everyItem(containsString('a'))));
    }

    public function testIsAlwaysTrueForEmptyLists()
    {
        assertThat(array(), everyItem(containsString('a')));
    }

    public function testDescribesItself()
    {
        $each = everyItem(containsString('a'));
        $this->assertEquals('every item is a string containing "a"', (string) $each);

        $this->assertMismatchDescription('an item was "BbB"', $each, array('BbB'));
    }
}
Core/IsTypeOfTest.php000066400000002711151520662040010513 0ustar00<?php
namespace Hamcrest\Core;

class IsTypeOfTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Core\IsTypeOf::typeOf('integer');
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat(array('5', 5), typeOf('array'));
        assertThat(false, typeOf('boolean'));
        assertThat(5, typeOf('integer'));
        assertThat(5.2, typeOf('double'));
        assertThat(null, typeOf('null'));
        assertThat(tmpfile(), typeOf('resource'));
        assertThat('a string', typeOf('string'));
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(typeOf('array')));
        assertThat(array('5', 5), not(typeOf('boolean')));
        assertThat(5.2, not(typeOf('integer')));
        assertThat(5, not(typeOf('double')));
        assertThat(false, not(typeOf('null')));
        assertThat('a string', not(typeOf('resource')));
        assertThat(tmpfile(), not(typeOf('string')));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a double', typeOf('double'));
        $this->assertDescription('an integer', typeOf('integer'));
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', typeOf('boolean'), null);
        $this->assertMismatchDescription('was an integer <5>', typeOf('float'), 5);
    }
}
StringDescriptionTest.php000066400000012505151520662040011575 0ustar00<?php
namespace Hamcrest;

class SampleSelfDescriber implements \Hamcrest\SelfDescribing
{
    private $_text;

    public function __construct($text)
    {
        $this->_text = $text;
    }

    public function describeTo(\Hamcrest\Description $description)
    {
        $description->appendText($this->_text);
    }
}

class StringDescriptionTest extends \PhpUnit_Framework_TestCase
{

    private $_description;

    public function setUp()
    {
        $this->_description = new \Hamcrest\StringDescription();
    }

    public function testAppendTextAppendsTextInformation()
    {
        $this->_description->appendText('foo')->appendText('bar');
        $this->assertEquals('foobar', (string) $this->_description);
    }

    public function testAppendValueCanAppendTextTypes()
    {
        $this->_description->appendValue('foo');
        $this->assertEquals('"foo"', (string) $this->_description);
    }

    public function testSpecialCharactersAreEscapedForStringTypes()
    {
        $this->_description->appendValue("foo\\bar\"zip\r\n");
        $this->assertEquals('"foo\\bar\\"zip\r\n"', (string) $this->_description);
    }

    public function testIntegerValuesCanBeAppended()
    {
        $this->_description->appendValue(42);
        $this->assertEquals('<42>', (string) $this->_description);
    }

    public function testFloatValuesCanBeAppended()
    {
        $this->_description->appendValue(42.78);
        $this->assertEquals('<42.78F>', (string) $this->_description);
    }

    public function testNullValuesCanBeAppended()
    {
        $this->_description->appendValue(null);
        $this->assertEquals('null', (string) $this->_description);
    }

    public function testArraysCanBeAppended()
    {
        $this->_description->appendValue(array('foo', 42.78));
        $this->assertEquals('["foo", <42.78F>]', (string) $this->_description);
    }

    public function testObjectsCanBeAppended()
    {
        $this->_description->appendValue(new \stdClass());
        $this->assertEquals('<stdClass>', (string) $this->_description);
    }

    public function testBooleanValuesCanBeAppended()
    {
        $this->_description->appendValue(false);
        $this->assertEquals('<false>', (string) $this->_description);
    }

    public function testListsOfvaluesCanBeAppended()
    {
        $this->_description->appendValue(array('foo', 42.78));
        $this->assertEquals('["foo", <42.78F>]', (string) $this->_description);
    }

    public function testIterableOfvaluesCanBeAppended()
    {
        $items = new \ArrayObject(array('foo', 42.78));
        $this->_description->appendValue($items);
        $this->assertEquals('["foo", <42.78F>]', (string) $this->_description);
    }

    public function testIteratorOfvaluesCanBeAppended()
    {
        $items = new \ArrayObject(array('foo', 42.78));
        $this->_description->appendValue($items->getIterator());
        $this->assertEquals('["foo", <42.78F>]', (string) $this->_description);
    }

    public function testListsOfvaluesCanBeAppendedManually()
    {
        $this->_description->appendValueList('@start@', '@sep@ ', '@end@', array('foo', 42.78));
        $this->assertEquals('@start@"foo"@sep@ <42.78F>@end@', (string) $this->_description);
    }

    public function testIterableOfvaluesCanBeAppendedManually()
    {
        $items = new \ArrayObject(array('foo', 42.78));
        $this->_description->appendValueList('@start@', '@sep@ ', '@end@', $items);
        $this->assertEquals('@start@"foo"@sep@ <42.78F>@end@', (string) $this->_description);
    }

    public function testIteratorOfvaluesCanBeAppendedManually()
    {
        $items = new \ArrayObject(array('foo', 42.78));
        $this->_description->appendValueList('@start@', '@sep@ ', '@end@', $items->getIterator());
        $this->assertEquals('@start@"foo"@sep@ <42.78F>@end@', (string) $this->_description);
    }

    public function testSelfDescribingObjectsCanBeAppended()
    {
        $this->_description
            ->appendDescriptionOf(new \Hamcrest\SampleSelfDescriber('foo'))
            ->appendDescriptionOf(new \Hamcrest\SampleSelfDescriber('bar'))
            ;
        $this->assertEquals('foobar', (string) $this->_description);
    }

    public function testSelfDescribingObjectsCanBeAppendedAsLists()
    {
        $this->_description->appendList('@start@', '@sep@ ', '@end@', array(
            new \Hamcrest\SampleSelfDescriber('foo'),
            new \Hamcrest\SampleSelfDescriber('bar')
        ));
        $this->assertEquals('@start@foo@sep@ bar@end@', (string) $this->_description);
    }

    public function testSelfDescribingObjectsCanBeAppendedAsIteratedLists()
    {
        $items = new \ArrayObject(array(
            new \Hamcrest\SampleSelfDescriber('foo'),
            new \Hamcrest\SampleSelfDescriber('bar')
        ));
        $this->_description->appendList('@start@', '@sep@ ', '@end@', $items);
        $this->assertEquals('@start@foo@sep@ bar@end@', (string) $this->_description);
    }

    public function testSelfDescribingObjectsCanBeAppendedAsIterators()
    {
        $items = new \ArrayObject(array(
            new \Hamcrest\SampleSelfDescriber('foo'),
            new \Hamcrest\SampleSelfDescriber('bar')
        ));
        $this->_description->appendList('@start@', '@sep@ ', '@end@', $items->getIterator());
        $this->assertEquals('@start@foo@sep@ bar@end@', (string) $this->_description);
    }
}
FeatureMatcherTest.php000066400000003172151520662040011022 0ustar00<?php
namespace Hamcrest;

class Thingy
{
    private $_result;
    public function __construct($result)
    {
        $this->_result = $result;
    }
    public function getResult()
    {
        return $this->_result;
    }
}

/* Test-specific subclass only */
class ResultMatcher extends \Hamcrest\FeatureMatcher
{
    public function __construct()
    {
        parent::__construct(self::TYPE_ANY, null, equalTo('bar'), 'Thingy with result', 'result');
    }
    public function featureValueOf($actual)
    {
        if ($actual instanceof \Hamcrest\Thingy) {
            return $actual->getResult();
        }
    }
}

class FeatureMatcherTest extends \Hamcrest\AbstractMatcherTest
{

    private $_resultMatcher;

    public function setUp()
    {
        $this->_resultMatcher = $this->_resultMatcher();
    }

    protected function createMatcher()
    {
        return $this->_resultMatcher();
    }

    public function testMatchesPartOfAnObject()
    {
        $this->assertMatches($this->_resultMatcher, new \Hamcrest\Thingy('bar'), 'feature');
        $this->assertDescription('Thingy with result "bar"', $this->_resultMatcher);
    }

    public function testMismatchesPartOfAnObject()
    {
        $this->assertMismatchDescription(
            'result was "foo"',
            $this->_resultMatcher,
            new \Hamcrest\Thingy('foo')
        );
    }

    public function testDoesNotGenerateNoticesForNull()
    {
        $this->assertMismatchDescription('result was null', $this->_resultMatcher, null);
    }

    // -- Creation Methods

    private function _resultMatcher()
    {
        return new \Hamcrest\ResultMatcher();
    }
}
Number/OrderingComparisonTest.php000066400000001750151520662040013157 0ustar00<?php
namespace Hamcrest\Number;

class OrderingComparisonTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Number\OrderingComparison::greaterThan(1);
    }

    public function testComparesValuesForGreaterThan()
    {
        assertThat(2, greaterThan(1));
        assertThat(0, not(greaterThan(1)));
    }

    public function testComparesValuesForLessThan()
    {
        assertThat(2, lessThan(3));
        assertThat(0, lessThan(1));
    }

    public function testComparesValuesForEquality()
    {
        assertThat(3, comparesEqualTo(3));
        assertThat('aa', comparesEqualTo('aa'));
    }

    public function testAllowsForInclusiveComparisons()
    {
        assertThat(1, lessThanOrEqualTo(1));
        assertThat(1, greaterThanOrEqualTo(1));
    }

    public function testSupportsDifferentTypesOfComparableValues()
    {
        assertThat(1.1, greaterThan(1.0));
        assertThat("cc", greaterThan("bb"));
    }
}
Number/IsCloseToTest.php000066400000001441151520662040011214 0ustar00<?php
namespace Hamcrest\Number;

class IsCloseToTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        $irrelevant = 0.1;

        return \Hamcrest\Number\IsCloseTo::closeTo($irrelevant, $irrelevant);
    }

    public function testEvaluatesToTrueIfArgumentIsEqualToADoubleValueWithinSomeError()
    {
        $p = closeTo(1.0, 0.5);

        $this->assertTrue($p->matches(1.0));
        $this->assertTrue($p->matches(0.5));
        $this->assertTrue($p->matches(1.5));

        $this->assertDoesNotMatch($p, 2.0, 'too large');
        $this->assertMismatchDescription('<2F> differed by <0.5F>', $p, 2.0);
        $this->assertDoesNotMatch($p, 0.0, 'number too small');
        $this->assertMismatchDescription('<0F> differed by <0.5F>', $p, 0.0);
    }
}
Type/IsBooleanTest.php000066400000001667151520662040010726 0ustar00<?php
namespace Hamcrest\Type;

class IsBooleanTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsBoolean::booleanValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat(false, booleanValue());
        assertThat(true, booleanValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(array(), not(booleanValue()));
        assertThat(5, not(booleanValue()));
        assertThat('foo', not(booleanValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a boolean', booleanValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', booleanValue(), null);
        $this->assertMismatchDescription('was a string "foo"', booleanValue(), 'foo');
    }
}
Type/IsObjectTest.php000066400000001611151520662040010542 0ustar00<?php
namespace Hamcrest\Type;

class IsObjectTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsObject::objectValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat(new \stdClass, objectValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(objectValue()));
        assertThat(5, not(objectValue()));
        assertThat('foo', not(objectValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('an object', objectValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', objectValue(), null);
        $this->assertMismatchDescription('was a string "foo"', objectValue(), 'foo');
    }
}
Type/IsIntegerTest.php000066400000001731151520662040010734 0ustar00<?php
namespace Hamcrest\Type;

class IsIntegerTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsInteger::integerValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat(5, integerValue());
        assertThat(0, integerValue());
        assertThat(-5, integerValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(integerValue()));
        assertThat(5.2, not(integerValue()));
        assertThat('foo', not(integerValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('an integer', integerValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', integerValue(), null);
        $this->assertMismatchDescription('was a string "foo"', integerValue(), 'foo');
    }
}
Type/IsScalarTest.php000066400000002162151520662040010543 0ustar00<?php
namespace Hamcrest\Type;

class IsScalarTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsScalar::scalarValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat(true, scalarValue());
        assertThat(5, scalarValue());
        assertThat(5.3, scalarValue());
        assertThat('5', scalarValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(null, not(scalarValue()));
        assertThat(array(), not(scalarValue()));
        assertThat(array(5), not(scalarValue()));
        assertThat(tmpfile(), not(scalarValue()));
        assertThat(new \stdClass(), not(scalarValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a scalar', scalarValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', scalarValue(), null);
        $this->assertMismatchDescription('was an array ["foo"]', scalarValue(), array('foo'));
    }
}
Type/IsCallableTest.php000066400000005377151520662040011050 0ustar00<?php
namespace Hamcrest\Type;

class IsCallableTest extends \Hamcrest\AbstractMatcherTest
{

    public static function callableFunction()
    {
    }

    public function __invoke()
    {
    }

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsCallable::callableValue();
    }

    public function testEvaluatesToTrueIfArgumentIsFunctionName()
    {
        assertThat('preg_match', callableValue());
    }

    public function testEvaluatesToTrueIfArgumentIsStaticMethodCallback()
    {
        assertThat(
            array('Hamcrest\Type\IsCallableTest', 'callableFunction'),
            callableValue()
        );
    }

    public function testEvaluatesToTrueIfArgumentIsInstanceMethodCallback()
    {
        assertThat(
            array($this, 'testEvaluatesToTrueIfArgumentIsInstanceMethodCallback'),
            callableValue()
        );
    }

    public function testEvaluatesToTrueIfArgumentIsClosure()
    {
        if (!version_compare(PHP_VERSION, '5.3', '>=')) {
            $this->markTestSkipped('Closures require php 5.3');
        }
        eval('assertThat(function () {}, callableValue());');
    }

    public function testEvaluatesToTrueIfArgumentImplementsInvoke()
    {
        if (!version_compare(PHP_VERSION, '5.3', '>=')) {
            $this->markTestSkipped('Magic method __invoke() requires php 5.3');
        }
        assertThat($this, callableValue());
    }

    public function testEvaluatesToFalseIfArgumentIsInvalidFunctionName()
    {
        if (function_exists('not_a_Hamcrest_function')) {
            $this->markTestSkipped('Function "not_a_Hamcrest_function" must not exist');
        }

        assertThat('not_a_Hamcrest_function', not(callableValue()));
    }

    public function testEvaluatesToFalseIfArgumentIsInvalidStaticMethodCallback()
    {
        assertThat(
            array('Hamcrest\Type\IsCallableTest', 'noMethod'),
            not(callableValue())
        );
    }

    public function testEvaluatesToFalseIfArgumentIsInvalidInstanceMethodCallback()
    {
        assertThat(array($this, 'noMethod'), not(callableValue()));
    }

    public function testEvaluatesToFalseIfArgumentDoesntImplementInvoke()
    {
        assertThat(new \stdClass(), not(callableValue()));
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(callableValue()));
        assertThat(5.2, not(callableValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a callable', callableValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription(
            'was a string "invalid-function"',
            callableValue(),
            'invalid-function'
        );
    }
}
Type/IsResourceTest.php000066400000001632151520662040011126 0ustar00<?php
namespace Hamcrest\Type;

class IsResourceTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsResource::resourceValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat(tmpfile(), resourceValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(resourceValue()));
        assertThat(5, not(resourceValue()));
        assertThat('foo', not(resourceValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a resource', resourceValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', resourceValue(), null);
        $this->assertMismatchDescription('was a string "foo"', resourceValue(), 'foo');
    }
}
Type/IsDoubleTest.php000066400000001666151520662040010560 0ustar00<?php
namespace Hamcrest\Type;

class IsDoubleTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsDouble::doubleValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat((float) 5.2, floatValue());
        assertThat((double) 5.3, doubleValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(doubleValue()));
        assertThat(5, not(doubleValue()));
        assertThat('foo', not(doubleValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a double', doubleValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', doubleValue(), null);
        $this->assertMismatchDescription('was a string "foo"', doubleValue(), 'foo');
    }
}
Type/IsStringTest.php000066400000001657151520662040010614 0ustar00<?php
namespace Hamcrest\Type;

class IsStringTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsString::stringValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat('', stringValue());
        assertThat("foo", stringValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(stringValue()));
        assertThat(5, not(stringValue()));
        assertThat(array(1, 2, 3), not(stringValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a string', stringValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', stringValue(), null);
        $this->assertMismatchDescription('was a double <5.2F>', stringValue(), 5.2);
    }
}
Type/IsNumericTest.php000066400000003041151520662040010735 0ustar00<?php
namespace Hamcrest\Type;

class IsNumericTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsNumeric::numericValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat(5, numericValue());
        assertThat(0, numericValue());
        assertThat(-5, numericValue());
        assertThat(5.3, numericValue());
        assertThat(0.53, numericValue());
        assertThat(-5.3, numericValue());
        assertThat('5', numericValue());
        assertThat('0', numericValue());
        assertThat('-5', numericValue());
        assertThat('5.3', numericValue());
        assertThat('5e+3', numericValue());
        assertThat('0.053e-2', numericValue());
        assertThat('-53.253e+25', numericValue());
        assertThat('+53.253e+25', numericValue());
        assertThat('0x4F2a04', numericValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(numericValue()));
        assertThat('foo', not(numericValue()));
        assertThat('foo5', not(numericValue()));
        assertThat('5foo', not(numericValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a number', numericValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', numericValue(), null);
        $this->assertMismatchDescription('was a string "foo"', numericValue(), 'foo');
    }
}
Type/IsArrayTest.php000066400000001651151520662040010416 0ustar00<?php
namespace Hamcrest\Type;

class IsArrayTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Type\IsArray::arrayValue();
    }

    public function testEvaluatesToTrueIfArgumentMatchesType()
    {
        assertThat(array('5', 5), arrayValue());
        assertThat(array(), arrayValue());
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchType()
    {
        assertThat(false, not(arrayValue()));
        assertThat(5, not(arrayValue()));
        assertThat('foo', not(arrayValue()));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('an array', arrayValue());
    }

    public function testDecribesActualTypeInMismatchMessage()
    {
        $this->assertMismatchDescription('was null', arrayValue(), null);
        $this->assertMismatchDescription('was a string "foo"', arrayValue(), 'foo');
    }
}
MatcherAssertTest.php000066400000016257151520662040010700 0ustar00<?php
namespace Hamcrest;

class MatcherAssertTest extends \PhpUnit_Framework_TestCase
{

    protected function setUp()
    {
        \Hamcrest\MatcherAssert::resetCount();
    }

    public function testResetCount()
    {
        \Hamcrest\MatcherAssert::assertThat(true);
        self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
        \Hamcrest\MatcherAssert::resetCount();
        self::assertEquals(0, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
    }

    public function testAssertThatWithTrueArgPasses()
    {
        \Hamcrest\MatcherAssert::assertThat(true);
        \Hamcrest\MatcherAssert::assertThat('non-empty');
        \Hamcrest\MatcherAssert::assertThat(1);
        \Hamcrest\MatcherAssert::assertThat(3.14159);
        \Hamcrest\MatcherAssert::assertThat(array(true));
        self::assertEquals(5, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
    }

    public function testAssertThatWithFalseArgFails()
    {
        try {
            \Hamcrest\MatcherAssert::assertThat(false);
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat(null);
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat('');
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat(0);
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat(0.0);
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat(array());
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('', $ex->getMessage());
        }
        self::assertEquals(6, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
    }

    public function testAssertThatWithIdentifierAndTrueArgPasses()
    {
        \Hamcrest\MatcherAssert::assertThat('identifier', true);
        \Hamcrest\MatcherAssert::assertThat('identifier', 'non-empty');
        \Hamcrest\MatcherAssert::assertThat('identifier', 1);
        \Hamcrest\MatcherAssert::assertThat('identifier', 3.14159);
        \Hamcrest\MatcherAssert::assertThat('identifier', array(true));
        self::assertEquals(5, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
    }

    public function testAssertThatWithIdentifierAndFalseArgFails()
    {
        try {
            \Hamcrest\MatcherAssert::assertThat('identifier', false);
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('identifier', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat('identifier', null);
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('identifier', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat('identifier', '');
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('identifier', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat('identifier', 0);
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('identifier', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat('identifier', 0.0);
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('identifier', $ex->getMessage());
        }
        try {
            \Hamcrest\MatcherAssert::assertThat('identifier', array());
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals('identifier', $ex->getMessage());
        }
        self::assertEquals(6, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
    }

    public function testAssertThatWithActualValueAndMatcherArgsThatMatchPasses()
    {
        \Hamcrest\MatcherAssert::assertThat(true, is(true));
        self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
    }

    public function testAssertThatWithActualValueAndMatcherArgsThatDontMatchFails()
    {
        $expected = 'expected';
        $actual = 'actual';

        $expectedMessage =
            'Expected: "expected"' . PHP_EOL .
            '     but: was "actual"';

        try {
            \Hamcrest\MatcherAssert::assertThat($actual, equalTo($expected));
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals($expectedMessage, $ex->getMessage());
            self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
        }
    }

    public function testAssertThatWithIdentifierAndActualValueAndMatcherArgsThatMatchPasses()
    {
        \Hamcrest\MatcherAssert::assertThat('identifier', true, is(true));
        self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
    }

    public function testAssertThatWithIdentifierAndActualValueAndMatcherArgsThatDontMatchFails()
    {
        $expected = 'expected';
        $actual = 'actual';

        $expectedMessage =
            'identifier' . PHP_EOL .
            'Expected: "expected"' . PHP_EOL .
            '     but: was "actual"';

        try {
            \Hamcrest\MatcherAssert::assertThat('identifier', $actual, equalTo($expected));
            self::fail('expected assertion failure');
        } catch (\Hamcrest\AssertionError $ex) {
            self::assertEquals($expectedMessage, $ex->getMessage());
            self::assertEquals(1, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
        }
    }

    public function testAssertThatWithNoArgsThrowsErrorAndDoesntIncrementCount()
    {
        try {
            \Hamcrest\MatcherAssert::assertThat();
            self::fail('expected invalid argument exception');
        } catch (\InvalidArgumentException $ex) {
            self::assertEquals(0, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
        }
    }

    public function testAssertThatWithFourArgsThrowsErrorAndDoesntIncrementCount()
    {
        try {
            \Hamcrest\MatcherAssert::assertThat(1, 2, 3, 4);
            self::fail('expected invalid argument exception');
        } catch (\InvalidArgumentException $ex) {
            self::assertEquals(0, \Hamcrest\MatcherAssert::getCount(), 'assertion count');
        }
    }
}
Array/IsArrayContainingKeyTest.php000066400000003076151520662040013241 0ustar00<?php
namespace Hamcrest\Arrays;

use Hamcrest\AbstractMatcherTest;

class IsArrayContainingKeyTest extends AbstractMatcherTest
{

    protected function createMatcher()
    {
        return IsArrayContainingKey::hasKeyInArray('irrelevant');
    }

    public function testMatchesSingleElementArrayContainingKey()
    {
        $array = array('a'=>1);

        $this->assertMatches(hasKey('a'), $array, 'Matches single key');
    }

    public function testMatchesArrayContainingKey()
    {
        $array = array('a'=>1, 'b'=>2, 'c'=>3);

        $this->assertMatches(hasKey('a'), $array, 'Matches a');
        $this->assertMatches(hasKey('c'), $array, 'Matches c');
    }

    public function testMatchesArrayContainingKeyWithIntegerKeys()
    {
        $array = array(1=>'A', 2=>'B');

        assertThat($array, hasKey(1));
    }

    public function testMatchesArrayContainingKeyWithNumberKeys()
    {
        $array = array(1=>'A', 2=>'B');

        assertThat($array, hasKey(1));

        // very ugly version!
        assertThat($array, IsArrayContainingKey::hasKeyInArray(2));
    }

    public function testHasReadableDescription()
    {
        $this->assertDescription('array with key "a"', hasKey('a'));
    }

    public function testDoesNotMatchEmptyArray()
    {
        $this->assertMismatchDescription('array was []', hasKey('Foo'), array());
    }

    public function testDoesNotMatchArrayMissingKey()
    {
        $array = array('a'=>1, 'b'=>2, 'c'=>3);

        $this->assertMismatchDescription('array was ["a" => <1>, "b" => <2>, "c" => <3>]', hasKey('d'), $array);
    }
}
Array/IsArrayContainingTest.php000066400000002355151520662040012567 0ustar00<?php
namespace Hamcrest\Arrays;

use Hamcrest\AbstractMatcherTest;

class IsArrayContainingTest extends AbstractMatcherTest
{

    protected function createMatcher()
    {
        return IsArrayContaining::hasItemInArray('irrelevant');
    }

    public function testMatchesAnArrayThatContainsAnElementMatchingTheGivenMatcher()
    {
        $this->assertMatches(
            hasItemInArray('a'),
            array('a', 'b', 'c'),
            "should matches array that contains 'a'"
        );
    }

    public function testDoesNotMatchAnArrayThatDoesntContainAnElementMatchingTheGivenMatcher()
    {
        $this->assertDoesNotMatch(
            hasItemInArray('a'),
            array('b', 'c'),
            "should not matches array that doesn't contain 'a'"
        );
        $this->assertDoesNotMatch(
            hasItemInArray('a'),
            array(),
            'should not match empty array'
        );
    }

    public function testDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(
            hasItemInArray('a'),
            null,
            'should not match null'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('an array containing "a"', hasItemInArray('a'));
    }
}
Array/IsArrayContainingInOrderTest.php000066400000002660151520662040014051 0ustar00<?php
namespace Hamcrest\Arrays;

use Hamcrest\AbstractMatcherTest;

class IsArrayContainingInOrderTest extends AbstractMatcherTest
{

    protected function createMatcher()
    {
        return IsArrayContainingInOrder::arrayContaining(array(1, 2));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('[<1>, <2>]', arrayContaining(array(1, 2)));
    }

    public function testMatchesItemsInOrder()
    {
        $this->assertMatches(arrayContaining(array(1, 2, 3)), array(1, 2, 3), 'in order');
        $this->assertMatches(arrayContaining(array(1)), array(1), 'single');
    }

    public function testAppliesMatchersInOrder()
    {
        $this->assertMatches(
            arrayContaining(array(1, 2, 3)),
            array(1, 2, 3),
            'in order'
        );
        $this->assertMatches(arrayContaining(array(1)), array(1), 'single');
    }

    public function testMismatchesItemsInAnyOrder()
    {
        $matcher = arrayContaining(array(1, 2, 3));
        $this->assertMismatchDescription('was null', $matcher, null);
        $this->assertMismatchDescription('No item matched: <1>', $matcher, array());
        $this->assertMismatchDescription('No item matched: <2>', $matcher, array(1));
        $this->assertMismatchDescription('item with key 0: was <4>', $matcher, array(4, 3, 2, 1));
        $this->assertMismatchDescription('item with key 2: was <4>', $matcher, array(1, 2, 4));
    }
}
Array/IsArrayContainingInAnyOrderTest.php000066400000003274151520662040014523 0ustar00<?php
namespace Hamcrest\Arrays;

use Hamcrest\AbstractMatcherTest;

class IsArrayContainingInAnyOrderTest extends AbstractMatcherTest
{

    protected function createMatcher()
    {
        return IsArrayContainingInAnyOrder::arrayContainingInAnyOrder(array(1, 2));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('[<1>, <2>] in any order', containsInAnyOrder(array(1, 2)));
    }

    public function testMatchesItemsInAnyOrder()
    {
        $this->assertMatches(containsInAnyOrder(array(1, 2, 3)), array(1, 2, 3), 'in order');
        $this->assertMatches(containsInAnyOrder(array(1, 2, 3)), array(3, 2, 1), 'out of order');
        $this->assertMatches(containsInAnyOrder(array(1)), array(1), 'single');
    }

    public function testAppliesMatchersInAnyOrder()
    {
        $this->assertMatches(
            containsInAnyOrder(array(1, 2, 3)),
            array(1, 2, 3),
            'in order'
        );
        $this->assertMatches(
            containsInAnyOrder(array(1, 2, 3)),
            array(3, 2, 1),
            'out of order'
        );
        $this->assertMatches(
            containsInAnyOrder(array(1)),
            array(1),
            'single'
        );
    }

    public function testMismatchesItemsInAnyOrder()
    {
        $matcher = containsInAnyOrder(array(1, 2, 3));

        $this->assertMismatchDescription('was null', $matcher, null);
        $this->assertMismatchDescription('No item matches: <1>, <2>, <3> in []', $matcher, array());
        $this->assertMismatchDescription('No item matches: <2>, <3> in [<1>]', $matcher, array(1));
        $this->assertMismatchDescription('Not matched: <4>', $matcher, array(4, 3, 2, 1));
    }
}
Array/IsArrayWithSizeTest.php000066400000002203151520662040012234 0ustar00<?php
namespace Hamcrest\Arrays;

use Hamcrest\AbstractMatcherTest;

class IsArrayWithSizeTest extends AbstractMatcherTest
{

    protected function createMatcher()
    {
        return IsArrayWithSize::arrayWithSize(equalTo(2));
    }

    public function testMatchesWhenSizeIsCorrect()
    {
        $this->assertMatches(arrayWithSize(equalTo(3)), array(1, 2, 3), 'correct size');
        $this->assertDoesNotMatch(arrayWithSize(equalTo(2)), array(1, 2, 3), 'incorrect size');
    }

    public function testProvidesConvenientShortcutForArrayWithSizeEqualTo()
    {
        $this->assertMatches(arrayWithSize(3), array(1, 2, 3), 'correct size');
        $this->assertDoesNotMatch(arrayWithSize(2), array(1, 2, 3), 'incorrect size');
    }

    public function testEmptyArray()
    {
        $this->assertMatches(emptyArray(), array(), 'correct size');
        $this->assertDoesNotMatch(emptyArray(), array(1), 'incorrect size');
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('an array with size <3>', arrayWithSize(equalTo(3)));
        $this->assertDescription('an empty array', emptyArray());
    }
}
Array/IsArrayContainingKeyValuePairTest.php000066400000002112151520662040015040 0ustar00<?php
namespace Hamcrest\Arrays;

use Hamcrest\AbstractMatcherTest;

class IsArrayContainingKeyValuePairTest extends AbstractMatcherTest
{

    protected function createMatcher()
    {
        return IsArrayContainingKeyValuePair::hasKeyValuePair('irrelevant', 'irrelevant');
    }

    public function testMatchesArrayContainingMatchingKeyAndValue()
    {
        $array = array('a'=>1, 'b'=>2);

        $this->assertMatches(hasKeyValuePair(equalTo('a'), equalTo(1)), $array, 'matcherA');
        $this->assertMatches(hasKeyValuePair(equalTo('b'), equalTo(2)), $array, 'matcherB');
        $this->assertMismatchDescription(
            'array was ["a" => <1>, "b" => <2>]',
            hasKeyValuePair(equalTo('c'), equalTo(3)),
            $array
        );
    }

    public function testDoesNotMatchNull()
    {
        $this->assertMismatchDescription('was null', hasKeyValuePair(anything(), anything()), null);
    }

    public function testHasReadableDescription()
    {
        $this->assertDescription('array containing ["a" => <2>]', hasKeyValuePair(equalTo('a'), equalTo(2)));
    }
}
Array/IsArrayTest.php000066400000004676151520662040010565 0ustar00<?php
namespace Hamcrest\Arrays;

use Hamcrest\AbstractMatcherTest;

class IsArrayTest extends AbstractMatcherTest
{

    protected function createMatcher()
    {
        return IsArray::anArray(array(equalTo('irrelevant')));
    }

    public function testMatchesAnArrayThatMatchesAllTheElementMatchers()
    {
        $this->assertMatches(
            anArray(array(equalTo('a'), equalTo('b'), equalTo('c'))),
            array('a', 'b', 'c'),
            'should match array with matching elements'
        );
    }

    public function testDoesNotMatchAnArrayWhenElementsDoNotMatch()
    {
        $this->assertDoesNotMatch(
            anArray(array(equalTo('a'), equalTo('b'))),
            array('b', 'c'),
            'should not match array with different elements'
        );
    }

    public function testDoesNotMatchAnArrayOfDifferentSize()
    {
        $this->assertDoesNotMatch(
            anArray(array(equalTo('a'), equalTo('b'))),
            array('a', 'b', 'c'),
            'should not match larger array'
        );
        $this->assertDoesNotMatch(
            anArray(array(equalTo('a'), equalTo('b'))),
            array('a'),
            'should not match smaller array'
        );
    }

    public function testDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(
            anArray(array(equalTo('a'))),
            null,
            'should not match null'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            '["a", "b"]',
            anArray(array(equalTo('a'), equalTo('b')))
        );
    }

    public function testHasAReadableMismatchDescriptionWhenKeysDontMatch()
    {
        $this->assertMismatchDescription(
            'array keys were [<1>, <2>]',
            anArray(array(equalTo('a'), equalTo('b'))),
            array(1 => 'a', 2 => 'b')
        );
    }

    public function testSupportsMatchesAssociativeArrays()
    {
        $this->assertMatches(
            anArray(array('x'=>equalTo('a'), 'y'=>equalTo('b'), 'z'=>equalTo('c'))),
            array('x'=>'a', 'y'=>'b', 'z'=>'c'),
            'should match associative array with matching elements'
        );
    }

    public function testDoesNotMatchAnAssociativeArrayWhenKeysDoNotMatch()
    {
        $this->assertDoesNotMatch(
            anArray(array('x'=>equalTo('a'), 'y'=>equalTo('b'))),
            array('x'=>'b', 'z'=>'c'),
            'should not match array with different keys'
        );
    }
}
Collection/IsEmptyTraversableTest.php000066400000003513151520662040014002 0ustar00<?php
namespace Hamcrest\Collection;

use Hamcrest\AbstractMatcherTest;

class IsEmptyTraversableTest extends AbstractMatcherTest
{

    protected function createMatcher()
    {
        return IsEmptyTraversable::emptyTraversable();
    }

    public function testEmptyMatcherMatchesWhenEmpty()
    {
        $this->assertMatches(
            emptyTraversable(),
            new \ArrayObject(array()),
            'an empty traversable'
        );
    }

    public function testEmptyMatcherDoesNotMatchWhenNotEmpty()
    {
        $this->assertDoesNotMatch(
            emptyTraversable(),
            new \ArrayObject(array(1, 2, 3)),
            'a non-empty traversable'
        );
    }

    public function testEmptyMatcherDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(
            emptyTraversable(),
            null,
            'should not match null'
        );
    }

    public function testEmptyMatcherHasAReadableDescription()
    {
        $this->assertDescription('an empty traversable', emptyTraversable());
    }

    public function testNonEmptyDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(
            nonEmptyTraversable(),
            null,
            'should not match null'
        );
    }

    public function testNonEmptyDoesNotMatchWhenEmpty()
    {
        $this->assertDoesNotMatch(
            nonEmptyTraversable(),
            new \ArrayObject(array()),
            'an empty traversable'
        );
    }

    public function testNonEmptyMatchesWhenNotEmpty()
    {
        $this->assertMatches(
            nonEmptyTraversable(),
            new \ArrayObject(array(1, 2, 3)),
            'a non-empty traversable'
        );
    }

    public function testNonEmptyNonEmptyMatcherHasAReadableDescription()
    {
        $this->assertDescription('a non-empty traversable', nonEmptyTraversable());
    }
}
Collection/IsTraversableWithSizeTest.php000066400000002532151520662040014452 0ustar00<?php
namespace Hamcrest\Collection;

class IsTraversableWithSizeTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Collection\IsTraversableWithSize::traversableWithSize(
            equalTo(2)
        );
    }

    public function testMatchesWhenSizeIsCorrect()
    {
        $this->assertMatches(
            traversableWithSize(equalTo(3)),
            new \ArrayObject(array(1, 2, 3)),
            'correct size'
        );
    }

    public function testDoesNotMatchWhenSizeIsIncorrect()
    {
        $this->assertDoesNotMatch(
            traversableWithSize(equalTo(2)),
            new \ArrayObject(array(1, 2, 3)),
            'incorrect size'
        );
    }

    public function testDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(
            traversableWithSize(3),
            null,
            'should not match null'
        );
    }

    public function testProvidesConvenientShortcutForTraversableWithSizeEqualTo()
    {
        $this->assertMatches(
            traversableWithSize(3),
            new \ArrayObject(array(1, 2, 3)),
            'correct size'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            'a traversable with size <3>',
            traversableWithSize(equalTo(3))
        );
    }
}
AbstractMatcherTest.php000066400000003561151520662040011174 0ustar00<?php
namespace Hamcrest;

class UnknownType {
}

abstract class AbstractMatcherTest extends \PHPUnit_Framework_TestCase
{

    const ARGUMENT_IGNORED = "ignored";
    const ANY_NON_NULL_ARGUMENT = "notnull";

    abstract protected function createMatcher();

    public function assertMatches(\Hamcrest\Matcher $matcher, $arg, $message)
    {
        $this->assertTrue($matcher->matches($arg), $message);
    }

    public function assertDoesNotMatch(\Hamcrest\Matcher $matcher, $arg, $message)
    {
        $this->assertFalse($matcher->matches($arg), $message);
    }

    public function assertDescription($expected, \Hamcrest\Matcher $matcher)
    {
        $description = new \Hamcrest\StringDescription();
        $description->appendDescriptionOf($matcher);
        $this->assertEquals($expected, (string) $description, 'Expected description');
    }

    public function assertMismatchDescription($expected, \Hamcrest\Matcher $matcher, $arg)
    {
        $description = new \Hamcrest\StringDescription();
        $this->assertFalse(
            $matcher->matches($arg),
            'Precondtion: Matcher should not match item'
        );
        $matcher->describeMismatch($arg, $description);
        $this->assertEquals(
            $expected,
            (string) $description,
            'Expected mismatch description'
        );
    }

    public function testIsNullSafe()
    {
        //Should not generate any notices
        $this->createMatcher()->matches(null);
        $this->createMatcher()->describeMismatch(
            null,
            new \Hamcrest\NullDescription()
        );
    }

    public function testCopesWithUnknownTypes()
    {
        //Should not generate any notices
        $this->createMatcher()->matches(new UnknownType());
        $this->createMatcher()->describeMismatch(
            new UnknownType(),
            new NullDescription()
        );
    }
}
BaseMatcherTest.php000066400000001027151520662040010276 0ustar00<?php
namespace Hamcrest;

/* Test-specific subclass only */
class BaseMatcherTest extends \Hamcrest\BaseMatcher
{

    public function matches($item)
    {
        throw new \RuntimeException();
    }

    public function describeTo(\Hamcrest\Description $description)
    {
        $description->appendText('SOME DESCRIPTION');
    }

    public function testDescribesItselfWithToStringMethod()
    {
        $someMatcher = new \Hamcrest\SomeMatcher();
        $this->assertEquals('SOME DESCRIPTION', (string) $someMatcher);
    }
}
Text/MatchesPatternTest.php000066400000001533151520662040011770 0ustar00<?php
namespace Hamcrest\Text;

class MatchesPatternTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return matchesPattern('/o+b/');
    }

    public function testEvaluatesToTrueIfArgumentmatchesPattern()
    {
        assertThat('foobar', matchesPattern('/o+b/'));
        assertThat('foobar', matchesPattern('/^foo/'));
        assertThat('foobar', matchesPattern('/ba*r$/'));
        assertThat('foobar', matchesPattern('/^foobar$/'));
    }

    public function testEvaluatesToFalseIfArgumentDoesntMatchRegex()
    {
        assertThat('foobar', not(matchesPattern('/^foob$/')));
        assertThat('foobar', not(matchesPattern('/oobe/')));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a string matching "pattern"', matchesPattern('pattern'));
    }
}
Text/StringContainsIgnoringCaseTest.php000066400000004666151520662040014316 0ustar00<?php
namespace Hamcrest\Text;

class StringContainsIgnoringCaseTest extends \Hamcrest\AbstractMatcherTest
{

    const EXCERPT = 'ExcErPt';

    private $_stringContains;

    public function setUp()
    {
        $this->_stringContains = \Hamcrest\Text\StringContainsIgnoringCase::containsStringIgnoringCase(
            strtolower(self::EXCERPT)
        );
    }

    protected function createMatcher()
    {
        return $this->_stringContains;
    }

    public function testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring()
    {
        $this->assertTrue(
            $this->_stringContains->matches(self::EXCERPT . 'END'),
            'should be true if excerpt at beginning'
        );
        $this->assertTrue(
            $this->_stringContains->matches('START' . self::EXCERPT),
            'should be true if excerpt at end'
        );
        $this->assertTrue(
            $this->_stringContains->matches('START' . self::EXCERPT . 'END'),
            'should be true if excerpt in middle'
        );
        $this->assertTrue(
            $this->_stringContains->matches(self::EXCERPT . self::EXCERPT),
            'should be true if excerpt is repeated'
        );

        $this->assertFalse(
            $this->_stringContains->matches('Something else'),
            'should not be true if excerpt is not in string'
        );
        $this->assertFalse(
            $this->_stringContains->matches(substr(self::EXCERPT, 1)),
            'should not be true if part of excerpt is in string'
        );
    }

    public function testEvaluatesToTrueIfArgumentIsEqualToSubstring()
    {
        $this->assertTrue(
            $this->_stringContains->matches(self::EXCERPT),
            'should be true if excerpt is entire string'
        );
    }

    public function testEvaluatesToTrueIfArgumentContainsExactSubstring()
    {
        $this->assertTrue(
            $this->_stringContains->matches(strtolower(self::EXCERPT)),
            'should be false if excerpt is entire string ignoring case'
        );
        $this->assertTrue(
            $this->_stringContains->matches('START' . strtolower(self::EXCERPT) . 'END'),
            'should be false if excerpt is contained in string ignoring case'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            'a string containing in any case "'
            . strtolower(self::EXCERPT) . '"',
            $this->_stringContains
        );
    }
}
Text/StringContainsInOrderTest.php000066400000002344151520662040013277 0ustar00<?php
namespace Hamcrest\Text;

class StringContainsInOrderTest extends \Hamcrest\AbstractMatcherTest
{

    private $_m;

    public function setUp()
    {
        $this->_m = \Hamcrest\Text\StringContainsInOrder::stringContainsInOrder(array('a', 'b', 'c'));
    }

    protected function createMatcher()
    {
        return $this->_m;
    }

    public function testMatchesOnlyIfStringContainsGivenSubstringsInTheSameOrder()
    {
        $this->assertMatches($this->_m, 'abc', 'substrings in order');
        $this->assertMatches($this->_m, '1a2b3c4', 'substrings separated');

        $this->assertDoesNotMatch($this->_m, 'cab', 'substrings out of order');
        $this->assertDoesNotMatch($this->_m, 'xyz', 'no substrings in string');
        $this->assertDoesNotMatch($this->_m, 'ac', 'substring missing');
        $this->assertDoesNotMatch($this->_m, '', 'empty string');
    }

    public function testAcceptsVariableArguments()
    {
        $this->assertMatches(stringContainsInOrder('a', 'b', 'c'), 'abc', 'substrings as variable arguments');
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            'a string containing "a", "b", "c" in order',
            $this->_m
        );
    }
}
Text/StringEndsWithTest.php000066400000003547151520662040011771 0ustar00<?php
namespace Hamcrest\Text;

class StringEndsWithTest extends \Hamcrest\AbstractMatcherTest
{

    const EXCERPT = 'EXCERPT';

    private $_stringEndsWith;

    public function setUp()
    {
        $this->_stringEndsWith = \Hamcrest\Text\StringEndsWith::endsWith(self::EXCERPT);
    }

    protected function createMatcher()
    {
        return $this->_stringEndsWith;
    }

    public function testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring()
    {
        $this->assertFalse(
            $this->_stringEndsWith->matches(self::EXCERPT . 'END'),
            'should be false if excerpt at beginning'
        );
        $this->assertTrue(
            $this->_stringEndsWith->matches('START' . self::EXCERPT),
            'should be true if excerpt at end'
        );
        $this->assertFalse(
            $this->_stringEndsWith->matches('START' . self::EXCERPT . 'END'),
            'should be false if excerpt in middle'
        );
        $this->assertTrue(
            $this->_stringEndsWith->matches(self::EXCERPT . self::EXCERPT),
            'should be true if excerpt is at end and repeated'
        );

        $this->assertFalse(
            $this->_stringEndsWith->matches('Something else'),
            'should be false if excerpt is not in string'
        );
        $this->assertFalse(
            $this->_stringEndsWith->matches(substr(self::EXCERPT, 0, strlen(self::EXCERPT) - 2)),
            'should be false if part of excerpt is at end of string'
        );
    }

    public function testEvaluatesToTrueIfArgumentIsEqualToSubstring()
    {
        $this->assertTrue(
            $this->_stringEndsWith->matches(self::EXCERPT),
            'should be true if excerpt is entire string'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a string ending with "EXCERPT"', $this->_stringEndsWith);
    }
}
Text/StringStartsWithTest.php000066400000003562151520662040012355 0ustar00<?php
namespace Hamcrest\Text;

class StringStartsWithTest extends \Hamcrest\AbstractMatcherTest
{

    const EXCERPT = 'EXCERPT';

    private $_stringStartsWith;

    public function setUp()
    {
        $this->_stringStartsWith = \Hamcrest\Text\StringStartsWith::startsWith(self::EXCERPT);
    }

    protected function createMatcher()
    {
        return $this->_stringStartsWith;
    }

    public function testEvaluatesToTrueIfArgumentContainsSpecifiedSubstring()
    {
        $this->assertTrue(
            $this->_stringStartsWith->matches(self::EXCERPT . 'END'),
            'should be true if excerpt at beginning'
        );
        $this->assertFalse(
            $this->_stringStartsWith->matches('START' . self::EXCERPT),
            'should be false if excerpt at end'
        );
        $this->assertFalse(
            $this->_stringStartsWith->matches('START' . self::EXCERPT . 'END'),
            'should be false if excerpt in middle'
        );
        $this->assertTrue(
            $this->_stringStartsWith->matches(self::EXCERPT . self::EXCERPT),
            'should be true if excerpt is at beginning and repeated'
        );

        $this->assertFalse(
            $this->_stringStartsWith->matches('Something else'),
            'should be false if excerpt is not in string'
        );
        $this->assertFalse(
            $this->_stringStartsWith->matches(substr(self::EXCERPT, 1)),
            'should be false if part of excerpt is at start of string'
        );
    }

    public function testEvaluatesToTrueIfArgumentIsEqualToSubstring()
    {
        $this->assertTrue(
            $this->_stringStartsWith->matches(self::EXCERPT),
            'should be true if excerpt is entire string'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription('a string starting with "EXCERPT"', $this->_stringStartsWith);
    }
}
Text/IsEmptyStringTest.php000066400000004367151520662040011637 0ustar00<?php
namespace Hamcrest\Text;

class IsEmptyStringTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Text\IsEmptyString::isEmptyOrNullString();
    }

    public function testEmptyDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(emptyString(), null, 'null');
    }

    public function testEmptyDoesNotMatchZero()
    {
        $this->assertDoesNotMatch(emptyString(), 0, 'zero');
    }

    public function testEmptyDoesNotMatchFalse()
    {
        $this->assertDoesNotMatch(emptyString(), false, 'false');
    }

    public function testEmptyDoesNotMatchEmptyArray()
    {
        $this->assertDoesNotMatch(emptyString(), array(), 'empty array');
    }

    public function testEmptyMatchesEmptyString()
    {
        $this->assertMatches(emptyString(), '', 'empty string');
    }

    public function testEmptyDoesNotMatchNonEmptyString()
    {
        $this->assertDoesNotMatch(emptyString(), 'foo', 'non-empty string');
    }

    public function testEmptyHasAReadableDescription()
    {
        $this->assertDescription('an empty string', emptyString());
    }

    public function testEmptyOrNullMatchesNull()
    {
        $this->assertMatches(nullOrEmptyString(), null, 'null');
    }

    public function testEmptyOrNullMatchesEmptyString()
    {
        $this->assertMatches(nullOrEmptyString(), '', 'empty string');
    }

    public function testEmptyOrNullDoesNotMatchNonEmptyString()
    {
        $this->assertDoesNotMatch(nullOrEmptyString(), 'foo', 'non-empty string');
    }

    public function testEmptyOrNullHasAReadableDescription()
    {
        $this->assertDescription('(null or an empty string)', nullOrEmptyString());
    }

    public function testNonEmptyDoesNotMatchNull()
    {
        $this->assertDoesNotMatch(nonEmptyString(), null, 'null');
    }

    public function testNonEmptyDoesNotMatchEmptyString()
    {
        $this->assertDoesNotMatch(nonEmptyString(), '', 'empty string');
    }

    public function testNonEmptyMatchesNonEmptyString()
    {
        $this->assertMatches(nonEmptyString(), 'foo', 'non-empty string');
    }

    public function testNonEmptyHasAReadableDescription()
    {
        $this->assertDescription('a non-empty string', nonEmptyString());
    }
}
Text/IsEqualIgnoringCaseTest.php000066400000002174151520662040012704 0ustar00<?php
namespace Hamcrest\Text;

class IsEqualIgnoringCaseTest extends \Hamcrest\AbstractMatcherTest
{

    protected function createMatcher()
    {
        return \Hamcrest\Text\IsEqualIgnoringCase::equalToIgnoringCase('irrelevant');
    }

    public function testIgnoresCaseOfCharsInString()
    {
        assertThat('HELLO', equalToIgnoringCase('heLLo'));
        assertThat('hello', equalToIgnoringCase('heLLo'));
        assertThat('HelLo', equalToIgnoringCase('heLLo'));

        assertThat('bye', not(equalToIgnoringCase('heLLo')));
    }

    public function testFailsIfAdditionalWhitespaceIsPresent()
    {
        assertThat('heLLo ', not(equalToIgnoringCase('heLLo')));
        assertThat(' heLLo', not(equalToIgnoringCase('heLLo')));
        assertThat('hello', not(equalToIgnoringCase(' heLLo')));
    }

    public function testFailsIfMatchingAgainstNull()
    {
        assertThat(null, not(equalToIgnoringCase('heLLo')));
    }

    public function testDescribesItselfAsCaseInsensitive()
    {
        $this->assertDescription(
            'equalToIgnoringCase("heLLo")',
            equalToIgnoringCase('heLLo')
        );
    }
}
Text/StringContainsTest.php000066400000005127151520662040012016 0ustar00<?php
namespace Hamcrest\Text;

class StringContainsTest extends \Hamcrest\AbstractMatcherTest
{

    const EXCERPT = 'EXCERPT';

    private $_stringContains;

    public function setUp()
    {
        $this->_stringContains = \Hamcrest\Text\StringContains::containsString(self::EXCERPT);
    }

    protected function createMatcher()
    {
        return $this->_stringContains;
    }

    public function testEvaluatesToTrueIfArgumentContainsSubstring()
    {
        $this->assertTrue(
            $this->_stringContains->matches(self::EXCERPT . 'END'),
            'should be true if excerpt at beginning'
        );
        $this->assertTrue(
            $this->_stringContains->matches('START' . self::EXCERPT),
            'should be true if excerpt at end'
        );
        $this->assertTrue(
            $this->_stringContains->matches('START' . self::EXCERPT . 'END'),
            'should be true if excerpt in middle'
        );
        $this->assertTrue(
            $this->_stringContains->matches(self::EXCERPT . self::EXCERPT),
            'should be true if excerpt is repeated'
        );

        $this->assertFalse(
            $this->_stringContains->matches('Something else'),
            'should not be true if excerpt is not in string'
        );
        $this->assertFalse(
            $this->_stringContains->matches(substr(self::EXCERPT, 1)),
            'should not be true if part of excerpt is in string'
        );
    }

    public function testEvaluatesToTrueIfArgumentIsEqualToSubstring()
    {
        $this->assertTrue(
            $this->_stringContains->matches(self::EXCERPT),
            'should be true if excerpt is entire string'
        );
    }

    public function testEvaluatesToFalseIfArgumentContainsSubstringIgnoringCase()
    {
        $this->assertFalse(
            $this->_stringContains->matches(strtolower(self::EXCERPT)),
            'should be false if excerpt is entire string ignoring case'
        );
        $this->assertFalse(
            $this->_stringContains->matches('START' . strtolower(self::EXCERPT) . 'END'),
            'should be false if excerpt is contained in string ignoring case'
        );
    }

    public function testIgnoringCaseReturnsCorrectMatcher()
    {
        $this->assertTrue(
            $this->_stringContains->ignoringCase()->matches('EXceRpT'),
            'should be true if excerpt is entire string ignoring case'
        );
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            'a string containing "'
            . self::EXCERPT . '"',
            $this->_stringContains
        );
    }
}
Text/IsEqualIgnoringWhiteSpaceTest.php000066400000002553151520662040014066 0ustar00<?php
namespace Hamcrest\Text;

class IsEqualIgnoringWhiteSpaceTest extends \Hamcrest\AbstractMatcherTest
{

    private $_matcher;

    public function setUp()
    {
        $this->_matcher = \Hamcrest\Text\IsEqualIgnoringWhiteSpace::equalToIgnoringWhiteSpace(
            "Hello World   how\n are we? "
        );
    }

    protected function createMatcher()
    {
        return $this->_matcher;
    }

    public function testPassesIfWordsAreSameButWhitespaceDiffers()
    {
        assertThat('Hello World how are we?', $this->_matcher);
        assertThat("   Hello \rWorld \t  how are\nwe?", $this->_matcher);
    }

    public function testFailsIfTextOtherThanWhitespaceDiffers()
    {
        assertThat('Hello PLANET how are we?', not($this->_matcher));
        assertThat('Hello World how are we', not($this->_matcher));
    }

    public function testFailsIfWhitespaceIsAddedOrRemovedInMidWord()
    {
        assertThat('HelloWorld how are we?', not($this->_matcher));
        assertThat('Hello Wo rld how are we?', not($this->_matcher));
    }

    public function testFailsIfMatchingAgainstNull()
    {
        assertThat(null, not($this->_matcher));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            "equalToIgnoringWhiteSpace(\"Hello World   how\\n are we? \")",
            $this->_matcher
        );
    }
}
Xml/HasXPathTest.php000066400000011750151520662040010344 0ustar00<?php
namespace Hamcrest\Xml;

class HasXPathTest extends \Hamcrest\AbstractMatcherTest
{
    protected static $xml;
    protected static $doc;
    protected static $html;

    public static function setUpBeforeClass()
    {
        self::$xml = <<<XML
<?xml version="1.0"?>
<users>
    <user>
        <id>alice</id>
        <name>Alice Frankel</name>
        <role>admin</role>
    </user>
    <user>
        <id>bob</id>
        <name>Bob Frankel</name>
        <role>user</role>
    </user>
    <user>
        <id>charlie</id>
        <name>Charlie Chan</name>
        <role>user</role>
    </user>
</users>
XML;
        self::$doc = new \DOMDocument();
        self::$doc->loadXML(self::$xml);

        self::$html = <<<HTML
<html>
    <head>
        <title>Home Page</title>
    </head>
    <body>
        <h1>Heading</h1>
        <p>Some text</p>
    </body>
</html>
HTML;
    }

    protected function createMatcher()
    {
        return \Hamcrest\Xml\HasXPath::hasXPath('/users/user');
    }

    public function testMatchesWhenXPathIsFound()
    {
        assertThat('one match', self::$doc, hasXPath('user[id = "bob"]'));
        assertThat('two matches', self::$doc, hasXPath('user[role = "user"]'));
    }

    public function testDoesNotMatchWhenXPathIsNotFound()
    {
        assertThat(
            'no match',
            self::$doc,
            not(hasXPath('user[contains(id, "frank")]'))
        );
    }

    public function testMatchesWhenExpressionWithoutMatcherEvaluatesToTrue()
    {
        assertThat(
            'one match',
            self::$doc,
            hasXPath('count(user[id = "bob"])')
        );
    }

    public function testDoesNotMatchWhenExpressionWithoutMatcherEvaluatesToFalse()
    {
        assertThat(
            'no matches',
            self::$doc,
            not(hasXPath('count(user[id = "frank"])'))
        );
    }

    public function testMatchesWhenExpressionIsEqual()
    {
        assertThat(
            'one match',
            self::$doc,
            hasXPath('count(user[id = "bob"])', 1)
        );
        assertThat(
            'two matches',
            self::$doc,
            hasXPath('count(user[role = "user"])', 2)
        );
    }

    public function testDoesNotMatchWhenExpressionIsNotEqual()
    {
        assertThat(
            'no match',
            self::$doc,
            not(hasXPath('count(user[id = "frank"])', 2))
        );
        assertThat(
            'one match',
            self::$doc,
            not(hasXPath('count(user[role = "admin"])', 2))
        );
    }

    public function testMatchesWhenContentMatches()
    {
        assertThat(
            'one match',
            self::$doc,
            hasXPath('user/name', containsString('ice'))
        );
        assertThat(
            'two matches',
            self::$doc,
            hasXPath('user/role', equalTo('user'))
        );
    }

    public function testDoesNotMatchWhenContentDoesNotMatch()
    {
        assertThat(
            'no match',
            self::$doc,
            not(hasXPath('user/name', containsString('Bobby')))
        );
        assertThat(
            'no matches',
            self::$doc,
            not(hasXPath('user/role', equalTo('owner')))
        );
    }

    public function testProvidesConvenientShortcutForHasXPathEqualTo()
    {
        assertThat('matches', self::$doc, hasXPath('count(user)', 3));
        assertThat('matches', self::$doc, hasXPath('user[2]/id', 'bob'));
    }

    public function testProvidesConvenientShortcutForHasXPathCountEqualTo()
    {
        assertThat('matches', self::$doc, hasXPath('user[id = "charlie"]', 1));
    }

    public function testMatchesAcceptsXmlString()
    {
        assertThat('accepts XML string', self::$xml, hasXPath('user'));
    }

    public function testMatchesAcceptsHtmlString()
    {
        assertThat('accepts HTML string', self::$html, hasXPath('body/h1', 'Heading'));
    }

    public function testHasAReadableDescription()
    {
        $this->assertDescription(
            'XML or HTML document with XPath "/users/user"',
            hasXPath('/users/user')
        );
        $this->assertDescription(
            'XML or HTML document with XPath "count(/users/user)" <2>',
            hasXPath('/users/user', 2)
        );
        $this->assertDescription(
            'XML or HTML document with XPath "/users/user/name"'
            . ' a string starting with "Alice"',
            hasXPath('/users/user/name', startsWith('Alice'))
        );
    }

    public function testHasAReadableMismatchDescription()
    {
        $this->assertMismatchDescription(
            'XPath returned no results',
            hasXPath('/users/name'),
            self::$doc
        );
        $this->assertMismatchDescription(
            'XPath expression result was <3F>',
            hasXPath('/users/user', 2),
            self::$doc
        );
        $this->assertMismatchDescription(
            'XPath returned ["alice", "bob", "charlie"]',
            hasXPath('/users/user/id', 'Frank'),
            self::$doc
        );
    }
}