diff options
author | Paul Duffin <paulduffin@google.com> | 2017-02-24 13:38:19 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-02-24 13:38:19 +0000 |
commit | 2c2a845e1e8fdda704e4f2ccaa335d69d043ebf3 (patch) | |
tree | 873cd708d3c6fb36684c53bc506ff3940c3ec3f0 | |
parent | 9432ade17c16656f8c3ebbe2b7f3081a93c52d4d (diff) | |
parent | c2e228b07b9dd8266a6eeabb34e27233733ef127 (diff) | |
download | hamcrest-2c2a845e1e8fdda704e4f2ccaa335d69d043ebf3.tar.gz |
Merge changes from topic 'upgrade-hamcrest-to-2.0' am: f324aac9e2 am: 0d446c0a6fandroid-wear-8.1.0_r1android-vts-8.1_r9android-vts-8.1_r8android-vts-8.1_r7android-vts-8.1_r6android-vts-8.1_r5android-vts-8.1_r4android-vts-8.1_r3android-vts-8.1_r14android-vts-8.1_r13android-vts-8.1_r12android-vts-8.1_r11android-vts-8.1_r10android-vts-8.0_r2android-vts-8.0_r1android-security-8.1.0_r93android-security-8.1.0_r92android-security-8.1.0_r91android-security-8.1.0_r90android-security-8.1.0_r89android-security-8.1.0_r88android-security-8.1.0_r87android-security-8.1.0_r86android-security-8.1.0_r85android-security-8.1.0_r84android-security-8.1.0_r83android-security-8.1.0_r82android-o-mr1-preview-2android-o-mr1-preview-1android-cts-8.1_r9android-cts-8.1_r8android-cts-8.1_r7android-cts-8.1_r6android-cts-8.1_r5android-cts-8.1_r4android-cts-8.1_r3android-cts-8.1_r25android-cts-8.1_r24android-cts-8.1_r23android-cts-8.1_r22android-cts-8.1_r21android-cts-8.1_r20android-cts-8.1_r2android-cts-8.1_r19android-cts-8.1_r18android-cts-8.1_r17android-cts-8.1_r16android-cts-8.1_r15android-cts-8.1_r14android-cts-8.1_r13android-cts-8.1_r12android-cts-8.1_r11android-cts-8.1_r10android-cts-8.1_r1android-8.1.0_r9android-8.1.0_r81android-8.1.0_r80android-8.1.0_r8android-8.1.0_r79android-8.1.0_r78android-8.1.0_r77android-8.1.0_r76android-8.1.0_r75android-8.1.0_r74android-8.1.0_r73android-8.1.0_r72android-8.1.0_r71android-8.1.0_r70android-8.1.0_r7android-8.1.0_r69android-8.1.0_r68android-8.1.0_r67android-8.1.0_r66android-8.1.0_r65android-8.1.0_r64android-8.1.0_r63android-8.1.0_r62android-8.1.0_r61android-8.1.0_r60android-8.1.0_r6android-8.1.0_r53android-8.1.0_r52android-8.1.0_r51android-8.1.0_r50android-8.1.0_r5android-8.1.0_r48android-8.1.0_r47android-8.1.0_r46android-8.1.0_r45android-8.1.0_r43android-8.1.0_r42android-8.1.0_r41android-8.1.0_r40android-8.1.0_r4android-8.1.0_r39android-8.1.0_r38android-8.1.0_r37android-8.1.0_r36android-8.1.0_r35android-8.1.0_r33android-8.1.0_r32android-8.1.0_r31android-8.1.0_r30android-8.1.0_r3android-8.1.0_r29android-8.1.0_r28android-8.1.0_r27android-8.1.0_r26android-8.1.0_r25android-8.1.0_r23android-8.1.0_r22android-8.1.0_r21android-8.1.0_r20android-8.1.0_r2android-8.1.0_r19android-8.1.0_r18android-8.1.0_r17android-8.1.0_r16android-8.1.0_r15android-8.1.0_r14android-8.1.0_r13android-8.1.0_r12android-8.1.0_r11android-8.1.0_r10android-8.1.0_r1android-8.0.0_r34android-8.0.0_r33android-8.0.0_r27android-8.0.0_r26android-8.0.0_r25android-8.0.0_r24android-8.0.0_r23android-8.0.0_r22android-8.0.0_r21security-oc-mr1-releaseoreo-mr1-wear-releaseoreo-mr1-vts-releaseoreo-mr1-security-releaseoreo-mr1-s1-releaseoreo-mr1-releaseoreo-mr1-devoreo-mr1-cuttlefish-testingoreo-mr1-cts-releaseoreo-m8-releaseoreo-m7-releaseoreo-m6-s4-releaseoreo-m6-s3-releaseoreo-m6-s2-releaseoreo-m5-releaseoreo-m4-s9-releaseoreo-m4-s8-releaseoreo-m4-s7-releaseoreo-m4-s6-releaseoreo-m4-s5-releaseoreo-m4-s4-releaseoreo-m4-s3-releaseoreo-m4-s2-releaseoreo-m4-s12-releaseoreo-m4-s11-releaseoreo-m4-s10-releaseoreo-m4-s1-releaseoreo-m3-releaseoreo-m2-s5-releaseoreo-m2-s4-releaseoreo-m2-s3-releaseoreo-m2-s2-releaseoreo-m2-s1-releaseoreo-m2-releaseoreo-dr3-releaseoreo-dr2-releaseoreo-dr1-releaseoreo-dr1-devoreo-dev
am: c2e228b07b
Change-Id: I737b987a8b22811c7ea058bcd9898b58694b58ce
157 files changed, 10354 insertions, 1483 deletions
diff --git a/BUILDING.txt b/BUILDING.txt new file mode 100644 index 0000000..8d6ee82 --- /dev/null +++ b/BUILDING.txt @@ -0,0 +1,19 @@ + **********************
+********************* Building Hamcrest *********************
+ **********************
+
+--[ Build requirements ]-------------------------------------
+
+* JDK 1.7
+
+* Gradle
+
+--[ Building from the command line ]-------------------------
+
+Execute the default ant target:
+ ./gradlew clean build javadoc
+
+This will do a full clean build, run all tests and (if
+successful) package up a distribution. The resulting builds
+reside in the 'build' directory.
+
diff --git a/CHANGES.txt b/CHANGES.txt new file mode 100644 index 0000000..f0a392b --- /dev/null +++ b/CHANGES.txt @@ -0,0 +1,135 @@ +== Version 2.0.0.0 ==
+
+A new beginning...
+
+* Upgraded to Java 7
+
+* Build with Gradle
+
+* Publish a single jar java-hamcrest-x.x.x.x.jar
+
+* Removed deprecated methods from previous release
+
+* Improve mismatch description of hasItem/hasItems
+
+* General improvements to mismatch descriptions
+
+* Several JavaDoc improvements and corrections
+
+* Fix gh issue #69 - Iterable contains in order is null-safe
+
+* Fix gh issue #59 - added equalToObject() (i.e. unchecked) method
+
+* Fix gh issue #25 - arrayContaining(null, null) cause NullPointerException
+
+* Fix gh issue #36 - string matching on regular expressions
+
+* Fix gh issue #8 - isCloseTo() shows wrong delta in mismatch description
+
+* Fix issue 131 - Implement IsEmptyMap, IsMapWithSize
+
+* Fix issue 155 - Deprecated several matcher factory methods of the for "isXyz"
+
+* Fix issue 187 - IsArray.describeMismatchSafely() should use Matcher.describeMismatch
+
+* Fix issue 155 - Add Matcher implementation for files
+
+* Fix issue 59 - add untyped version of equalTo, named equalToObject
+
+* Fix issue 69 - fix NPE in IsIterableContainingInOrder
+
+* Fix issue 75 - address doclint errors reported in JDK 1.8
+
+== Version 1.3: Released July 09 2012 ==
+
+* Introduce Condition class to ease the implementation of multi-step matches
+
+* Upgrade qdox (included in the generator) to the latest stable version
+
+* Correct inadvertent deprecation of the Is.isA factory method
+
+* Fix issue 179 - AllOf does not output mismatch description
+
+* Fix issue 177 - Introduced closeTo matcher for BigDecimals
+
+* Fix issue 152 - Factory classes missing from matchers.xml
+
+* Fix issue 144 - OrderingComparison doesn't describe mismatch of comparables that return values other than (-1,0,1)
+
+* Fix issue 134 - DescribedAs does not delegate describeMismatch
+
+* Fix issue 106 - deprecation warning when writing custom matchers
+
+* Fix issue 101 - Added theInstance alias for sameInstance factory method
+
+== Version 1.3 RC2: Released October 22 2010 ==
+
+* Added FeatureMatcher
+
+* distinguish between instanceOf() and any()
+
+== Version 1.2: Released May 16 2009 ==
+
+* Added mismatch reporting
+
+* Added WithSamePropertyValuesAs matcher
+
+* Moved any() from IsAnything to IsInstanceOf. It now checks the type of the matched object
+
+* Moved MatcherAssert from integration to core
+
+* Tightened up generics.
+
+* Added IsMapContainingKey and IsMapContainingValue matchers to resolve a
+ generics bug in hasKey and hasValue static factories previously declared
+ in IsMapContaining (ngd)
+
+* Added IsCollectionOnlyContaining and IsArrayOnlyContaining which matches
+ collections (and arrays) where all match a given matcher. E.g onlyContains(3,4,5)
+ or onlyContains(lessThan(9))
+
+* text module moved to separate project, hamcrest-text-patterns
+
+* added more colection matchers: xContainingInAnyOrder, xContainingInOrder, xWithSize
+
+* new text Matcher: IsEmptyString
+
+* hamcrest generator uses method return type
+
+== Version 1.1: Released Jun 30 2007 ==
+
+* Hamcrest Generator now includes JavaDoc and parameter names in generated code
+ by using QDox to parse the source code.
+
+* Created hamcrest-core.jar (and removed hamcrest-api.jar).
+ Moved core set of matchers (and, eq, not, etc)
+ to this package to make it more practical for external libraries
+ to embed Hamcrest.
+
+* Created CoreMatchers (static import sugar) in hamcrest-core.jar.
+
+* StringBuilder can use any Appendable (not just StringBuffer).
+
+* Added sensible toString() method to BaseMatcher.
+
+* Created StringDescription.asString() alias (because toString() caused issues
+ with static imports).
+
+* Relaxed isInstanceOf() matcher generic type so it can be used on any kind of
+ object. e.g. assertThat(someUnknownObject, isInstanceOf(String.class));
+
+* Added any(Class<T>), null(Class<T>) and notNull(Class<T>) matchers, which returns
+ Matcher<T>. Helpful when the compiler struggles with type inference.
+
+* Modified anyOf() and allOf() to accept mixed-types.
+
+* TypeSafeMatcher.matchesSafely() is now public.
+
+* Generator recognizes @Factory methods that return subclass of Matcher.
+ (Fix by David Saff)
+
+== Version 1.0: Released Dec 15 2006 ==
+
+Initial release.
+* Support for namespaces in HasXPath
+* Bug fix for matching empty elements with HasXPath
diff --git a/LICENSE.txt b/LICENSE.txt index 5ebe92c..71806dd 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ BSD License
-Copyright (c) 2000-2006, www.hamcrest.org
+Copyright (c) 2000-20014 www.hamcrest.org
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/README.android b/README.android deleted file mode 100644 index a1bbfd2..0000000 --- a/README.android +++ /dev/null @@ -1 +0,0 @@ -unmodified source obtained from http://code.google.com/p/hamcrest/downloads/detail?name=hamcrest-core-1.1.jar&can=2&q=, diff --git a/README.md b/README.md new file mode 100644 index 0000000..c1e1e0f --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +![JavaHamcrest](http://hamcrest.org/images/logo.jpg) + +[![Build Status](https://travis-ci.org/hamcrest/JavaHamcrest.png?branch=master)](https://travis-ci.org/hamcrest/JavaHamcrest) + +Java Hamcrest +============= +Licensed under [BSD License][]. + +What is Hamcrest? +----------------- +Hamcrest is a library of matchers, which can be combined in to create flexible expressions of intent in tests. +They've also been used for other purposes. + +Downloads +--------- +You can obtain Hamcrest binaries from [maven central][], or from [google code downloads][]. + +Extensions +---------- + +For Hamcrest extension projects see the [hamcrest extensions page][]. + +Documentation +------------- +Documentation can be found on the [Hamcrest site](http://hamcrest.org). + +Reporting Bugs/Issues +--------------------- +If you find an issue with Java Hamcrest, please report it via the +[GitHub issue tracker](https://github.com/hamcrest/JavaHamcrest/issues), +after first checking that it hasn't been raised already. + +Source +------ +To build, please read BUILDING.txt + +Acknowledgements +---------------- +Developers: + + * Joe Walnes + * Nat Pryce + * Steve Freeman + +Contributors: + + * Robert Chatley + * Tom White + * Neil Dunn + * Dan North + * Magne Rasmussen + * David Saff + * Tom Denley + +Also, thanks to everyone who has worked on DynaMock, nMock, jMock, EasyMock and MiniMock! These libraries inspired Hamcrest. + + +[logo]: https://raw.github.com/hamcrest/JavaHamcrest/master/doc/images/logo.jpg +[website]: https://github.com/hamcrest/JavaHamcrest +[BSD License]: http://opensource.org/licenses/BSD-3-Clause +[Maven central]: http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.hamcrest +[hamcrest extensions page]: https://github.com/hamcrest/JavaHamcrest/wiki/Related-Projects +[GitHub issue tracker]: https://github.com/hamcrest/JavaHamcrest/issues diff --git a/README.version b/README.version new file mode 100644 index 0000000..660cee5 --- /dev/null +++ b/README.version @@ -0,0 +1,15 @@ +URL: https://github.com/hamcrest/JavaHamcrest/archive/f540af9fd49f33cc07b3446a8895c7b51cbf0944.zip +Version: f540af9fd49f33cc07b3446a8895c7b51cbf0944 +BugComponent: 40416 + +Version f540af9fd49f33cc07b3446a8895c7b51cbf0944 was chosen because it is the +point at which v2.0.0.0 and master diverge. There are only about 7 commits +on v2.0.0.0 which are not on master but they do conflict with some changes in +master. Those changes appear to be relatively minor and while it is not clear +what the future holds for Hamcrest given that it has had no activity since June +2016 it seems unnecessary to take those extra 7 commits given the potential for +conflicts in future upgrades. + +Local Changes: + Remove hamcrest-library/src/main/java/org/hamcrest/beans/ as Android does not support java.beans. +
\ No newline at end of file diff --git a/build.gradle b/build.gradle index b169d73..cd23be2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,116 @@ +import static org.gradle.api.JavaVersion.VERSION_1_7 + apply plugin: 'java' +apply plugin: 'maven' +apply plugin: 'signing' + +sourceCompatibility = VERSION_1_7 +targetCompatibility = VERSION_1_7 +archivesBaseName = "java-hamcrest" + +group = "org.hamcrest" +version = "2.0.0.0" + + +repositories { + mavenCentral() +} + +dependencies { + testCompile(group: 'junit', name: 'junit', version: '4.12') { + transitive = false + } +} sourceSets { main { java { - srcDirs = ['src'] + srcDirs 'hamcrest-core/src/main/java', 'hamcrest-library/src/main/java' + } + + } + test { + java { + srcDirs 'hamcrest-core/src/test/java', 'hamcrest-library/src/test/java' + } + } +} + +jar { + manifest { + attributes 'Implementation-Title': 'hamcrest-all', + 'Implementation-Vendor': 'hamcrest.org', + 'Implementation-Version': version + } +} + +task sourcesJar(type: Jar) { + classifier = 'sources' + from sourceSets.main.allSource +} + +task javadocJar(type: Jar) { + classifier = 'javadoc' + from javadoc +} + +artifacts { + archives sourcesJar, javadocJar +} + +signing { + required { gradle.taskGraph.hasTask("uploadArchives") } + sign configurations.archives +} + +uploadArchives { + if (hasProperty('ossrhUsername') && hasProperty('ossrhPassword')) { + repositories { + mavenDeployer { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + + repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } + + snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { + authentication(userName: ossrhUsername, password: ossrhPassword) + } + + pom.project { + name 'Java Hamcrest' + packaging 'jar' + description 'Hamcrest matcher library for Java' + url 'http://hamcrest.org/JavaHamcrest/' + + scm { + connection 'git@github.com:hamcrest/JavaHamcrest.git' + url 'https://github.com/hamcrest/JavaHamcrest' + } + + licenses { + license { + name 'BSD Licence 3' + url 'http://opensource.org/licenses/BSD-3-Clause' + } + } + + developers { + developer { + id 'joewalnes' + name 'Joe Walnes' + } + developer { + id 'npryce' + name 'Nat Pryce' + } + developer { + id 'sf105' + name 'Steve Freeman' + } + } + } + } } } } diff --git a/build.xml.original b/build.xml.original new file mode 100644 index 0000000..95662ee --- /dev/null +++ b/build.xml.original @@ -0,0 +1,289 @@ +<project name="hamcrest" default="all"> + + <property name="version" value="SNAPSHOT" description="Version number to use in build files"/> + <property name="haltonfailure" value="true" description="Whether to halt the build if the tests fail"/> + <property name="debug" value="true" description="Whether to build with debug information"/> + <property name="javaversion" value="1.5" description="Java version to target"/> + <tstamp><format property="build.timestamp" pattern="yyyy-MM-dd HH:mm:ss" timezone="GMT"/></tstamp> + <taskdef name="junit" classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTask" classpath="lib/integration/ant-junit-1.8.4.jar"/> + + + <target name="all" depends="clean, bigjar, javadoc" description="Performs clean build, runs tests and packages for distribution"/> + + <target name="clean" description="Clean up all built files"> + <delete dir="build"/> + </target> + + <target name="api" description="Build Hamcrest APIs"> + <path id="cp-hamcrest-api-main" path=""/> + <path id="cp-hamcrest-api-test" path=""/> + <compile-module modulename="hamcrest-api"/> + <jar-module modulename="hamcrest-api"/> + <test-module modulename="hamcrest-api"/> + </target> + + <target name="generator" depends="api" description="Build code generator tool"> + <path id="cp-hamcrest-generator-main" path="lib/generator/qdox-2.0-M2.jar;build/hamcrest-api-${version}.jar"/> + <path id="cp-hamcrest-generator-test" path=""/> + <compile-module modulename="hamcrest-generator"/> + <jar-module modulename="hamcrest-generator"/> + <test-module modulename="hamcrest-generator"/> + + <!-- Include QDox classes in hamcrest-generator.jar using JarJar to place classes under a different package --> + <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="lib/generator/jarjar-1.3.jar"/> + <copy file="build/hamcrest-generator-${version}.jar" tofile="build/hamcrest-generator-${version}-nodep.jar"/> + <jarjar jarfile="build/hamcrest-generator-${version}.jar"> + <zipfileset src="build/hamcrest-generator-${version}-nodep.jar"/> + <zipfileset src="lib/generator/qdox-2.0-M2.jar"/> + <rule pattern="com.thoughtworks.qdox.**" result="org.hamcrest.generator.qdox.@1"/> + </jarjar> + </target> + + <target name="core" depends="generator" description="Build core Hamcrest library"> + <path id="cp-hamcrest-core-main" path="build/hamcrest-api-${version}.jar"/> + <path id="cp-hamcrest-core-test" path=""/> + <compile-module modulename="hamcrest-core"/> + <generate-module-factory modulename="hamcrest-core" configurationfile="hamcrest-core/core-matchers.xml" targetclass="org.hamcrest.CoreMatchers" sources="hamcrest-core/src/main/java"/> + <jar-module modulename="hamcrest-core"/> + <test-module modulename="hamcrest-core"/> + </target> + + <target name="library" depends="core" description="Build library of matchers"> + <path id="cp-hamcrest-library-main" path="build/hamcrest-api-${version}.jar;build/hamcrest-core-${version}.jar"/> + <path id="cp-hamcrest-library-test" path="build/hamcrest-core-${version}-tests.jar"/> + <compile-module modulename="hamcrest-library"/> + <generate-module-factory modulename="hamcrest-library" configurationfile="hamcrest-library/matchers.xml" targetclass="org.hamcrest.Matchers" sources="hamcrest-core/src/main/java,hamcrest-library/src/main/java"/> + <jar-module modulename="hamcrest-library"/> + <test-module modulename="hamcrest-library"/> + </target> + + <target name="integration" depends="library" description="Build integration with external tools"> + <path id="cp-hamcrest-integration-main"> + <fileset file="build/hamcrest-api-${version}.jar"/> + <fileset file="build/hamcrest-core-${version}.jar"/> + <fileset file="build/hamcrest-library-${version}.jar"/> + <fileset dir="lib/integration" includes="**/*.jar"/> + </path> + <path id="cp-hamcrest-integration-test" path="build/hamcrest-core-${version}-tests.jar"/> + <compile-module modulename="hamcrest-integration"/> + <jar-module modulename="hamcrest-integration"/> + <test-module modulename="hamcrest-integration"/> + </target> + + <target name="examples" depends="core, library, integration" description="Build and run unit tests."> + <path id="cp-hamcrest-examples-main"> + <fileset file="build/hamcrest-api-${version}.jar"/> + <fileset file="build/hamcrest-core-${version}.jar"/> + <fileset file="build/hamcrest-library-${version}.jar"/> + <fileset file="build/hamcrest-integration-${version}.jar"/> + <fileset dir="lib/integration" includes="**/*.jar"/> + </path> + <compile-module modulename="hamcrest-examples"/> + <jar-module modulename="hamcrest-examples"/> + </target> + + <target name="bigjar" depends="core,library,integration,generator" description="Build composite jars"> + <!-- Bundle api into core jar --> + <copy todir="build/temp/hamcrest-core-${version}.jar.contents"> + <fileset dir="build/temp/hamcrest-api-${version}.jar.contents"/> + </copy> + <copy todir="build/temp/hamcrest-core-${version}-sources.jar.contents"> + <fileset dir="build/temp/hamcrest-api-${version}-sources.jar.contents"/> + </copy> + <jar-module modulename="hamcrest-core"/> + + <!-- Bundle core, library, integration, and generator into all jar--> + <copy todir="build/temp/hamcrest-all-${version}.jar.contents"> + <fileset dir="build/temp/hamcrest-core-${version}.jar.contents"/> + <fileset dir="build/temp/hamcrest-library-${version}.jar.contents"/> + <fileset dir="build/temp/hamcrest-integration-${version}.jar.contents"/> + <fileset dir="build/temp/hamcrest-generator-${version}.jar.contents"/> + </copy> + <copy todir="build/temp/hamcrest-all-${version}-sources.jar.contents"> + <fileset dir="build/temp/hamcrest-core-${version}-sources.jar.contents"/> + <fileset dir="build/temp/hamcrest-library-${version}-sources.jar.contents"/> + <fileset dir="build/temp/hamcrest-integration-${version}-sources.jar.contents"/> + <fileset dir="build/temp/hamcrest-generator-${version}-sources.jar.contents"/> + </copy> + <path id="cp-hamcrest-all-main"> + <path refid="cp-hamcrest-core-main"/> + <path refid="cp-hamcrest-library-main"/> + <path refid="cp-hamcrest-integration-main"/> + <path refid="cp-hamcrest-generator-main"/> + </path> + <jar-module modulename="hamcrest-all"/> + </target> + + <target name="javadoc" depends="bigjar" description="build javadoc jars"> + <javadoc-module modulename="hamcrest-generator"/> + <javadoc-module modulename="hamcrest-core"/> + <javadoc-module modulename="hamcrest-library"/> + <javadoc-module modulename="hamcrest-integration"/> + <javadoc-module modulename="hamcrest-all"/> + </target> + + <target name="bundle" description="Create a release bundle for deployment to maven central" depends="clean, javadoc"> + <copy todir="build"> + <fileset dir="pom" includes="*.pom"/> + <filterset><filter token="VERSION" value="${version}"/></filterset> + <mapper type="regexp" from="(.*)\.pom" to="\1-${version}.pom"/> + </copy> + + <sign target="hamcrest-parent-${version}.pom"/> + <jar-bundle modulename="hamcrest-parent"/> + + <bundle-module modulename="hamcrest-core"/> + <bundle-module modulename="hamcrest-generator"/> + <bundle-module modulename="hamcrest-library"/> + <bundle-module modulename="hamcrest-integration"/> + <bundle-module modulename="hamcrest-all"/> + </target> + + <macrodef name="make-manifest"> + <attribute name="modulename" description="Name of the module"/> + <sequential> + <mkdir dir="build/temp/@{modulename}-${version}.jar.manifest"/> + <manifest file="build/temp/@{modulename}-${version}.jar.manifest/MANIFEST.MF"> + <attribute name="Implementation-Title" value="@{modulename}"/> + <attribute name="Implementation-Vendor" value="hamcrest.org"/> + <attribute name="Implementation-Version" value="${version}"/> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Built-Date" value="${build.timestamp}"/> + </manifest> + </sequential> + </macrodef> + + <macrodef name="compile-module"> + <attribute name="modulename" description="Name of the module to jar"/> + <sequential> + <compile-content srcdir="@{modulename}/src/main/java" jarname="@{modulename}-${version}" classpathref="cp-@{modulename}-main" /> + <path id="cp-@{modulename}-test-complete"> + <path path="lib/integration/junit-dep-4.11.jar"/> + <path refid="cp-@{modulename}-main"/> + <path refid="cp-@{modulename}-test"/> + <path path="build/temp/@{modulename}-${version}.jar.contents"/> + </path> + <compile-content srcdir="@{modulename}/src/test/java" jarname="@{modulename}-${version}-tests" classpathref="cp-@{modulename}-test-complete" /> + </sequential> + </macrodef> + + <macrodef name="compile-content"> + <attribute name="srcdir"/> + <attribute name="jarname" description="Name of the jar whose content is being compiled (without .jar suffix)"/> + <attribute name="classpathref"/> + <sequential> + <mkdir dir="build/temp/@{jarname}-sources.jar.contents"/> + <copy failonerror="false" todir="build/temp/@{jarname}-sources.jar.contents"> + <fileset dir="@{srcdir}"/> + </copy> + <mkdir dir="build/temp/@{jarname}.jar.contents"/> + <javac srcdir="build/temp/@{jarname}-sources.jar.contents" + destdir="build/temp/@{jarname}.jar.contents" + debug="${debug}" source="${javaversion}" target="${javaversion}" includeantruntime="false"> + <classpath refid="@{classpathref}"/> + </javac> + </sequential> + </macrodef> + + <macrodef name="jar-module"> + <attribute name="modulename" description="Name of the module to jar"/> + <sequential> + <make-manifest modulename="@{modulename}"/> + <jar-module-component modulename="@{modulename}"/> + <jar-module-component modulename="@{modulename}" suffix="-tests"/> + <jar-module-component modulename="@{modulename}" suffix="-sources"/> + </sequential> + </macrodef> + + <macrodef name="jar-module-component"> + <attribute name="modulename" description="Name of the module to jar"/> + <attribute name="suffix" default="" description="Name of the module to jar"/> + <sequential> + <copy file="LICENSE.txt" todir="build/temp/@{modulename}-${version}@{suffix}.jar.contents/META-INF"/> + <jar jarfile="build/@{modulename}-${version}@{suffix}.jar" manifest="build/temp/@{modulename}-${version}.jar.manifest/MANIFEST.MF"> + <fileset dir="build/temp/@{modulename}-${version}@{suffix}.jar.contents"/> + </jar> + </sequential> + </macrodef> + + <macrodef name="generate-module-factory" description="Generate one class with all static imports"> + <attribute name="modulename" description="Name of the module to jar"/> + <attribute name="configurationfile" description="xml configuration file"/> + <attribute name="targetclass" description="factory class to generate"/> + <attribute name="sources" description="comma-separated source directories"/> + <sequential> + <mkdir dir="build/temp/@{modulename}/generated-code"/> + <java classname="org.hamcrest.generator.config.XmlConfigurator" fork="yes" failonerror="yes"> + <classpath path="build/hamcrest-generator-${version}.jar"/> + <classpath refid="cp-@{modulename}-main"/> + <classpath path="build/temp/@{modulename}-${version}.jar.contents"/> + <arg value="@{configurationfile}"/> + <arg value="@{sources}"/> + <arg value="@{targetclass}"/> + <arg value="build/temp/@{modulename}/generated-code"/> + </java> + + <copy todir="build/temp/@{modulename}-${version}-sources.jar.contents"> + <fileset dir="build/temp/@{modulename}/generated-code"/> + </copy> + <compile-module modulename="@{modulename}"/> + </sequential> + </macrodef> + + <macrodef name="test-module" description="run unit tests."> + <attribute name="modulename" description="Name of the module to test"/> + <sequential> + <mkdir dir="build/temp/@{modulename}/test-wrk"/> + <junit printsummary="no" forkmode="once" tempdir="build/temp/@{modulename}/test-wrk" haltonfailure="${haltonfailure}" dir="@{modulename}"> + <formatter type="brief" usefile="no"/> + <classpath refid="cp-@{modulename}-test-complete"/> + <classpath path="build/@{modulename}-${version}-tests.jar"/> + <batchtest fork="yes" todir="${build.dir}/testreport"> + <zipfileset src="build/@{modulename}-${version}-tests.jar"> + <include name="org/hamcrest/**/*Test.class"/> + <exclude name="**/Abstract*.class"/> + </zipfileset> + </batchtest> + </junit> + </sequential> + </macrodef> + + <macrodef name="javadoc-module" description="Generate javadoc for a module and build a Jar"> + <attribute name="modulename" description="Name of the module to document"/> + <sequential> + <javadoc packagenames="org.hamcrest.*" sourcepath="build/temp/@{modulename}-${version}-sources.jar.contents" + destdir="build/temp/@{modulename}-${version}-javadoc.jar.contents" author="true" version="true" + use="true" windowtitle="Hamcrest" source="${javaversion}" failonerror="yes" defaultexcludes="yes"> + <classpath refid="cp-@{modulename}-main"/> + </javadoc> + <jar-module-component modulename="@{modulename}" suffix="-javadoc"/> + </sequential> + </macrodef> + + <macrodef name="bundle-module" description="Generate maven bundle jar for a module"> + <attribute name="modulename" description="Name of the module to bundle"/> + <sequential> + <sign target="@{modulename}-${version}.pom"/> + <sign target="@{modulename}-${version}.jar"/> + <sign target="@{modulename}-${version}-javadoc.jar"/> + <sign target="@{modulename}-${version}-sources.jar"/> + <jar-bundle modulename="@{modulename}"/> + </sequential> + </macrodef> + + <macrodef name="jar-bundle" description="Jar maven bundle contents"> + <attribute name="modulename" description="Name of the module to create bundle jar for"/> + <sequential> + <jar destfile="build/maven-bundle-@{modulename}.jar"> + <fileset dir="build"><include name="@{modulename}-${version}*"/></fileset> + </jar> + </sequential> + </macrodef> + + <macrodef name="sign" description="Sign a file with a gpg key"> + <attribute name="target" description="Name of the resource to sign"/> + <sequential> + <exec executable="gpg" dir="build"><arg value="-ab"/><arg value="@{target}"/></exec> + </sequential> + </macrodef> +</project> diff --git a/doc/images/logo.jpg b/doc/images/logo.jpg Binary files differnew file mode 100644 index 0000000..efd750d --- /dev/null +++ b/doc/images/logo.jpg diff --git a/hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java b/hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java index 4c98e5f..6e62e69 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java +++ b/hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java @@ -1,127 +1,144 @@ -package org.hamcrest;
-
-import static java.lang.String.valueOf;
-
-import java.util.Arrays;
-import java.util.Iterator;
-
-import org.hamcrest.internal.ArrayIterator;
-import org.hamcrest.internal.SelfDescribingValueIterator;
-
-/**
- * A {@link Description} that is stored as a string.
- */
-public abstract class BaseDescription implements Description {
- public Description appendText(String text) {
- append(text);
- return this;
- }
-
- public Description appendDescriptionOf(SelfDescribing value) {
- value.describeTo(this);
- return this;
- }
-
- public Description appendValue(Object value) {
- if (value == null) {
- append("null");
- } else if (value instanceof String) {
- toJavaSyntax((String) value);
- } else if (value instanceof Character) {
- append('"');
- toJavaSyntax((Character) value);
- append('"');
- } else if (value instanceof Short) {
- append('<');
- append(valueOf(value));
- append("s>");
- } else if (value instanceof Long) {
- append('<');
- append(valueOf(value));
- append("L>");
- } else if (value instanceof Float) {
- append('<');
- append(valueOf(value));
- append("F>");
- } else if (value.getClass().isArray()) {
- appendValueList("[",", ","]", new ArrayIterator(value));
- } else {
- append('<');
- append(valueOf(value));
- append('>');
- }
- return this;
- }
-
- public <T> Description appendValueList(String start, String separator, String end, T... values) {
- return appendValueList(start, separator, end, Arrays.asList(values));
- }
-
- public <T> Description appendValueList(String start, String separator, String end, Iterable<T> values) {
- return appendValueList(start, separator, end, values.iterator());
- }
-
- private <T> Description appendValueList(String start, String separator, String end, Iterator<T> values) {
- return appendList(start, separator, end, new SelfDescribingValueIterator<T>(values));
- }
-
- public Description appendList(String start, String separator, String end, Iterable<? extends SelfDescribing> values) {
- return appendList(start, separator, end, values.iterator());
- }
-
- private Description appendList(String start, String separator, String end, Iterator<? extends SelfDescribing> i) {
- boolean separate = false;
-
- append(start);
- while (i.hasNext()) {
- if (separate) append(separator);
- appendDescriptionOf(i.next());
- separate = true;
- }
- append(end);
-
- return this;
- }
-
-
- /** Append the String <var>str</var> to the description.
- * The default implementation passes every character to {@link #append(char)}.
- * Override in subclasses to provide an efficient implementation.
- */
- protected void append(String str) {
- for (int i = 0; i < str.length(); i++) {
- append(str.charAt(i));
- }
- }
-
- /** Append the char <var>c</var> to the description.
- */
- protected abstract void append(char c);
-
- private void toJavaSyntax(String unformatted) {
- append('"');
- for (int i = 0; i < unformatted.length(); i++) {
- toJavaSyntax(unformatted.charAt(i));
- }
- append('"');
- }
-
- private void toJavaSyntax(char ch) {
- switch (ch) {
- case '"':
- append("\\\"");
- break;
- case '\n':
- append("\\n");
- break;
- case '\r':
- append("\\r");
- break;
- case '\t':
- append("\\t");
- break;
- default:
- append(ch);
- }
- }
-}
+package org.hamcrest; + +import org.hamcrest.internal.ArrayIterator; +import org.hamcrest.internal.SelfDescribingValueIterator; + +import java.util.Arrays; +import java.util.Iterator; + +import static java.lang.String.valueOf; + +/** + * A {@link Description} that is stored as a string. + */ +public abstract class BaseDescription implements Description { + + @Override + public Description appendText(String text) { + append(text); + return this; + } + + @Override + public Description appendDescriptionOf(SelfDescribing value) { + value.describeTo(this); + return this; + } + + @Override + public Description appendValue(Object value) { + if (value == null) { + append("null"); + } else if (value instanceof String) { + toJavaSyntax((String) value); + } else if (value instanceof Character) { + append('"'); + toJavaSyntax((Character) value); + append('"'); + } else if (value instanceof Short) { + append('<'); + append(descriptionOf(value)); + append("s>"); + } else if (value instanceof Long) { + append('<'); + append(descriptionOf(value)); + append("L>"); + } else if (value instanceof Float) { + append('<'); + append(descriptionOf(value)); + append("F>"); + } else if (value.getClass().isArray()) { + appendValueList("[",", ","]", new ArrayIterator(value)); + } else { + append('<'); + append(descriptionOf(value)); + append('>'); + } + return this; + } + + private String descriptionOf(Object value) { + try { + return valueOf(value); + } + catch (Exception e) { + return value.getClass().getName() + "@" + Integer.toHexString(value.hashCode()); + } + } + + @Override + public <T> Description appendValueList(String start, String separator, String end, T... values) { + return appendValueList(start, separator, end, Arrays.asList(values)); + } + + @Override + public <T> Description appendValueList(String start, String separator, String end, Iterable<T> values) { + return appendValueList(start, separator, end, values.iterator()); + } + + private <T> Description appendValueList(String start, String separator, String end, Iterator<T> values) { + return appendList(start, separator, end, new SelfDescribingValueIterator<T>(values)); + } + + @Override + public Description appendList(String start, String separator, String end, Iterable<? extends SelfDescribing> values) { + return appendList(start, separator, end, values.iterator()); + } + + private Description appendList(String start, String separator, String end, Iterator<? extends SelfDescribing> i) { + boolean separate = false; + + append(start); + while (i.hasNext()) { + if (separate) append(separator); + appendDescriptionOf(i.next()); + separate = true; + } + append(end); + + return this; + } + + /** + * Append the String <var>str</var> to the description. + * The default implementation passes every character to {@link #append(char)}. + * Override in subclasses to provide an efficient implementation. + */ + protected void append(String str) { + for (int i = 0; i < str.length(); i++) { + append(str.charAt(i)); + } + } + + /** + * Append the char <var>c</var> to the description. + */ + protected abstract void append(char c); + + private void toJavaSyntax(String unformatted) { + append('"'); + for (int i = 0; i < unformatted.length(); i++) { + toJavaSyntax(unformatted.charAt(i)); + } + append('"'); + } + + private void toJavaSyntax(char ch) { + switch (ch) { + case '"': + append("\\\""); + break; + case '\n': + append("\\n"); + break; + case '\r': + append("\\r"); + break; + case '\t': + append("\\t"); + break; + default: + append(ch); + } + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java index 3fdd6f7..484c101 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java +++ b/hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java @@ -1,5 +1,3 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest; /** @@ -12,11 +10,18 @@ public abstract class BaseMatcher<T> implements Matcher<T> { /** * @see Matcher#_dont_implement_Matcher___instead_extend_BaseMatcher_() */ + @Override + @Deprecated public final void _dont_implement_Matcher___instead_extend_BaseMatcher_() { // See Matcher interface for an explanation of this method. } @Override + public void describeMismatch(Object item, Description description) { + description.appendText("was ").appendValue(item); + } + + @Override public String toString() { return StringDescription.toString(this); } diff --git a/hamcrest-core/src/main/java/org/hamcrest/Condition.java b/hamcrest-core/src/main/java/org/hamcrest/Condition.java new file mode 100644 index 0000000..02ce09e --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/Condition.java @@ -0,0 +1,69 @@ +package org.hamcrest; + +/** + * A Condition implements part of a multi-step match. We sometimes need to write matchers + * that have a sequence of steps, where each step depends on the result of the previous + * step and we can stop processing as soon as a step fails. These classes provide + * infrastructure for writing such a sequence. + * + * Based on https://github.com/npryce/maybe-java + * @author Steve Freeman 2012 http://www.hamcrest.com + */ + +public abstract class Condition<T> { + public static final NotMatched<Object> NOT_MATCHED = new NotMatched<Object>(); + + public interface Step<I, O> { + Condition<O> apply(I value, Description mismatch); + } + + private Condition() { } + + public abstract boolean matching(Matcher<T> match, String message); + public abstract <U> Condition<U> and(Step<? super T, U> mapping); + + public final boolean matching(Matcher<T> match) { return matching(match, ""); } + public final <U> Condition<U> then(Step<? super T, U> mapping) { return and(mapping); } + + @SuppressWarnings("unchecked") + public static <T> Condition<T> notMatched() { + return (Condition<T>) NOT_MATCHED; + } + + public static <T> Condition<T> matched(final T theValue, final Description mismatch) { + return new Matched<T>(theValue, mismatch); + } + + private static final class Matched<T> extends Condition<T> { + private final T theValue; + private final Description mismatch; + + private Matched(T theValue, Description mismatch) { + this.theValue = theValue; + this.mismatch = mismatch; + } + + @Override + public boolean matching(Matcher<T> matcher, String message) { + if (matcher.matches(theValue)) { + return true; + } + mismatch.appendText(message); + matcher.describeMismatch(theValue, mismatch); + return false; + } + + @Override + public <U> Condition<U> and(Step<? super T, U> next) { + return next.apply(theValue, mismatch); + } + } + + private static final class NotMatched<T> extends Condition<T> { + @Override public boolean matching(Matcher<T> match, String message) { return false; } + + @Override public <U> Condition<U> and(Step<? super T, U> mapping) { + return notMatched(); + } + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java b/hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java index 400a491..799a26a 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java +++ b/hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java @@ -1,24 +1,114 @@ -// Generated source. package org.hamcrest; +@SuppressWarnings("UnusedDeclaration") public class CoreMatchers { /** - * Decorates another Matcher, retaining the behavior but allowing tests - * to be slightly more expressive. + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.Matcher<T> allOf(java.lang.Iterable<org.hamcrest.Matcher<? super T>> matchers) { + return org.hamcrest.core.AllOf.<T>allOf(matchers); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + @SafeVarargs + public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T>... matchers) { + return org.hamcrest.core.AllOf.<T>allOf(matchers); + } + + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.core.AnyOf<T> anyOf(java.lang.Iterable<org.hamcrest.Matcher<? super T>> matchers) { + return org.hamcrest.core.AnyOf.<T>anyOf(matchers); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + @SafeVarargs + public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<? super T>... matchers) { + return org.hamcrest.core.AnyOf.<T>anyOf(matchers); + } + + /** + * Creates a matcher that matches when both of the specified matchers match the examined object. + * For example: + * <pre>assertThat("fab", both(containsString("a")).and(containsString("b")))</pre> + */ + public static <LHS> org.hamcrest.core.CombinableMatcher.CombinableBothMatcher<LHS> both(org.hamcrest.Matcher<? super LHS> matcher) { + return org.hamcrest.core.CombinableMatcher.both(matcher); + } + + /** + * Creates a matcher that matches when either of the specified matchers match the examined object. + * For example: + * <pre>assertThat("fan", either(containsString("a")).or(containsString("b")))</pre> + */ + public static <LHS> org.hamcrest.core.CombinableMatcher.CombinableEitherMatcher<LHS> either(org.hamcrest.Matcher<? super LHS> matcher) { + return org.hamcrest.core.CombinableMatcher.either(matcher); + } + + /** + * Wraps an existing matcher, overriding its description with that specified. All other functions are + * delegated to the decorated matcher, including its mismatch description. + * For example: + * <pre>describedAs("a big decimal equal to %0", equalTo(myBigDecimal), myBigDecimal.toPlainString())</pre> + * + * @param description + * the new description for the wrapped matcher + * @param matcher + * the matcher to wrap + * @param values + * optional values to insert into the tokenised description + */ + public static <T> org.hamcrest.Matcher<T> describedAs(java.lang.String description, org.hamcrest.Matcher<T> matcher, java.lang.Object... values) { + return org.hamcrest.core.DescribedAs.describedAs(description, matcher, values); + } + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields items that are all matched by the specified + * <code>itemMatcher</code>. + * For example: + * <pre>assertThat(Arrays.asList("bar", "baz"), everyItem(startsWith("ba")))</pre> * - * eg. assertThat(cheese, equalTo(smelly)) - * vs assertThat(cheese, is(equalTo(smelly))) + * @param itemMatcher + * the matcher to apply to every item provided by the examined {@link Iterable} + */ + public static <U> org.hamcrest.Matcher<java.lang.Iterable<? extends U>> everyItem(org.hamcrest.Matcher<U> itemMatcher) { + return org.hamcrest.core.Every.everyItem(itemMatcher); + } + + /** + * Decorates another Matcher, retaining its behaviour, but allowing tests + * to be slightly more expressive. + * For example: + * <pre>assertThat(cheese, is(equalTo(smelly)))</pre> + * instead of: + * <pre>assertThat(cheese, equalTo(smelly))</pre> */ public static <T> org.hamcrest.Matcher<T> is(org.hamcrest.Matcher<T> matcher) { return org.hamcrest.core.Is.is(matcher); } /** - * This is a shortcut to the frequently used is(equalTo(x)). - * - * eg. assertThat(cheese, is(equalTo(smelly))) - * vs assertThat(cheese, is(smelly)) + * A shortcut to the frequently used <code>is(equalTo(x))</code>. + * For example: + * <pre>assertThat(cheese, is(smelly))</pre> + * instead of: + * <pre>assertThat(cheese, is(equalTo(smelly)))</pre> */ public static <T> org.hamcrest.Matcher<T> is(T value) { return org.hamcrest.core.Is.is(value); @@ -41,131 +131,334 @@ public class CoreMatchers { } /** - * Inverts the rule. + * A shortcut to the frequently used <code>is(instanceOf(SomeClass.class))</code>. + * For example: + * <pre>assertThat(cheese, isA(Cheddar.class))</pre> + * instead of: + * <pre>assertThat(cheese, is(instanceOf(Cheddar.class)))</pre> */ - public static <T> org.hamcrest.Matcher<T> not(org.hamcrest.Matcher<T> matcher) { - return org.hamcrest.core.IsNot.not(matcher); + public static <T> org.hamcrest.Matcher<T> isA(java.lang.Class<T> type) { + return org.hamcrest.core.Is.isA(type); } /** - * This is a shortcut to the frequently used not(equalTo(x)). + * Creates a matcher that always matches, regardless of the examined object. + */ + public static org.hamcrest.Matcher<java.lang.Object> anything() { + return org.hamcrest.core.IsAnything.anything(); + } + + /** + * Creates a matcher that always matches, regardless of the examined object, but describes + * itself with the specified {@link String}. * - * eg. assertThat(cheese, is(not(equalTo(smelly)))) - * vs assertThat(cheese, is(not(smelly))) + * @param description + * a meaningful {@link String} used when describing itself */ - public static <T> org.hamcrest.Matcher<T> not(T value) { - return org.hamcrest.core.IsNot.not(value); + public static org.hamcrest.Matcher<java.lang.Object> anything(java.lang.String description) { + return org.hamcrest.core.IsAnything.anything(description); } /** - * Is the value equal to another value, as tested by the - * {@link java.lang.Object#equals} invokedMethod? + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields at least one item that is matched by the specified + * <code>itemMatcher</code>. Whilst matching, the traversal of the examined {@link Iterable} + * will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem(startsWith("ba")))</pre> + * + * @param itemMatcher + * the matcher to apply to items provided by the examined {@link Iterable} */ - public static <T> org.hamcrest.Matcher<T> equalTo(T operand) { - return org.hamcrest.core.IsEqual.equalTo(operand); + public static <T> org.hamcrest.Matcher<java.lang.Iterable<? super T>> hasItem(org.hamcrest.Matcher<? super T> itemMatcher) { + return org.hamcrest.core.IsCollectionContaining.<T>hasItem(itemMatcher); } /** - * Is the value an instance of a particular type? + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields at least one item that is equal to the specified + * <code>item</code>. Whilst matching, the traversal of the examined {@link Iterable} + * will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem("bar"))</pre> + * + * @param item + * the item to compare against the items provided by the examined {@link Iterable} */ - public static org.hamcrest.Matcher<java.lang.Object> instanceOf(java.lang.Class<?> type) { - return org.hamcrest.core.IsInstanceOf.instanceOf(type); + public static <T> org.hamcrest.Matcher<java.lang.Iterable<? super T>> hasItem(T item) { + return org.hamcrest.core.IsCollectionContaining.<T>hasItem(item); } /** - * Evaluates to true only if ALL of the passed in matchers evaluate to true. + * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the + * examined {@link Iterable} yield at least one item that is matched by the corresponding + * matcher from the specified <code>itemMatchers</code>. Whilst matching, each traversal of + * the examined {@link Iterable} will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems(endsWith("z"), endsWith("o")))</pre> + * + * @param itemMatchers + * the matchers to apply to items provided by the examined {@link Iterable} */ - public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? extends T>... matchers) { - return org.hamcrest.core.AllOf.<T>allOf(matchers); + @SafeVarargs + public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(org.hamcrest.Matcher<? super T>... itemMatchers) { + return org.hamcrest.core.IsCollectionContaining.<T>hasItems(itemMatchers); } /** - * Evaluates to true only if ALL of the passed in matchers evaluate to true. + * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the + * examined {@link Iterable} yield at least one item that is equal to the corresponding + * item from the specified <code>items</code>. Whilst matching, each traversal of the + * examined {@link Iterable} will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems("baz", "foo"))</pre> + * + * @param items + * the items to compare against the items provided by the examined {@link Iterable} */ - public static <T> org.hamcrest.Matcher<T> allOf(java.lang.Iterable<org.hamcrest.Matcher<? extends T>> matchers) { - return org.hamcrest.core.AllOf.allOf(matchers); + @SafeVarargs + public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... items) { + return org.hamcrest.core.IsCollectionContaining.<T>hasItems(items); } /** - * Evaluates to true if ANY of the passed in matchers evaluate to true. + * Creates a matcher that matches when the examined object is logically equal to the specified + * <code>operand</code>, as determined by calling the {@link java.lang.Object#equals} method on + * the <b>examined</b> object. + * + * <p>If the specified operand is <code>null</code> then the created matcher will only match if + * the examined object's <code>equals</code> method returns <code>true</code> when passed a + * <code>null</code> (which would be a violation of the <code>equals</code> contract), unless the + * examined object itself is <code>null</code>, in which case the matcher will return a positive + * match.</p> + * + * <p>The created matcher provides a special behaviour when examining <code>Array</code>s, whereby + * it will match if both the operand and the examined object are arrays of the same length and + * contain items that are equal to each other (according to the above rules) <b>in the same + * indexes</b>.</p> + * For example: + * <pre> + * assertThat("foo", equalTo("foo")); + * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"})); + * </pre> */ - public static <T> org.hamcrest.Matcher<T> anyOf(org.hamcrest.Matcher<? extends T>... matchers) { - return org.hamcrest.core.AnyOf.<T>anyOf(matchers); + public static <T> org.hamcrest.Matcher<T> equalTo(T operand) { + return org.hamcrest.core.IsEqual.equalTo(operand); } /** - * Evaluates to true if ANY of the passed in matchers evaluate to true. + * Creates an {@link org.hamcrest.core.IsEqual} matcher that does not enforce the values being + * compared to be of the same static type. */ - public static <T> org.hamcrest.Matcher<T> anyOf(java.lang.Iterable<org.hamcrest.Matcher<? extends T>> matchers) { - return org.hamcrest.core.AnyOf.anyOf(matchers); + public static org.hamcrest.Matcher<java.lang.Object> equalToObject(java.lang.Object operand) { + return org.hamcrest.core.IsEqual.equalToObject(operand); } /** - * Creates a new instance of IsSame + * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>, + * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the + * the examined object. * - * @param object The predicate evaluates to true only when the argument is - * this object. + * <p>The created matcher forces a relationship between specified type and the examined object, and should be + * used when it is necessary to make generics conform, for example in the JMock clause + * <code>with(any(Thing.class))</code></p> + * For example: + * <pre>assertThat(new Canoe(), instanceOf(Canoe.class));</pre> */ - public static <T> org.hamcrest.Matcher<T> sameInstance(T object) { - return org.hamcrest.core.IsSame.sameInstance(object); + public static <T> org.hamcrest.Matcher<T> any(java.lang.Class<T> type) { + return org.hamcrest.core.IsInstanceOf.any(type); } /** - * This matcher always evaluates to true. + * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>, + * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the + * the examined object. + * + * <p>The created matcher assumes no relationship between specified type and the examined object.</p> + * For example: + * <pre>assertThat(new Canoe(), instanceOf(Paddlable.class));</pre> */ - public static <T> org.hamcrest.Matcher<T> anything() { - return org.hamcrest.core.IsAnything.anything(); + public static <T> org.hamcrest.Matcher<T> instanceOf(java.lang.Class<?> type) { + return org.hamcrest.core.IsInstanceOf.instanceOf(type); } /** - * This matcher always evaluates to true. + * Creates a matcher that wraps an existing matcher, but inverts the logic by which + * it will match. + * For example: + * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre> * - * @param description A meaningful string used when describing itself. + * @param matcher + * the matcher whose sense should be inverted */ - public static <T> org.hamcrest.Matcher<T> anything(java.lang.String description) { - return org.hamcrest.core.IsAnything.anything(description); + public static <T> org.hamcrest.Matcher<T> not(org.hamcrest.Matcher<T> matcher) { + return org.hamcrest.core.IsNot.not(matcher); } /** - * This matcher always evaluates to true. With type inference. + * A shortcut to the frequently used <code>not(equalTo(x))</code>. + * For example: + * <pre>assertThat(cheese, is(not(smelly)))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre> + * + * @param value + * the value that any examined object should <b>not</b> equal */ - public static <T> org.hamcrest.Matcher<T> any(java.lang.Class<T> type) { - return org.hamcrest.core.IsAnything.any(type); + public static <T> org.hamcrest.Matcher<T> not(T value) { + return org.hamcrest.core.IsNot.not(value); } /** - * Matches if value is null. + * A shortcut to the frequently used <code>not(nullValue())</code>. + * For example: + * <pre>assertThat(cheese, is(notNullValue()))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(nullValue())))</pre> */ - public static <T> org.hamcrest.Matcher<T> nullValue() { + public static org.hamcrest.Matcher<java.lang.Object> notNullValue() { + return org.hamcrest.core.IsNull.notNullValue(); + } + + /** + * A shortcut to the frequently used <code>not(nullValue(X.class)). Accepts a + * single dummy argument to facilitate type inference.</code>. + * For example: + * <pre>assertThat(cheese, is(notNullValue(X.class)))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(nullValue(X.class))))</pre> + * + * @param type + * dummy parameter used to infer the generic type of the returned matcher + */ + public static <T> org.hamcrest.Matcher<T> notNullValue(java.lang.Class<T> type) { + return org.hamcrest.core.IsNull.notNullValue(type); + } + + /** + * Creates a matcher that matches if examined object is <code>null</code>. + * For example: + * <pre>assertThat(cheese, is(nullValue())</pre> + */ + public static org.hamcrest.Matcher<java.lang.Object> nullValue() { return org.hamcrest.core.IsNull.nullValue(); } /** - * Matches if value is null. With type inference. + * Creates a matcher that matches if examined object is <code>null</code>. Accepts a + * single dummy argument to facilitate type inference. + * For example: + * <pre>assertThat(cheese, is(nullValue(Cheese.class))</pre> + * + * @param type + * dummy parameter used to infer the generic type of the returned matcher */ public static <T> org.hamcrest.Matcher<T> nullValue(java.lang.Class<T> type) { return org.hamcrest.core.IsNull.nullValue(type); } /** - * Matches if value is not null. + * Creates a matcher that matches only when the examined object is the same instance as + * the specified target object. + * + * @param target + * the target instance against which others should be assessed */ - public static <T> org.hamcrest.Matcher<T> notNullValue() { - return org.hamcrest.core.IsNull.notNullValue(); + public static <T> org.hamcrest.Matcher<T> sameInstance(T target) { + return org.hamcrest.core.IsSame.sameInstance(target); } /** - * Matches if value is not null. With type inference. + * Creates a matcher that matches only when the examined object is the same instance as + * the specified target object. + * + * @param target + * the target instance against which others should be assessed */ - public static <T> org.hamcrest.Matcher<T> notNullValue(java.lang.Class<T> type) { - return org.hamcrest.core.IsNull.notNullValue(type); + public static <T> org.hamcrest.Matcher<T> theInstance(T target) { + return org.hamcrest.core.IsSame.theInstance(target); } /** - * Wraps an existing matcher and overrides the description when it fails. + * Creates a matcher that matches if the examined {@link String} contains the specified + * {@link String} anywhere. + * For example: + * <pre>assertThat("myStringOfNote", containsString("ring"))</pre> + * + * @param substring + * the substring that the returned matcher will expect to find within any examined string */ - public static <T> org.hamcrest.Matcher<T> describedAs(java.lang.String description, org.hamcrest.Matcher<T> matcher, java.lang.Object... values) { - return org.hamcrest.core.DescribedAs.describedAs(description, matcher, values); + public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) { + return org.hamcrest.core.StringContains.containsString(substring); + } + + /** + * Creates a matcher that matches if the examined {@link String} contains the specified + * {@link String} anywhere, ignoring case. + * For example: + * <pre>assertThat("myStringOfNote", containsString("ring"))</pre> + * + * @param substring + * the substring that the returned matcher will expect to find within any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> containsStringIgnoringCase(java.lang.String substring) { + return org.hamcrest.core.StringContains.containsStringIgnoringCase(substring); + } + + /** + * <p> + * Creates a matcher that matches if the examined {@link String} starts with the specified + * {@link String}. + * </p> + * For example: + * <pre>assertThat("myStringOfNote", startsWith("my"))</pre> + * + * @param prefix + * the substring that the returned matcher will expect at the start of any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> startsWith(java.lang.String prefix) { + return org.hamcrest.core.StringStartsWith.startsWith(prefix); + } + + /** + * <p> + * Creates a matcher that matches if the examined {@link String} starts with the specified + * {@link String}, ignoring case + * </p> + * For example: + * <pre>assertThat("myStringOfNote", startsWith("my"))</pre> + * + * @param prefix + * the substring that the returned matcher will expect at the start of any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> startsWithIgnoringCase(java.lang.String prefix) { + return org.hamcrest.core.StringStartsWith.startsWithIgnoringCase(prefix); + } + + /** + * Creates a matcher that matches if the examined {@link String} ends with the specified + * {@link String}. + * For example: + * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre> + * + * @param suffix + * the substring that the returned matcher will expect at the end of any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> endsWith(java.lang.String suffix) { + return org.hamcrest.core.StringEndsWith.endsWith(suffix); + } + + /** + * Creates a matcher that matches if the examined {@link String} ends with the specified + * {@link String}, ignoring case. + * For example: + * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre> + * + * @param suffix + * the substring that the returned matcher will expect at the end of any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> endsWithIgnoringCase(java.lang.String suffix) { + return org.hamcrest.core.StringEndsWith.endsWithIgnoringCase(suffix); } } diff --git a/hamcrest-core/src/main/java/org/hamcrest/CustomMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/CustomMatcher.java new file mode 100644 index 0000000..036a764 --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/CustomMatcher.java @@ -0,0 +1,37 @@ +package org.hamcrest; + +/** + * Utility class for writing one off matchers. + * For example: + * <pre> + * Matcher<String> aNonEmptyString = new CustomMatcher<String>("a non empty string") { + * public boolean matches(Object object) { + * return ((object instanceof String) && !((String) object).isEmpty(); + * } + * }; + * </pre> + * <p> + * This class is designed for scenarios where an anonymous inner class + * matcher makes sense. It should not be used by API designers implementing + * matchers. + * + * @author Neil Dunn + * @see CustomTypeSafeMatcher for a type safe variant of this class that you probably + * want to use. + * @param <T> The type of object being matched. + */ +public abstract class CustomMatcher<T> extends BaseMatcher<T> { + private final String fixedDescription; + + public CustomMatcher(String description) { + if (description == null) { + throw new IllegalArgumentException("Description should be non null!"); + } + this.fixedDescription = description; + } + + @Override + public final void describeTo(Description description) { + description.appendText(fixedDescription); + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/CustomTypeSafeMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/CustomTypeSafeMatcher.java new file mode 100644 index 0000000..7c5c46c --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/CustomTypeSafeMatcher.java @@ -0,0 +1,39 @@ +package org.hamcrest; + + +/** + * Utility class for writing one off matchers. + * For example: + * <pre> + * Matcher<String> aNonEmptyString = new CustomTypeSafeMatcher<String>("a non empty string") { + * public boolean matchesSafely(String string) { + * return !string.isEmpty(); + * } + * public void describeMismatchSafely(String string, Description mismatchDescription) { + * mismatchDescription.appendText("was empty"); + * } + * }; + * </pre> + * This is a variant of {@link CustomMatcher} that first type checks + * the argument being matched. By the time {@link TypeSafeMatcher#matchesSafely} is + * is called the argument is guaranteed to be non-null and of the correct + * type. + * + * @author Neil Dunn + * @param <T> The type of object being matched + */ +public abstract class CustomTypeSafeMatcher<T> extends TypeSafeMatcher<T> { + private final String fixedDescription; + + public CustomTypeSafeMatcher(String description) { + if (description == null) { + throw new IllegalArgumentException("Description must be non null!"); + } + this.fixedDescription = description; + } + + @Override + public final void describeTo(Description description) { + description.appendText(fixedDescription); + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/Description.java b/hamcrest-core/src/main/java/org/hamcrest/Description.java index 36ddeda..73bfa38 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/Description.java +++ b/hamcrest-core/src/main/java/org/hamcrest/Description.java @@ -1,44 +1,89 @@ -package org.hamcrest;
-
-/**
- * A description of a Matcher. A Matcher will describe itself to a description
- * which can later be used for reporting.
- *
- * @see Matcher#describeTo(Description)
- */
-public interface Description {
-
- /**
- * Appends some plain text to the description.
- */
- Description appendText(String text);
-
- /**
- * Appends the description of a {@link SelfDescribing} value to this description.
- */
- Description appendDescriptionOf(SelfDescribing value);
-
- /**
- * Appends an arbitary value to the description.
- */
- Description appendValue(Object value);
-
- /**
- * Appends a list of values to the description.
- */
- <T> Description appendValueList(String start, String separator, String end,
- T... values);
-
- /**
- * Appends a list of values to the description.
- */
- <T> Description appendValueList(String start, String separator, String end,
- Iterable<T> values);
-
- /**
- * Appends a list of {@link org.hamcrest.SelfDescribing} objects
- * to the description.
- */
- Description appendList(String start, String separator, String end,
- Iterable<? extends SelfDescribing> values);
-}
+package org.hamcrest; + +/** + * A description of a Matcher. A Matcher will describe itself to a description + * which can later be used for reporting. + * + * @see Matcher#describeTo(Description) + */ +public interface Description { + /** + * A description that consumes input but does nothing. + */ + static final Description NONE = new NullDescription(); + + /** + * Appends some plain text to the description. + */ + Description appendText(String text); + + /** + * Appends the description of a {@link SelfDescribing} value to this description. + */ + Description appendDescriptionOf(SelfDescribing value); + + /** + * Appends an arbitrary value to the description. + */ + Description appendValue(Object value); + + /** + * Appends a list of values to the description. + */ + <T> Description appendValueList(String start, String separator, String end, + T... values); + + /** + * Appends a list of values to the description. + */ + <T> Description appendValueList(String start, String separator, String end, + Iterable<T> values); + + /** + * Appends a list of {@link org.hamcrest.SelfDescribing} objects + * to the description. + */ + Description appendList(String start, String separator, String end, + Iterable<? extends SelfDescribing> values); + + + public static final class NullDescription implements Description { + @Override + public Description appendDescriptionOf(SelfDescribing value) { + return this; + } + + @Override + public Description appendList(String start, String separator, + String end, Iterable<? extends SelfDescribing> values) { + return this; + } + + @Override + public Description appendText(String text) { + return this; + } + + @Override + public Description appendValue(Object value) { + return this; + } + + @Override + public <T> Description appendValueList(String start, String separator, + String end, T... values) { + return this; + } + + @Override + public <T> Description appendValueList(String start, String separator, + String end, Iterable<T> values) { + return this; + } + + @Override + public String toString() { + return ""; + } + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/DiagnosingMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/DiagnosingMatcher.java new file mode 100644 index 0000000..f87de2d --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/DiagnosingMatcher.java @@ -0,0 +1,21 @@ +package org.hamcrest; + +/** + * TODO(ngd): Document. + * + * @param <T> + */ +public abstract class DiagnosingMatcher<T> extends BaseMatcher<T> { + + @Override + public final boolean matches(Object item) { + return matches(item, Description.NONE); + } + + @Override + public final void describeMismatch(Object item, Description mismatchDescription) { + matches(item, mismatchDescription); + } + + protected abstract boolean matches(Object item, Description mismatchDescription); +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/Factory.java b/hamcrest-core/src/main/java/org/hamcrest/Factory.java index a8bf5f9..99a5132 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/Factory.java +++ b/hamcrest-core/src/main/java/org/hamcrest/Factory.java @@ -1,17 +1,20 @@ package org.hamcrest; -import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; -import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + /** * Marks a Hamcrest static factory method so tools recognise them. * A factory method is an equivalent to a named constructor. - * + * + * @deprecated The code generator is no longer maintained. Write classes of syntactic sugar by hand. * @author Joe Walnes */ @Retention(RUNTIME) @Target({METHOD}) +@Deprecated public @interface Factory { } diff --git a/hamcrest-core/src/main/java/org/hamcrest/FeatureMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/FeatureMatcher.java new file mode 100644 index 0000000..385cf99 --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/FeatureMatcher.java @@ -0,0 +1,54 @@ +package org.hamcrest; + +import org.hamcrest.internal.ReflectiveTypeFinder; + +/** + * Supporting class for matching a feature of an object. Implement <code>featureValueOf()</code> + * in a subclass to pull out the feature to be matched against. + * + * @param <T> The type of the object to be matched + * @param <U> The type of the feature to be matched + */ +public abstract class FeatureMatcher<T, U> extends TypeSafeDiagnosingMatcher<T> { + private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("featureValueOf", 1, 0); + private final Matcher<? super U> subMatcher; + private final String featureDescription; + private final String featureName; + + /** + * Constructor + * @param subMatcher The matcher to apply to the feature + * @param featureDescription Descriptive text to use in describeTo + * @param featureName Identifying text for mismatch message + */ + public FeatureMatcher(Matcher<? super U> subMatcher, String featureDescription, String featureName) { + super(TYPE_FINDER); + this.subMatcher = subMatcher; + this.featureDescription = featureDescription; + this.featureName = featureName; + } + + /** + * Implement this to extract the interesting feature. + * @param actual the target object + * @return the feature to be matched + */ + protected abstract U featureValueOf(T actual); + + @Override + protected boolean matchesSafely(T actual, Description mismatch) { + final U featureValue = featureValueOf(actual); + if (!subMatcher.matches(featureValue)) { + mismatch.appendText(featureName).appendText(" "); + subMatcher.describeMismatch(featureValue, mismatch); + return false; + } + return true; + } + + @Override + public final void describeTo(Description description) { + description.appendText(featureDescription).appendText(" ") + .appendDescriptionOf(subMatcher); + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/Matcher.java b/hamcrest-core/src/main/java/org/hamcrest/Matcher.java index fd10207..3ac1a53 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/Matcher.java +++ b/hamcrest-core/src/main/java/org/hamcrest/Matcher.java @@ -1,32 +1,31 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest; /** + * <p> * A matcher over acceptable values. * A matcher is able to describe itself to give feedback when it fails. - * <p/> + * </p> + * <p> * Matcher implementations should <b>NOT directly implement this interface</b>. * Instead, <b>extend</b> the {@link BaseMatcher} abstract class, * which will ensure that the Matcher API can grow to support * new features and remain compatible with all Matcher implementations. - * <p/> - * For easy access to common Matcher implementations, use the static factory - * methods in {@link CoreMatchers}. + * </p> + * <p> + * N.B. Well designed matchers should be immutable. + * </p> * - * @see CoreMatchers * @see BaseMatcher */ -@SuppressWarnings({"unused", "UnusedDeclaration"}) public interface Matcher<T> extends SelfDescribing { /** * Evaluates the matcher for argument <var>item</var>. - * <p/> + * * This method matches against Object, instead of the generic type T. This is * because the caller of the Matcher does not know at runtime what the type is * (because of type erasure with Java generics). It is down to the implementations - * to check the correct type. + * to check the correct type. * * @param item the object against which the matcher is evaluated. * @return <code>true</code> if <var>item</var> matches, otherwise <code>false</code>. @@ -34,6 +33,19 @@ public interface Matcher<T> extends SelfDescribing { * @see BaseMatcher */ boolean matches(Object item); + + /** + * Generate a description of why the matcher has not accepted the item. + * The description will be part of a larger description of why a matching + * failed, so it should be concise. + * This method assumes that <code>matches(item)</code> is false, but + * will not check this. + * + * @param item The item that the Matcher has rejected. + * @param mismatchDescription + * The description to be built or appended to. + */ + void describeMismatch(Object item, Description mismatchDescription); /** * This method simply acts a friendly reminder not to implement Matcher directly and @@ -42,6 +54,8 @@ public interface Matcher<T> extends SelfDescribing { * * @see Matcher for reasons why. * @see BaseMatcher + * @deprecated to make */ + @Deprecated void _dont_implement_Matcher___instead_extend_BaseMatcher_(); } diff --git a/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java b/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java index 3eb234a..049e1df 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java +++ b/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java @@ -1,24 +1,27 @@ -/* Copyright (c) 2000-2006 hamcrest.org
- */
-package org.hamcrest;
-
-
-public class MatcherAssert {
- public static <T> void assertThat(T actual, Matcher<T> matcher) {
- assertThat("", actual, matcher);
- }
-
- public static <T> void assertThat(String reason, T actual, Matcher<T> matcher) {
- if (!matcher.matches(actual)) {
- Description description = new StringDescription();
- description.appendText(reason)
- .appendText("\nExpected: ")
- .appendDescriptionOf(matcher)
- .appendText("\n got: ")
- .appendValue(actual)
- .appendText("\n");
-
- throw new java.lang.AssertionError(description.toString());
- }
- }
-}
+package org.hamcrest; + + +public class MatcherAssert { + public static <T> void assertThat(T actual, Matcher<? super T> matcher) { + assertThat("", actual, matcher); + } + + public static <T> void assertThat(String reason, T actual, Matcher<? super T> matcher) { + if (!matcher.matches(actual)) { + Description description = new StringDescription(); + description.appendText(reason) + .appendText("\nExpected: ") + .appendDescriptionOf(matcher) + .appendText("\n but: "); + matcher.describeMismatch(actual, description); + + throw new AssertionError(description.toString()); + } + } + + public static void assertThat(String reason, boolean assertion) { + if (!assertion) { + throw new AssertionError(reason); + } + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java b/hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java index cd53070..06b361d 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java +++ b/hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java @@ -12,5 +12,5 @@ public interface SelfDescribing { * @param description * The description to be built or appended to. */ - void describeTo(Description description); + void describeTo(Description description); }
\ No newline at end of file diff --git a/hamcrest-core/src/main/java/org/hamcrest/StringDescription.java b/hamcrest-core/src/main/java/org/hamcrest/StringDescription.java index 66709ee..813c178 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/StringDescription.java +++ b/hamcrest-core/src/main/java/org/hamcrest/StringDescription.java @@ -1,60 +1,63 @@ -package org.hamcrest;
-
-import java.io.IOException;
-
-/**
- * A {@link Description} that is stored as a string.
- */
-public class StringDescription extends BaseDescription {
- private final Appendable out;
-
- public StringDescription() {
- this(new StringBuilder());
- }
-
- public StringDescription(Appendable out) {
- this.out = out;
- }
-
- /**
- * Return the description of a {@link SelfDescribing} object as a String.
- *
- * @param selfDescribing
- * The object to be described.
- * @return
- * The description of the object.
- */
- public static String toString(SelfDescribing value) {
- return new StringDescription().appendDescriptionOf(value).toString();
- }
-
- /**
- * Alias for {@link #toString(SelfDescribing)}.
- */
- public static String asString(SelfDescribing selfDescribing) {
- return toString(selfDescribing);
- }
-
- protected void append(String str) {
- try {
- out.append(str);
- } catch (IOException e) {
- throw new RuntimeException("Could not write description", e);
- }
- }
-
- protected void append(char c) {
- try {
- out.append(c);
- } catch (IOException e) {
- throw new RuntimeException("Could not write description", e);
- }
- }
-
- /**
- * Returns the description as a string.
- */
- public String toString() {
- return out.toString();
- }
-}
+package org.hamcrest; + +import java.io.IOException; + +/** + * A {@link Description} that is stored as a string. + */ +public class StringDescription extends BaseDescription { + private final Appendable out; + + public StringDescription() { + this(new StringBuilder()); + } + + public StringDescription(Appendable out) { + this.out = out; + } + + /** + * Return the description of a {@link SelfDescribing} object as a String. + * + * @param selfDescribing + * The object to be described. + * @return + * The description of the object. + */ + public static String toString(SelfDescribing selfDescribing) { + return new StringDescription().appendDescriptionOf(selfDescribing).toString(); + } + + /** + * Alias for {@link #toString(SelfDescribing)}. + */ + public static String asString(SelfDescribing selfDescribing) { + return toString(selfDescribing); + } + + @Override + protected void append(String str) { + try { + out.append(str); + } catch (IOException e) { + throw new RuntimeException("Could not write description", e); + } + } + + @Override + protected void append(char c) { + try { + out.append(c); + } catch (IOException e) { + throw new RuntimeException("Could not write description", e); + } + } + + /** + * Returns the description as a string. + */ + @Override + public String toString() { + return out.toString(); + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/TypeSafeDiagnosingMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/TypeSafeDiagnosingMatcher.java new file mode 100644 index 0000000..c204120 --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/TypeSafeDiagnosingMatcher.java @@ -0,0 +1,69 @@ +package org.hamcrest; + +import org.hamcrest.internal.ReflectiveTypeFinder; + + +/** + * Convenient base class for Matchers that require a non-null value of a specific type + * and that will report why the received value has been rejected. + * This implements the null check, checks the type and then casts. + * To use, implement <pre>matchesSafely()</pre>. + * + * @param <T> + * @author Neil Dunn + * @author Nat Pryce + * @author Steve Freeman + */ +public abstract class TypeSafeDiagnosingMatcher<T> extends BaseMatcher<T> { + private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("matchesSafely", 2, 0); + private final Class<?> expectedType; + + /** + * Subclasses should implement this. The item will already have been checked + * for the specific type and will never be null. + */ + protected abstract boolean matchesSafely(T item, Description mismatchDescription); + + /** + * Use this constructor if the subclass that implements <code>matchesSafely</code> + * is <em>not</em> the class that binds <T> to a type. + * @param expectedType The expectedType of the actual value. + */ + protected TypeSafeDiagnosingMatcher(Class<?> expectedType) { + this.expectedType = expectedType; + } + + /** + * Use this constructor if the subclass that implements <code>matchesSafely</code> + * is <em>not</em> the class that binds <T> to a type. + * @param typeFinder A type finder to extract the type + */ + protected TypeSafeDiagnosingMatcher(ReflectiveTypeFinder typeFinder) { + this.expectedType = typeFinder.findExpectedType(getClass()); + } + + /** + * The default constructor for simple sub types + */ + protected TypeSafeDiagnosingMatcher() { + this(TYPE_FINDER); + } + + @Override + @SuppressWarnings("unchecked") + public final boolean matches(Object item) { + return item != null + && expectedType.isInstance(item) + && matchesSafely((T) item, new Description.NullDescription()); + } + + @SuppressWarnings("unchecked") + @Override + public final void describeMismatch(Object item, Description mismatchDescription) { + if (item == null || !expectedType.isInstance(item)) { + super.describeMismatch(item, mismatchDescription); + } else { + matchesSafely((T) item, mismatchDescription); + } + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java index 7f18fd3..08dfce8 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java +++ b/hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java @@ -1,58 +1,85 @@ package org.hamcrest; -import java.lang.reflect.Method; +import org.hamcrest.internal.ReflectiveTypeFinder; /** * Convenient base class for Matchers that require a non-null value of a specific type. * This simply implements the null check, checks the type and then casts. * * @author Joe Walnes + * @author Steve Freeman + * @author Nat Pryce */ public abstract class TypeSafeMatcher<T> extends BaseMatcher<T> { - - private Class expectedType; + private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("matchesSafely", 1, 0); + + final private Class<?> expectedType; /** - * Subclasses should implement this. The item will already have been checked for - * the specific type and will never be null. + * The default constructor for simple sub types */ - public abstract boolean matchesSafely(T item); - protected TypeSafeMatcher() { - expectedType = findExpectedType(getClass()); + this(TYPE_FINDER); } - - private static Class<?> findExpectedType(Class<?> fromClass) { - for (Class<?> c = fromClass; c != Object.class; c = c.getSuperclass()) { - for (Method method : c.getDeclaredMethods()) { - if (isMatchesSafelyMethod(method)) { - return method.getParameterTypes()[0]; - } - } - } - - throw new Error("Cannot determine correct type for matchesSafely() method."); + + /** + * Use this constructor if the subclass that implements <code>matchesSafely</code> + * is <em>not</em> the class that binds <T> to a type. + * @param expectedType The expectedType of the actual value. + */ + protected TypeSafeMatcher(Class<?> expectedType) { + this.expectedType = expectedType; } - private static boolean isMatchesSafelyMethod(Method method) { - return method.getName().equals("matchesSafely") - && method.getParameterTypes().length == 1 - && !method.isSynthetic(); + /** + * Use this constructor if the subclass that implements <code>matchesSafely</code> + * is <em>not</em> the class that binds <T> to a type. + * @param typeFinder A type finder to extract the type + */ + protected TypeSafeMatcher(ReflectiveTypeFinder typeFinder) { + this.expectedType = typeFinder.findExpectedType(getClass()); } + + /** + * Subclasses should implement this. The item will already have been checked for + * the specific type and will never be null. + */ + protected abstract boolean matchesSafely(T item); - protected TypeSafeMatcher(Class<T> expectedType) { - this.expectedType = expectedType; + /** + * Subclasses should override this. The item will already have been checked for + * the specific type and will never be null. + */ + protected void describeMismatchSafely(T item, Description mismatchDescription) { + super.describeMismatch(item, mismatchDescription); } - + /** - * Method made final to prevent accidental override. + * Methods made final to prevent accidental override. * If you need to override this, there's no point on extending TypeSafeMatcher. * Instead, extend the {@link BaseMatcher}. */ + @Override @SuppressWarnings({"unchecked"}) public final boolean matches(Object item) { return item != null && expectedType.isInstance(item) && matchesSafely((T) item); } + + @SuppressWarnings("unchecked") + @Override + final public void describeMismatch(Object item, Description description) { + if (item == null) { + super.describeMismatch(null, description); + } else if (! expectedType.isInstance(item)) { + description.appendText("was a ") + .appendText(item.getClass().getName()) + .appendText(" (") + .appendValue(item) + .appendText(")"); + } else { + describeMismatchSafely((T)item, description); + } + } } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java b/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java index f619a7d..2cbe2e3 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java @@ -1,51 +1,57 @@ package org.hamcrest.core; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Matcher; import org.hamcrest.Description; -import org.hamcrest.Factory; +import org.hamcrest.DiagnosingMatcher; +import org.hamcrest.Matcher; import java.util.Arrays; +import java.util.List; /** - * Calculates the logical conjunction of two matchers. Evaluation is - * shortcut, so that the second matcher is not called if the first - * matcher returns <code>false</code>. + * Calculates the logical conjunction of multiple matchers. Evaluation is shortcut, so + * subsequent matchers are not called if an earlier matcher returns <code>false</code>. */ -public class AllOf<T> extends BaseMatcher<T> { - private final Iterable<Matcher<? extends T>> matchers; +public class AllOf<T> extends DiagnosingMatcher<T> { - public AllOf(Iterable<Matcher<? extends T>> matchers) { + private final Iterable<Matcher<? super T>> matchers; + + public AllOf(Iterable<Matcher<? super T>> matchers) { this.matchers = matchers; } - public boolean matches(Object o) { - for (Matcher<? extends T> matcher : matchers) { + @Override + public boolean matches(Object o, Description mismatch) { + for (Matcher<? super T> matcher : matchers) { if (!matcher.matches(o)) { - return false; + mismatch.appendDescriptionOf(matcher).appendText(" "); + matcher.describeMismatch(o, mismatch); + return false; } } return true; } + @Override public void describeTo(Description description) { - description.appendList("(", " and ", ")", matchers); + description.appendList("(", " " + "and" + " ", ")", matchers); } /** - * Evaluates to true only if ALL of the passed in matchers evaluate to true. + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> */ - @Factory - public static <T> Matcher<T> allOf(Matcher<? extends T>... matchers) { - return allOf(Arrays.asList(matchers)); + public static <T> Matcher<T> allOf(Iterable<Matcher<? super T>> matchers) { + return new AllOf<>(matchers); } /** - * Evaluates to true only if ALL of the passed in matchers evaluate to true. + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> */ - @Factory - public static <T> Matcher<T> allOf(Iterable<Matcher<? extends T>> matchers) { - return new AllOf<T>(matchers); + @SafeVarargs + public static <T> Matcher<T> allOf(Matcher<? super T>... matchers) { + return allOf((List) Arrays.asList(matchers)); } - } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java b/hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java index e7e9181..106a473 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java @@ -1,51 +1,47 @@ package org.hamcrest.core; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Matcher; import org.hamcrest.Description; -import org.hamcrest.Factory; +import org.hamcrest.Matcher; import java.util.Arrays; +import java.util.List; /** - * Calculates the logical disjunction of two matchers. Evaluation is - * shortcut, so that the second matcher is not called if the first - * matcher returns <code>true</code>. + * Calculates the logical disjunction of multiple matchers. Evaluation is shortcut, so + * subsequent matchers are not called if an earlier matcher returns <code>true</code>. */ -public class AnyOf<T> extends BaseMatcher<T> { +public class AnyOf<T> extends ShortcutCombination<T> { - private final Iterable<Matcher<? extends T>> matchers; - - public AnyOf(Iterable<Matcher<? extends T>> matchers) { - this.matchers = matchers; + public AnyOf(Iterable<Matcher<? super T>> matchers) { + super(matchers); } + @Override public boolean matches(Object o) { - for (Matcher<? extends T> matcher : matchers) { - if (matcher.matches(o)) { - return true; - } - } - return false; + return matches(o, true); } + @Override public void describeTo(Description description) { - description.appendList("(", " or ", ")", matchers); + describeTo(description, "or"); } /** - * Evaluates to true if ANY of the passed in matchers evaluate to true. + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> */ - @Factory - public static <T> Matcher<T> anyOf(Matcher<? extends T>... matchers) { - return anyOf(Arrays.asList(matchers)); + public static <T> AnyOf<T> anyOf(Iterable<Matcher<? super T>> matchers) { + return new AnyOf<>(matchers); } - + /** - * Evaluates to true if ANY of the passed in matchers evaluate to true. + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> */ - @Factory - public static <T> Matcher<T> anyOf(Iterable<Matcher<? extends T>> matchers) { - return new AnyOf<T>(matchers); + @SafeVarargs + public static <T> AnyOf<T> anyOf(Matcher<? super T>... matchers) { + return anyOf((List) Arrays.asList(matchers)); } } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/CombinableMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/core/CombinableMatcher.java new file mode 100644 index 0000000..2414bbb --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/core/CombinableMatcher.java @@ -0,0 +1,82 @@ +package org.hamcrest.core; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; + +import java.util.ArrayList; + +public class CombinableMatcher<T> extends TypeSafeDiagnosingMatcher<T> { + private final Matcher<? super T> matcher; + + public CombinableMatcher(Matcher<? super T> matcher) { + this.matcher = matcher; + } + + @Override + protected boolean matchesSafely(T item, Description mismatch) { + if (!matcher.matches(item)) { + matcher.describeMismatch(item, mismatch); + return false; + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendDescriptionOf(matcher); + } + + public CombinableMatcher<T> and(Matcher<? super T> other) { + return new CombinableMatcher<T>(new AllOf<T>(templatedListWith(other))); + } + + public CombinableMatcher<T> or(Matcher<? super T> other) { + return new CombinableMatcher<T>(new AnyOf<T>(templatedListWith(other))); + } + + private ArrayList<Matcher<? super T>> templatedListWith(Matcher<? super T> other) { + ArrayList<Matcher<? super T>> matchers = new ArrayList<Matcher<? super T>>(); + matchers.add(matcher); + matchers.add(other); + return matchers; + } + + /** + * Creates a matcher that matches when both of the specified matchers match the examined object. + * For example: + * <pre>assertThat("fab", both(containsString("a")).and(containsString("b")))</pre> + */ + public static <LHS> CombinableBothMatcher<LHS> both(Matcher<? super LHS> matcher) { + return new CombinableBothMatcher<LHS>(matcher); + } + + public static final class CombinableBothMatcher<X> { + private final Matcher<? super X> first; + public CombinableBothMatcher(Matcher<? super X> matcher) { + this.first = matcher; + } + public CombinableMatcher<X> and(Matcher<? super X> other) { + return new CombinableMatcher<X>(first).and(other); + } + } + + /** + * Creates a matcher that matches when either of the specified matchers match the examined object. + * For example: + * <pre>assertThat("fan", either(containsString("a")).or(containsString("b")))</pre> + */ + public static <LHS> CombinableEitherMatcher<LHS> either(Matcher<? super LHS> matcher) { + return new CombinableEitherMatcher<LHS>(matcher); + } + + public static final class CombinableEitherMatcher<X> { + private final Matcher<? super X> first; + public CombinableEitherMatcher(Matcher<? super X> matcher) { + this.first = matcher; + } + public CombinableMatcher<X> or(Matcher<? super X> other) { + return new CombinableMatcher<X>(first).or(other); + } + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java b/hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java index 7b8c151..2387609 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java @@ -1,55 +1,69 @@ -/* Copyright (c) 2000-2006 hamcrest.org
- */
-package org.hamcrest.core;
-
-import java.util.regex.Pattern;
-
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.BaseMatcher;
-
-/**
- * Provides a custom description to another matcher.
- */
-public class DescribedAs<T> extends BaseMatcher<T> {
- private final String descriptionTemplate;
- private final Matcher<T> matcher;
- private final Object[] values;
-
- private final static Pattern ARG_PATTERN = Pattern.compile("%([0-9]+)");
-
- public DescribedAs(String descriptionTemplate, Matcher<T> matcher, Object[] values) {
- this.descriptionTemplate = descriptionTemplate;
- this.matcher = matcher;
- this.values = values.clone();
- }
-
- public boolean matches(Object o) {
- return matcher.matches(o);
- }
-
- public void describeTo(Description description) {
- java.util.regex.Matcher arg = ARG_PATTERN.matcher(descriptionTemplate);
-
- int textStart = 0;
- while (arg.find()) {
- description.appendText(descriptionTemplate.substring(textStart, arg.start()));
- int argIndex = Integer.parseInt(arg.group(1));
- description.appendValue(values[argIndex]);
- textStart = arg.end();
- }
-
- if (textStart < descriptionTemplate.length()) {
- description.appendText(descriptionTemplate.substring(textStart));
- }
- }
-
- /**
- * Wraps an existing matcher and overrides the description when it fails.
- */
- @Factory
- public static <T> Matcher<T> describedAs(String description, Matcher<T> matcher, Object... values) {
- return new DescribedAs<T>(description, matcher, values);
- }
-}
+package org.hamcrest.core; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; + +import java.util.regex.Pattern; + +import static java.lang.Integer.parseInt; + +/** + * Provides a custom description to another matcher. + */ +public class DescribedAs<T> extends BaseMatcher<T> { + private final String descriptionTemplate; + private final Matcher<T> matcher; + private final Object[] values; + + private final static Pattern ARG_PATTERN = Pattern.compile("%([0-9]+)"); + + public DescribedAs(String descriptionTemplate, Matcher<T> matcher, Object[] values) { + this.descriptionTemplate = descriptionTemplate; + this.matcher = matcher; + this.values = values.clone(); + } + + @Override + public boolean matches(Object o) { + return matcher.matches(o); + } + + @Override + public void describeTo(Description description) { + java.util.regex.Matcher arg = ARG_PATTERN.matcher(descriptionTemplate); + + int textStart = 0; + while (arg.find()) { + description.appendText(descriptionTemplate.substring(textStart, arg.start())); + description.appendValue(values[parseInt(arg.group(1))]); + textStart = arg.end(); + } + + if (textStart < descriptionTemplate.length()) { + description.appendText(descriptionTemplate.substring(textStart)); + } + } + + @Override + public void describeMismatch(Object item, Description description) { + matcher.describeMismatch(item, description); + } + + /** + * Wraps an existing matcher, overriding its description with that specified. All other functions are + * delegated to the decorated matcher, including its mismatch description. + * For example: + * <pre>describedAs("a big decimal equal to %0", equalTo(myBigDecimal), myBigDecimal.toPlainString())</pre> + * + * @param description + * the new description for the wrapped matcher + * @param matcher + * the matcher to wrap + * @param values + * optional values to insert into the tokenised description + */ + public static <T> Matcher<T> describedAs(String description, Matcher<T> matcher, Object... values) { + return new DescribedAs<T>(description, matcher, values); + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/Every.java b/hamcrest-core/src/main/java/org/hamcrest/core/Every.java new file mode 100644 index 0000000..757b7b4 --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/core/Every.java @@ -0,0 +1,44 @@ +package org.hamcrest.core; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; + +public class Every<T> extends TypeSafeDiagnosingMatcher<Iterable<? extends T>> { + private final Matcher<? super T> matcher; + + public Every(Matcher<? super T> matcher) { + this.matcher= matcher; + } + + @Override + public boolean matchesSafely(Iterable<? extends T> collection, Description mismatchDescription) { + for (T t : collection) { + if (!matcher.matches(t)) { + mismatchDescription.appendText("an item "); + matcher.describeMismatch(t, mismatchDescription); + return false; + } + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("every item is ").appendDescriptionOf(matcher); + } + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields items that are all matched by the specified + * <code>itemMatcher</code>. + * For example: + * <pre>assertThat(Arrays.asList("bar", "baz"), everyItem(startsWith("ba")))</pre> + * + * @param itemMatcher + * the matcher to apply to every item provided by the examined {@link Iterable} + */ + public static <U> Matcher<Iterable<? extends U>> everyItem(final Matcher<U> itemMatcher) { + return new Every<U>(itemMatcher); + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/Is.java b/hamcrest-core/src/main/java/org/hamcrest/core/Is.java index f9152e9..ec22238 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/Is.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/Is.java @@ -1,68 +1,76 @@ package org.hamcrest.core; -import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.hamcrest.core.IsEqual.equalTo; -import org.hamcrest.Factory; -import org.hamcrest.Matcher; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; +import org.hamcrest.Matcher; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsInstanceOf.instanceOf; /** - * Decorates another Matcher, retaining the behavior but allowing tests + * Decorates another Matcher, retaining the behaviour but allowing tests * to be slightly more expressive. * - * eg. assertThat(cheese, equalTo(smelly)) - * vs assertThat(cheese, is(equalTo(smelly))) + * For example: assertThat(cheese, equalTo(smelly)) + * vs. assertThat(cheese, is(equalTo(smelly))) */ public class Is<T> extends BaseMatcher<T> { - private final Matcher<T> matcher; public Is(Matcher<T> matcher) { this.matcher = matcher; } + @Override public boolean matches(Object arg) { return matcher.matches(arg); } + @Override public void describeTo(Description description) { description.appendText("is ").appendDescriptionOf(matcher); } - + + @Override + public void describeMismatch(Object item, Description mismatchDescription) { + matcher.describeMismatch(item, mismatchDescription); + } + /** - * Decorates another Matcher, retaining the behavior but allowing tests + * Decorates another Matcher, retaining its behaviour, but allowing tests * to be slightly more expressive. - * - * eg. assertThat(cheese, equalTo(smelly)) - * vs assertThat(cheese, is(equalTo(smelly))) + * For example: + * <pre>assertThat(cheese, is(equalTo(smelly)))</pre> + * instead of: + * <pre>assertThat(cheese, equalTo(smelly))</pre> + * */ - @Factory public static <T> Matcher<T> is(Matcher<T> matcher) { return new Is<T>(matcher); } /** - * This is a shortcut to the frequently used is(equalTo(x)). - * - * eg. assertThat(cheese, is(equalTo(smelly))) - * vs assertThat(cheese, is(smelly)) + * A shortcut to the frequently used <code>is(equalTo(x))</code>. + * For example: + * <pre>assertThat(cheese, is(smelly))</pre> + * instead of: + * <pre>assertThat(cheese, is(equalTo(smelly)))</pre> + * */ - @Factory public static <T> Matcher<T> is(T value) { return is(equalTo(value)); } /** - * This is a shortcut to the frequently used is(instanceOf(SomeClass.class)). - * - * eg. assertThat(cheese, is(instanceOf(Cheddar.class))) - * vs assertThat(cheese, is(Cheddar.class)) + * A shortcut to the frequently used <code>is(instanceOf(SomeClass.class))</code>. + * For example: + * <pre>assertThat(cheese, isA(Cheddar.class))</pre> + * instead of: + * <pre>assertThat(cheese, is(instanceOf(Cheddar.class)))</pre> + * */ - @Factory - public static Matcher<Object> is(Class<?> type) { - return is(instanceOf(type)); + public static <T> Matcher<T> isA(Class<T> type) { + final Matcher<T> typeMatcher = instanceOf(type); + return is(typeMatcher); } - } - diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java index c5ca49d..4c71a9b 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java @@ -1,11 +1,8 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest.core; +import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.BaseMatcher; /** @@ -13,47 +10,41 @@ import org.hamcrest.BaseMatcher; */ public class IsAnything<T> extends BaseMatcher<T> { - private final String description; + private final String message; public IsAnything() { this("ANYTHING"); } - public IsAnything(String description) { - this.description = description; + public IsAnything(String message) { + this.message = message; } + @Override public boolean matches(Object o) { return true; } + @Override public void describeTo(Description description) { - description.appendText(this.description); + description.appendText(message); } /** - * This matcher always evaluates to true. + * Creates a matcher that always matches, regardless of the examined object. */ - @Factory - public static <T> Matcher<T> anything() { - return new IsAnything<T>(); + public static Matcher<Object> anything() { + return new IsAnything<Object>(); } /** - * This matcher always evaluates to true. + * Creates a matcher that always matches, regardless of the examined object, but describes + * itself with the specified {@link String}. * - * @param description A meaningful string used when describing itself. - */ - @Factory - public static <T> Matcher<T> anything(String description) { - return new IsAnything<T>(description); - } - - /** - * This matcher always evaluates to true. With type inference. + * @param description + * a meaningful {@link String} used when describing itself */ - @Factory - public static <T> Matcher<T> any(@SuppressWarnings("unused")Class<T> type) { - return new IsAnything<T>(); + public static Matcher<Object> anything(String description) { + return new IsAnything<Object>(description); } } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java new file mode 100644 index 0000000..c55853d --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java @@ -0,0 +1,133 @@ +package org.hamcrest.core; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.core.AllOf.allOf; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsCollectionContaining<T> extends TypeSafeDiagnosingMatcher<Iterable<? super T>> { + private final Matcher<? super T> elementMatcher; + + public IsCollectionContaining(Matcher<? super T> elementMatcher) { + this.elementMatcher = elementMatcher; + } + + @Override + protected boolean matchesSafely(Iterable<? super T> collection, Description mismatchDescription) { + if (isEmpty(collection)) { + mismatchDescription.appendText("was empty"); + return false; + } + + for (Object item : collection) { + if (elementMatcher.matches(item)) { + return true; + } + } + + mismatchDescription.appendText("mismatches were: ["); + boolean isPastFirst = false; + for (Object item : collection) { + if (isPastFirst) { + mismatchDescription.appendText(", "); + } + elementMatcher.describeMismatch(item, mismatchDescription); + isPastFirst = true; + } + mismatchDescription.appendText("]"); + return false; + } + + private boolean isEmpty(Iterable<? super T> iterable) { + return ! iterable.iterator().hasNext(); + } + + @Override + public void describeTo(Description description) { + description + .appendText("a collection containing ") + .appendDescriptionOf(elementMatcher); + } + + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields at least one item that is matched by the specified + * <code>itemMatcher</code>. Whilst matching, the traversal of the examined {@link Iterable} + * will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem(startsWith("ba")))</pre> + * + * @param itemMatcher + * the matcher to apply to items provided by the examined {@link Iterable} + */ + public static <T> Matcher<Iterable<? super T>> hasItem(Matcher<? super T> itemMatcher) { + return new IsCollectionContaining<>(itemMatcher); + } + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields at least one item that is equal to the specified + * <code>item</code>. Whilst matching, the traversal of the examined {@link Iterable} + * will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem("bar"))</pre> + * + * @param item + * the item to compare against the items provided by the examined {@link Iterable} + */ + public static <T> Matcher<Iterable<? super T>> hasItem(T item) { + // Doesn't forward to hasItem() method so compiler can sort out generics. + return new IsCollectionContaining<>(equalTo(item)); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the + * examined {@link Iterable} yield at least one item that is matched by the corresponding + * matcher from the specified <code>itemMatchers</code>. Whilst matching, each traversal of + * the examined {@link Iterable} will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems(endsWith("z"), endsWith("o")))</pre> + * + * @param itemMatchers + * the matchers to apply to items provided by the examined {@link Iterable} + */ + @SafeVarargs + public static <T> Matcher<Iterable<T>> hasItems(Matcher<? super T>... itemMatchers) { + List<Matcher<? super Iterable<T>>> all = new ArrayList<>(itemMatchers.length); + + for (Matcher<? super T> elementMatcher : itemMatchers) { + // Doesn't forward to hasItem() method so compiler can sort out generics. + all.add(new IsCollectionContaining<>(elementMatcher)); + } + + return allOf(all); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the + * examined {@link Iterable} yield at least one item that is equal to the corresponding + * item from the specified <code>items</code>. Whilst matching, each traversal of the + * examined {@link Iterable} will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems("baz", "foo"))</pre> + * + * @param items + * the items to compare against the items provided by the examined {@link Iterable} + */ + @SafeVarargs + public static <T> Matcher<Iterable<T>> hasItems(T... items) { + List<Matcher<? super Iterable<T>>> all = new ArrayList<>(items.length); + for (T item : items) { + all.add(hasItem(item)); + } + + return allOf(all); + } + +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java index b9f17c5..860e85e 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java @@ -1,11 +1,8 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest.core; +import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.BaseMatcher; import java.lang.reflect.Array; @@ -15,42 +12,47 @@ import java.lang.reflect.Array; * {@link java.lang.Object#equals} invokedMethod? */ public class IsEqual<T> extends BaseMatcher<T> { - private final Object object; + private final Object expectedValue; public IsEqual(T equalArg) { - object = equalArg; + expectedValue = equalArg; } - public boolean matches(Object arg) { - return areEqual(object, arg); + @Override + public boolean matches(Object actualValue) { + return areEqual(actualValue, expectedValue); } + @Override public void describeTo(Description description) { - description.appendValue(object); + description.appendValue(expectedValue); } - private static boolean areEqual(Object o1, Object o2) { - if (o1 == null || o2 == null) { - return o1 == null && o2 == null; - } else if (isArray(o1)) { - return isArray(o2) && areArraysEqual(o1, o2); - } else { - return o1.equals(o2); + private static boolean areEqual(Object actual, Object expected) { + if (actual == null) { + return expected == null; + } + + if (expected != null && isArray(actual)) { + return isArray(expected) && areArraysEqual(actual, expected); } + + return actual.equals(expected); } - private static boolean areArraysEqual(Object o1, Object o2) { - return areArrayLengthsEqual(o1, o2) - && areArrayElementsEqual(o1, o2); + private static boolean areArraysEqual(Object actualArray, Object expectedArray) { + return areArrayLengthsEqual(actualArray, expectedArray) && areArrayElementsEqual(actualArray, expectedArray); } - private static boolean areArrayLengthsEqual(Object o1, Object o2) { - return Array.getLength(o1) == Array.getLength(o2); + private static boolean areArrayLengthsEqual(Object actualArray, Object expectedArray) { + return Array.getLength(actualArray) == Array.getLength(expectedArray); } - private static boolean areArrayElementsEqual(Object o1, Object o2) { - for (int i = 0; i < Array.getLength(o1); i++) { - if (!areEqual(Array.get(o1, i), Array.get(o2, i))) return false; + private static boolean areArrayElementsEqual(Object actualArray, Object expectedArray) { + for (int i = 0; i < Array.getLength(actualArray); i++) { + if (!areEqual(Array.get(actualArray, i), Array.get(expectedArray, i))) { + return false; + } } return true; } @@ -60,12 +62,36 @@ public class IsEqual<T> extends BaseMatcher<T> { } /** - * Is the value equal to another value, as tested by the - * {@link java.lang.Object#equals} invokedMethod? + * Creates a matcher that matches when the examined object is logically equal to the specified + * <code>operand</code>, as determined by calling the {@link java.lang.Object#equals} method on + * the <b>examined</b> object. + * + * <p>If the specified operand is <code>null</code> then the created matcher will only match if + * the examined object's <code>equals</code> method returns <code>true</code> when passed a + * <code>null</code> (which would be a violation of the <code>equals</code> contract), unless the + * examined object itself is <code>null</code>, in which case the matcher will return a positive + * match.</p> + * + * <p>The created matcher provides a special behaviour when examining <code>Array</code>s, whereby + * it will match if both the operand and the examined object are arrays of the same length and + * contain items that are equal to each other (according to the above rules) <b>in the same + * indexes</b>.</p> + * For example: + * <pre> + * assertThat("foo", equalTo("foo")); + * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"})); + * </pre> + * */ - @Factory public static <T> Matcher<T> equalTo(T operand) { return new IsEqual<T>(operand); } - + + /** + * Creates an {@link org.hamcrest.core.IsEqual} matcher that does not enforce the values being + * compared to be of the same static type. + */ + public static Matcher<Object> equalToObject(Object operand) { + return new IsEqual<Object>(operand); + } } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java index df20824..5a508c9 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java @@ -1,44 +1,91 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest.core; import org.hamcrest.Description; +import org.hamcrest.DiagnosingMatcher; import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.BaseMatcher; /** * Tests whether the value is an instance of a class. + * Classes of basic types will be converted to the relevant "Object" classes */ -public class IsInstanceOf extends BaseMatcher<Object> { - private final Class<?> theClass; +public class IsInstanceOf extends DiagnosingMatcher<Object> { + private final Class<?> expectedClass; + private final Class<?> matchableClass; /** * Creates a new instance of IsInstanceOf * - * @param theClass The predicate evaluates to true for instances of this class + * @param expectedClass The predicate evaluates to true for instances of this class * or one of its subclasses. */ - public IsInstanceOf(Class<?> theClass) { - this.theClass = theClass; + public IsInstanceOf(Class<?> expectedClass) { + this.expectedClass = expectedClass; + this.matchableClass = matchableClass(expectedClass); + } + + private static Class<?> matchableClass(Class<?> expectedClass) { + if (boolean.class.equals(expectedClass)) return Boolean.class; + if (byte.class.equals(expectedClass)) return Byte.class; + if (char.class.equals(expectedClass)) return Character.class; + if (double.class.equals(expectedClass)) return Double.class; + if (float.class.equals(expectedClass)) return Float.class; + if (int.class.equals(expectedClass)) return Integer.class; + if (long.class.equals(expectedClass)) return Long.class; + if (short.class.equals(expectedClass)) return Short.class; + return expectedClass; } - public boolean matches(Object item) { - return theClass.isInstance(item); + @Override + protected boolean matches(Object item, Description mismatch) { + if (null == item) { + mismatch.appendText("null"); + return false; + } + + if (!matchableClass.isInstance(item)) { + mismatch.appendValue(item).appendText(" is a " + item.getClass().getName()); + return false; + } + + return true; } + @Override public void describeTo(Description description) { - description.appendText("an instance of ") - .appendText(theClass.getName()); + description.appendText("an instance of ").appendText(expectedClass.getName()); } /** - * Is the value an instance of a particular type? + * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>, + * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the + * the examined object. + * + * <p>The created matcher assumes no relationship between specified type and the examined object.</p> + * For example: + * <pre>assertThat(new Canoe(), instanceOf(Paddlable.class));</pre> + * + */ + @SuppressWarnings("unchecked") + public static <T> Matcher<T> instanceOf(Class<?> type) { + return (Matcher<T>) new IsInstanceOf(type); + } + + /** + * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>, + * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the + * the examined object. + * + * <p>The created matcher forces a relationship between specified type and the examined object, and should be + * used when it is necessary to make generics conform, for example in the JMock clause + * <code>with(any(Thing.class))</code></p> + * For example: + * <pre>assertThat(new Canoe(), instanceOf(Canoe.class));</pre> + * */ - @Factory - public static Matcher<Object> instanceOf(Class<?> type) { - return new IsInstanceOf(type); + @SuppressWarnings("unchecked") + public static <T> Matcher<T> any(Class<T> type) { + return (Matcher<T>) new IsInstanceOf(type); } } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java index cb6946c..d5cf9c0 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java @@ -1,49 +1,57 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest.core; -import static org.hamcrest.core.IsEqual.equalTo; +import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.BaseMatcher; + +import static org.hamcrest.core.IsEqual.equalTo; /** * Calculates the logical negation of a matcher. */ -public class IsNot<T> extends BaseMatcher<T> { +public class IsNot<T> extends BaseMatcher<T> { private final Matcher<T> matcher; public IsNot(Matcher<T> matcher) { this.matcher = matcher; } + @Override public boolean matches(Object arg) { return !matcher.matches(arg); } + @Override public void describeTo(Description description) { description.appendText("not ").appendDescriptionOf(matcher); } + /** - * Inverts the rule. + * Creates a matcher that wraps an existing matcher, but inverts the logic by which + * it will match. + * For example: + * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre> + * + * @param matcher + * the matcher whose sense should be inverted */ - @Factory public static <T> Matcher<T> not(Matcher<T> matcher) { return new IsNot<T>(matcher); } /** - * This is a shortcut to the frequently used not(equalTo(x)). - * - * eg. assertThat(cheese, is(not(equalTo(smelly)))) - * vs assertThat(cheese, is(not(smelly))) + * A shortcut to the frequently used <code>not(equalTo(x))</code>. + * For example: + * <pre>assertThat(cheese, is(not(smelly)))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre> + * + * @param value + * the value that any examined object should <b>not</b> equal */ - @Factory public static <T> Matcher<T> not(T value) { return not(equalTo(value)); } - } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java index 737dcf2..9ebf080 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java @@ -1,55 +1,74 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest.core; -import static org.hamcrest.core.IsNot.not; +import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.BaseMatcher; + +import static org.hamcrest.core.IsNot.not; /** * Is the value null? */ public class IsNull<T> extends BaseMatcher<T> { + @Override public boolean matches(Object o) { return o == null; } + @Override public void describeTo(Description description) { description.appendText("null"); } /** - * Matches if value is null. + * Creates a matcher that matches if examined object is <code>null</code>. + * For example: + * <pre>assertThat(cheese, is(nullValue())</pre> + * */ - @Factory - public static <T> Matcher<T> nullValue() { - return new IsNull<T>(); + public static Matcher<Object> nullValue() { + return new IsNull<Object>(); } /** - * Matches if value is not null. + * A shortcut to the frequently used <code>not(nullValue())</code>. + * For example: + * <pre>assertThat(cheese, is(notNullValue()))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(nullValue())))</pre> + * */ - @Factory - public static <T> Matcher<T> notNullValue() { - return not(IsNull.<T>nullValue()); + public static Matcher<Object> notNullValue() { + return not(nullValue()); } /** - * Matches if value is null. With type inference. + * Creates a matcher that matches if examined object is <code>null</code>. Accepts a + * single dummy argument to facilitate type inference. + * For example: + * <pre>assertThat(cheese, is(nullValue(Cheese.class))</pre> + * + * @param type + * dummy parameter used to infer the generic type of the returned matcher */ - @Factory - public static <T> Matcher<T> nullValue(@SuppressWarnings("unused") Class<T> type) { - return nullValue(); + public static <T> Matcher<T> nullValue(Class<T> type) { + return new IsNull<T>(); } /** - * Matches if value is not null. With type inference. + * A shortcut to the frequently used <code>not(nullValue(X.class)). Accepts a + * single dummy argument to facilitate type inference.</code>. + * For example: + * <pre>assertThat(cheese, is(notNullValue(X.class)))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(nullValue(X.class))))</pre> + * + * @param type + * dummy parameter used to infer the generic type of the returned matcher + * */ - @Factory - public static <T> Matcher<T> notNullValue(@SuppressWarnings("unused") Class<T> type) { - return notNullValue(); + public static <T> Matcher<T> notNullValue(Class<T> type) { + return not(nullValue(type)); } } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java b/hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java index b3ad77e..cbc3971 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java +++ b/hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java @@ -1,11 +1,8 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest.core; +import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.BaseMatcher; /** @@ -13,28 +10,42 @@ import org.hamcrest.BaseMatcher; */ public class IsSame<T> extends BaseMatcher<T> { private final T object; - + public IsSame(T object) { this.object = object; } + @Override public boolean matches(Object arg) { return arg == object; } + @Override public void describeTo(Description description) { - description.appendText("same(") .appendValue(object) .appendText(")"); + description.appendText("sameInstance(") + .appendValue(object) + .appendText(")"); } - + /** - * Creates a new instance of IsSame + * Creates a matcher that matches only when the examined object is the same instance as + * the specified target object. * - * @param object The predicate evaluates to true only when the argument is - * this object. + * @param target + * the target instance against which others should be assessed */ - @Factory - public static <T> Matcher<T> sameInstance(T object) { - return new IsSame<T>(object); + public static <T> Matcher<T> sameInstance(T target) { + return new IsSame<T>(target); + } + + /** + * Creates a matcher that matches only when the examined object is the same instance as + * the specified target object. + * + * @param target + * the target instance against which others should be assessed + */ + public static <T> Matcher<T> theInstance(T target) { + return new IsSame<T>(target); } - } diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/ShortcutCombination.java b/hamcrest-core/src/main/java/org/hamcrest/core/ShortcutCombination.java new file mode 100644 index 0000000..30b33af --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/core/ShortcutCombination.java @@ -0,0 +1,33 @@ +package org.hamcrest.core; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; + +abstract class ShortcutCombination<T> extends BaseMatcher<T> { + + private final Iterable<Matcher<? super T>> matchers; + + public ShortcutCombination(Iterable<Matcher<? super T>> matchers) { + this.matchers = matchers; + } + + @Override + public abstract boolean matches(Object o); + + @Override + public abstract void describeTo(Description description); + + protected boolean matches(Object o, boolean shortcut) { + for (Matcher<? super T> matcher : matchers) { + if (matcher.matches(o) == shortcut) { + return shortcut; + } + } + return !shortcut; + } + + public void describeTo(Description description, String operator) { + description.appendList("(", " " + operator + " ", ")", matchers); + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/StringContains.java b/hamcrest-core/src/main/java/org/hamcrest/core/StringContains.java new file mode 100644 index 0000000..9e0a4ab --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/core/StringContains.java @@ -0,0 +1,46 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; + +/** + * Tests if the argument is a string that contains a substring. + */ +public class StringContains extends SubstringMatcher { + public StringContains(boolean ignoringCase, String substring) { + super("containing", ignoringCase, substring); + } + + @Override + protected boolean evalSubstringOf(String s) { + return converted(s).contains(converted(substring)); + } + + /** + * Creates a matcher that matches if the examined {@link String} contains the specified + * {@link String} anywhere. + * For example: + * <pre>assertThat("myStringOfNote", containsString("ring"))</pre> + * + * @param substring + * the substring that the returned matcher will expect to find within any examined string + * + */ + public static Matcher<String> containsString(String substring) { + return new StringContains(false, substring); + } + + /** + * Creates a matcher that matches if the examined {@link String} contains the specified + * {@link String} anywhere, ignoring case. + * For example: + * <pre>assertThat("myStringOfNote", containsString("ring"))</pre> + * + * @param substring + * the substring that the returned matcher will expect to find within any examined string + * + */ + public static Matcher<String> containsStringIgnoringCase(String substring) { + return new StringContains(true, substring); + } + +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/StringEndsWith.java b/hamcrest-core/src/main/java/org/hamcrest/core/StringEndsWith.java new file mode 100644 index 0000000..6a6d1a0 --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/core/StringEndsWith.java @@ -0,0 +1,42 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; + +/** + * Tests if the argument is a string that contains a substring. + */ +public class StringEndsWith extends SubstringMatcher { + public StringEndsWith(boolean ignoringCase, String substring) { super("ending with", ignoringCase, substring); } + + @Override + protected boolean evalSubstringOf(String s) { + return converted(s).endsWith(converted(substring)); + } + + /** + * Creates a matcher that matches if the examined {@link String} ends with the specified + * {@link String}. + * For example: + * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre> + * + * @param suffix + * the substring that the returned matcher will expect at the end of any examined string + */ + public static Matcher<String> endsWith(String suffix) { + return new StringEndsWith(false, suffix); + } + + /** + * Creates a matcher that matches if the examined {@link String} ends with the specified + * {@link String}, ignoring case. + * For example: + * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre> + * + * @param suffix + * the substring that the returned matcher will expect at the end of any examined string + */ + public static Matcher<String> endsWithIgnoringCase(String suffix) { + return new StringEndsWith(true, suffix); + } + +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/StringStartsWith.java b/hamcrest-core/src/main/java/org/hamcrest/core/StringStartsWith.java new file mode 100644 index 0000000..fe7b990 --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/core/StringStartsWith.java @@ -0,0 +1,40 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; + +/** + * Tests if the argument is a string that contains a substring. + */ +public class StringStartsWith extends SubstringMatcher { + public StringStartsWith(boolean ignoringCase, String substring) { super("starting with", ignoringCase, substring); } + + @Override + protected boolean evalSubstringOf(String s) { return converted(s).startsWith(converted(substring)); } + + /** + * <p> + * Creates a matcher that matches if the examined {@link String} starts with the specified + * {@link String}. + * </p> + * For example: + * <pre>assertThat("myStringOfNote", startsWith("my"))</pre> + * + * @param prefix + * the substring that the returned matcher will expect at the start of any examined string + */ + public static Matcher<String> startsWith(String prefix) { return new StringStartsWith(false, prefix); } + + /** + * <p> + * Creates a matcher that matches if the examined {@link String} starts with the specified + * {@link String}, ignoring case + * </p> + * For example: + * <pre>assertThat("myStringOfNote", startsWith("my"))</pre> + * + * @param prefix + * the substring that the returned matcher will expect at the start of any examined string + */ + public static Matcher<String> startsWithIgnoringCase(String prefix) { return new StringStartsWith(true, prefix); } + +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/core/SubstringMatcher.java b/hamcrest-core/src/main/java/org/hamcrest/core/SubstringMatcher.java new file mode 100644 index 0000000..85c6657 --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/core/SubstringMatcher.java @@ -0,0 +1,44 @@ +package org.hamcrest.core; + +import org.hamcrest.Description; +import org.hamcrest.TypeSafeMatcher; + +public abstract class SubstringMatcher extends TypeSafeMatcher<String> { + + // TODO: Replace String with CharSequence to allow for easy interoperability between + // String, StringBuffer, StringBuilder, CharBuffer, etc (joe). + + private final String relationship; + private final boolean ignoringCase; + protected final String substring; + + protected SubstringMatcher(String relationship, boolean ignoringCase, String substring) { + this.relationship = relationship; + this.ignoringCase = ignoringCase; + this.substring = substring; + } + + @Override + public boolean matchesSafely(String item) { + return evalSubstringOf(ignoringCase ? item.toLowerCase() :item); + } + @Override + public void describeMismatchSafely(String item, Description mismatchDescription) { + mismatchDescription.appendText("was \"").appendText(item).appendText("\""); + } + + @Override + public void describeTo(Description description) { + description.appendText("a string ") + .appendText(relationship) + .appendText(" ") + .appendValue(substring); + if (ignoringCase) { + description.appendText(" ignoring case"); + } + } + + protected String converted(String arg) { return ignoringCase ? arg.toLowerCase() : arg; } + protected abstract boolean evalSubstringOf(String string); + +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java b/hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java index 093cdba..03e4c43 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java +++ b/hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java @@ -4,25 +4,28 @@ import java.lang.reflect.Array; import java.util.Iterator; public class ArrayIterator implements Iterator<Object> { - private final Object array; - private int currentIndex = 0; - - public ArrayIterator(Object array) { - if (!array.getClass().isArray()) { - throw new IllegalArgumentException("not an array"); - } - this.array = array; - } - - public boolean hasNext() { - return currentIndex < Array.getLength(array); - } + private final Object array; + private int currentIndex = 0; + + public ArrayIterator(Object array) { + if (!array.getClass().isArray()) { + throw new IllegalArgumentException("not an array"); + } + this.array = array; + } + + @Override + public boolean hasNext() { + return currentIndex < Array.getLength(array); + } - public Object next() { - return Array.get(array, currentIndex++); - } - - public void remove() { - throw new UnsupportedOperationException("cannot remove items from an array"); - } + @Override + public Object next() { + return Array.get(array, currentIndex++); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("cannot remove items from an array"); + } } diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/NullSafety.java b/hamcrest-core/src/main/java/org/hamcrest/internal/NullSafety.java new file mode 100644 index 0000000..9310abf --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/internal/NullSafety.java @@ -0,0 +1,18 @@ +package org.hamcrest.internal; + +import org.hamcrest.Matcher; +import org.hamcrest.core.IsNull; + +import java.util.ArrayList; +import java.util.List; + +public class NullSafety { + @SuppressWarnings("unchecked") + public static <E> List<Matcher<? super E>> nullSafe(Matcher<? super E>[] itemMatchers) { + final List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>(itemMatchers.length); + for (final Matcher<? super E> itemMatcher : itemMatchers) { + matchers.add((Matcher<? super E>) (itemMatcher == null ? IsNull.nullValue() : itemMatcher)); + } + return matchers; + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/ReflectiveTypeFinder.java b/hamcrest-core/src/main/java/org/hamcrest/internal/ReflectiveTypeFinder.java new file mode 100644 index 0000000..ada74d6 --- /dev/null +++ b/hamcrest-core/src/main/java/org/hamcrest/internal/ReflectiveTypeFinder.java @@ -0,0 +1,70 @@ +/** + * The TypeSafe classes, and their descendants, need a mechanism to find out what type has been used as a parameter + * for the concrete matcher. Unfortunately, this type is lost during type erasure so we need to use reflection + * to get it back, by picking out the type of a known parameter to a known method. + * The catch is that, with bridging methods, this type is only visible in the class that actually implements + * the expected method, so the ReflectiveTypeFinder needs to be applied to that class or a subtype. + * + * For example, the abstract <code>TypeSafeDiagnosingMatcher<T></code> defines an abstract method + * <pre>protected abstract boolean matchesSafely(T item, Description mismatchDescription);</pre> + * By default it uses <code>new ReflectiveTypeFinder("matchesSafely", 2, 0); </code> to find the + * parameterised type. If we create a <code>TypeSafeDiagnosingMatcher<String></code>, the type + * finder will return <code>String.class</code>. + * + * A <code>FeatureMatcher</code> is an abstract subclass of <code>TypeSafeDiagnosingMatcher</code>. + * Although it has a templated implementation of <code>matchesSafely(<T>, Description);</code>, the + * actual run-time signature of this is <code>matchesSafely(Object, Description);</code>. Instead, + * we must find the type by reflecting on the concrete implementation of + * <pre>protected abstract U featureValueOf(T actual);</pre> + * a method which is declared in <code>FeatureMatcher</code>. + * + * In short, use this to extract a type from a method in the leaf class of a templated class hierarchy. + * + * @author Steve Freeman + * @author Nat Pryce + */ +package org.hamcrest.internal; + +import java.lang.reflect.Method; + +public class ReflectiveTypeFinder { + private final String methodName; + private final int expectedNumberOfParameters; + private final int typedParameter; + + public ReflectiveTypeFinder(String methodName, int expectedNumberOfParameters, int typedParameter) { + this.methodName = methodName; + this.expectedNumberOfParameters = expectedNumberOfParameters; + this.typedParameter = typedParameter; + } + + public Class<?> findExpectedType(Class<?> fromClass) { + for (Class<?> c = fromClass; c != Object.class; c = c.getSuperclass()) { + for (Method method : c.getDeclaredMethods()) { + if (canObtainExpectedTypeFrom(method)) { + return expectedTypeFrom(method); + } + } + } + throw new Error("Cannot determine correct type for " + methodName + "() method."); + } + + /** + * @param method The method to examine. + * @return true if this method references the relevant type + */ + protected boolean canObtainExpectedTypeFrom(Method method) { + return method.getName().equals(methodName) + && method.getParameterTypes().length == expectedNumberOfParameters + && !method.isSynthetic(); + } + + + /** + * @param method The method from which to extract + * @return The type we're looking for + */ + protected Class<?> expectedTypeFrom(Method method) { + return method.getParameterTypes()[typedParameter]; + } +} diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java b/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java index 0634527..6537018 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java +++ b/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java @@ -10,6 +10,7 @@ public class SelfDescribingValue<T> implements SelfDescribing { this.value = value; } + @Override public void describeTo(Description description) { description.appendValue(value); } diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java b/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java index 58bedf6..bc8f8f4 100644 --- a/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java +++ b/hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java @@ -1,9 +1,9 @@ package org.hamcrest.internal; -import java.util.Iterator; - import org.hamcrest.SelfDescribing; +import java.util.Iterator; + public class SelfDescribingValueIterator<T> implements Iterator<SelfDescribing> { private Iterator<T> values; @@ -11,14 +11,17 @@ public class SelfDescribingValueIterator<T> implements Iterator<SelfDescribing> this.values = values; } + @Override public boolean hasNext() { return values.hasNext(); } + @Override public SelfDescribing next() { return new SelfDescribingValue<T>(values.next()); } + @Override public void remove() { values.remove(); } diff --git a/hamcrest-core/src/main/java/org/hamcrest/internal/package.html b/hamcrest-core/src/main/java/org/hamcrest/internal/package.html deleted file mode 100644 index 1c9bf9d..0000000 --- a/hamcrest-core/src/main/java/org/hamcrest/internal/package.html +++ /dev/null @@ -1,5 +0,0 @@ -<html> -<body> - {@hide} -</body> -</html> diff --git a/hamcrest-core/src/main/java/org/hamcrest/package.html b/hamcrest-core/src/main/java/org/hamcrest/package.html deleted file mode 100644 index 143c704..0000000 --- a/hamcrest-core/src/main/java/org/hamcrest/package.html +++ /dev/null @@ -1,9 +0,0 @@ -<html> -<head> -</head> -<body> - <p>The stable API defining Matcher and its associated interfaces and classes. - Hamcrest sub-projects define their convenience classes in the org.hamcrest package. - </p> -</body> -</html> diff --git a/hamcrest-core/src/test/java/org/hamcrest/AbstractMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/AbstractMatcherTest.java new file mode 100644 index 0000000..22f823b --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/AbstractMatcherTest.java @@ -0,0 +1,77 @@ +package org.hamcrest; + +import junit.framework.TestCase; +import org.junit.Assert; + +public abstract class AbstractMatcherTest extends TestCase { + + /** + * Create an instance of the Matcher so some generic safety-net tests can be run on it. + */ + protected abstract Matcher<?> createMatcher(); + + public static <T> void assertMatches(Matcher<T> matcher, T arg) { + assertMatches("Expected match, but mismatched", matcher, arg); + } + + public static <T> void assertMatches(String message, Matcher<T> matcher, T arg) { + if (!matcher.matches(arg)) { + Assert.fail(message + " because: '" + mismatchDescription(matcher, arg) + "'"); + } + } + + public static <T> void assertDoesNotMatch(Matcher<? super T> c, T arg) { + assertDoesNotMatch("Unexpected match", c, arg); + } + + public static <T> void assertDoesNotMatch(String message, Matcher<? super T> c, T arg) { + Assert.assertFalse(message, c.matches(arg)); + } + + public static void assertDescription(String expected, Matcher<?> matcher) { + Description description = new StringDescription(); + description.appendDescriptionOf(matcher); + Assert.assertEquals("Expected description", expected, description.toString().trim()); + } + + public static <T> void assertMismatchDescription(String expected, Matcher<? super T> matcher, T arg) { + Assert.assertFalse("Precondition: Matcher should not match item.", matcher.matches(arg)); + Assert.assertEquals("Expected mismatch description", expected, mismatchDescription(matcher, arg)); + } + + public static void assertNullSafe(Matcher<?> matcher) { + try { + matcher.matches(null); + } + catch (Exception e) { + Assert.fail("Matcher was not null safe"); + } + } + + public static void assertUnknownTypeSafe(Matcher<?> matcher) { + try { + matcher.matches(new UnknownType()); + } + catch (Exception e) { + Assert.fail("Matcher was not unknown type safe"); + } + } + + public static <T> String mismatchDescription(Matcher<? super T> matcher, T arg) { + Description description = new StringDescription(); + matcher.describeMismatch(arg, description); + return description.toString().trim(); + } + + public void testIsNullSafe() { + assertNullSafe(createMatcher()); + } + + public void testCopesWithUnknownTypes() { + assertUnknownTypeSafe(createMatcher()); + } + + public static class UnknownType { + } + +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/BaseDescriptionTest.java b/hamcrest-core/src/test/java/org/hamcrest/BaseDescriptionTest.java new file mode 100644 index 0000000..8b70725 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/BaseDescriptionTest.java @@ -0,0 +1,78 @@ +package org.hamcrest; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public final class BaseDescriptionTest { + + private final StringBuilder result = new StringBuilder(); + + private final BaseDescription baseDescription = new BaseDescription() { + @Override protected void append(char c) { + result.append(c); + } + }; + + @Test public void + describesAppendedNullValue() { + baseDescription.appendValue(null); + assertEquals("null", result.toString()); + } + + @Test public void + quotesAppendedStringValue() { + baseDescription.appendValue("foo"); + assertEquals("\"foo\"", result.toString()); + } + + @Test public void + quotesAppendedCharacterValue() { + baseDescription.appendValue('f'); + assertEquals("\"f\"", result.toString()); + } + + @Test public void + bracketsAppendedShortValue() { + baseDescription.appendValue(Short.valueOf("2")); + assertEquals("<2s>", result.toString()); + } + + @Test public void + bracketsAppendedLongValue() { + baseDescription.appendValue(Long.valueOf("2")); + assertEquals("<2L>", result.toString()); + } + + @Test public void + bracketsAppendedFloatValue() { + baseDescription.appendValue(Float.valueOf("1.2")); + assertEquals("<1.2F>", result.toString()); + } + + @Test public void + describesAppendedArrayValue() { + baseDescription.appendValue(new String[] {"2", "3"}); + assertEquals("[\"2\", \"3\"]", result.toString()); + } + + @Test public void + bracketsAppendedObjectValue() { + final Object value = new Object(); + baseDescription.appendValue(value); + assertEquals("<" + value.toString() + ">", result.toString()); + } + + @Test public void + safelyDescribesAppendedValueOfObjectWhoseToStringThrowsAnException() { + final Object value = new Object() { + @Override public String toString() { + throw new UnsupportedOperationException(); + } + }; + + final String expected = value.getClass().getName() + "@" + Integer.toHexString(value.hashCode()); + baseDescription.appendValue(value); + assertEquals("<" + expected + ">", result.toString()); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/BaseMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/BaseMatcherTest.java new file mode 100644 index 0000000..e663f04 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/BaseMatcherTest.java @@ -0,0 +1,26 @@ +package org.hamcrest; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public final class BaseMatcherTest { + + @Test + public void + describesItselfWithToStringMethod() { + Matcher<Object> someMatcher = new BaseMatcher<Object>() { + @Override + public boolean matches(Object item) { + throw new UnsupportedOperationException(); + } + + @Override + public void describeTo(Description description) { + description.appendText("SOME DESCRIPTION"); + } + }; + + assertEquals("SOME DESCRIPTION", someMatcher.toString()); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/CustomMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/CustomMatcherTest.java new file mode 100644 index 0000000..08649f7 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/CustomMatcherTest.java @@ -0,0 +1,20 @@ +package org.hamcrest; + +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.assertDescription; + +public final class CustomMatcherTest { + + @Test public void + usesStaticDescription() throws Exception { + Matcher<String> matcher = new CustomMatcher<String>("I match strings") { + @Override + public boolean matches(Object item) { + return (item instanceof String); + } + }; + + assertDescription("I match strings", matcher); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/CustomTypeSafeMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/CustomTypeSafeMatcherTest.java new file mode 100644 index 0000000..2c86712 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/CustomTypeSafeMatcherTest.java @@ -0,0 +1,41 @@ +package org.hamcrest; + +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; + +public final class CustomTypeSafeMatcherTest { + private static final String STATIC_DESCRIPTION = "I match non empty strings"; + + private final Matcher<String> customMatcher = new CustomTypeSafeMatcher<String>(STATIC_DESCRIPTION) { + @Override + public boolean matchesSafely(String item) { + return false; + } + + @Override + public void describeMismatchSafely(String item, Description mismatchDescription) { + mismatchDescription.appendText("an " + item); + } + }; + + @Test public void + usesStaticDescription() throws Exception { + assertDescription(STATIC_DESCRIPTION, customMatcher); + } + + @Test public void + reportsMismatch() { + assertMismatchDescription("an item", customMatcher, "item"); + } + + @Test public void + isNullSafe() { + assertNullSafe(customMatcher); + } + + @Test public void + copesWithUnknownTypes() { + assertUnknownTypeSafe(customMatcher); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/FeatureMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/FeatureMatcherTest.java new file mode 100644 index 0000000..f0cbdd5 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/FeatureMatcherTest.java @@ -0,0 +1,68 @@ +package org.hamcrest; + +import org.hamcrest.core.IsEqual; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.junit.Assert.assertEquals; + +public final class FeatureMatcherTest { + private final FeatureMatcher<Thingy, String> resultMatcher = resultMatcher(); + + @Test public void + matchesPartOfAnObject() { + assertMatches("feature", resultMatcher, new Thingy("bar")); + assertDescription("Thingy with result \"bar\"", resultMatcher); + } + + @Test public void + mismatchesPartOfAnObject() { + assertMismatchDescription("result mismatch-description", resultMatcher, new Thingy("foo")); + } + + @Test public void + doesNotThrowNullPointerException() { + assertMismatchDescription("was null", resultMatcher, null); + } + + @Test public void + doesNotThrowClassCastException() { + resultMatcher.matches(new ShouldNotMatch()); + StringDescription mismatchDescription = new StringDescription(); + resultMatcher.describeMismatch(new ShouldNotMatch(), mismatchDescription); + assertEquals("was <ShouldNotMatch>", mismatchDescription.toString()); + } + + public static class Match extends IsEqual<String> { + public Match(String equalArg) { super(equalArg); } + @Override public void describeMismatch(Object item, Description description) { + description.appendText("mismatch-description"); + } + } + + public static class Thingy { + private final String result; + + public Thingy(String result) { + this.result = result; + } + + public String getResult() { + return result; + } + } + + public static class ShouldNotMatch { + @Override public String toString() { return "ShouldNotMatch"; } + } + + private static FeatureMatcher<Thingy, String> resultMatcher() { + return new FeatureMatcher<Thingy, String>(new Match("bar"), "Thingy with result", "result") { + @Override + public String featureValueOf(Thingy actual) { + return actual.getResult(); + } + }; + } + +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/MatcherAssertTest.java b/hamcrest-core/src/test/java/org/hamcrest/MatcherAssertTest.java new file mode 100644 index 0000000..b57c4d7 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/MatcherAssertTest.java @@ -0,0 +1,96 @@ +package org.hamcrest; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.*; + +public final class MatcherAssertTest { + + @Test public void + includesDescriptionOfTestedValueInErrorMessage() { + String expected = "expected"; + String actual = "actual"; + + String expectedMessage = "identifier\nExpected: \"expected\"\n but: was \"actual\""; + + try { + assertThat("identifier", actual, equalTo(expected)); + } + catch (AssertionError e) { + assertTrue(e.getMessage().startsWith(expectedMessage)); + return; + } + + fail("should have failed"); + } + + @Test public void + descriptionCanBeElided() { + String expected = "expected"; + String actual = "actual"; + + String expectedMessage = "\nExpected: \"expected\"\n but: was \"actual\""; + + try { + assertThat(actual, equalTo(expected)); + } + catch (AssertionError e) { + assertTrue(e.getMessage().startsWith(expectedMessage)); + return; + } + + fail("should have failed"); + } + + @Test public void + canTestBooleanDirectly() { + assertThat("success reason message", true); + + try { + assertThat("failing reason message", false); + } + catch (AssertionError e) { + assertEquals("failing reason message", e.getMessage()); + return; + } + + fail("should have failed"); + } + + @Test public void + includesMismatchDescription() { + Matcher<String> matcherWithCustomMismatchDescription = new BaseMatcher<String>() { + @Override + public boolean matches(Object item) { + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("Something cool"); + } + + @Override + public void describeMismatch(Object item, Description mismatchDescription) { + mismatchDescription.appendText("Not cool"); + } + }; + + String expectedMessage = "\nExpected: Something cool\n but: Not cool"; + + try { + assertThat("Value", matcherWithCustomMismatchDescription); + fail("should have failed"); + } + catch (AssertionError e) { + assertEquals(expectedMessage, e.getMessage()); + } + } + + @Test public void + canAssertSubtypes() { + assertThat(1, equalTo((Number) 1)); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/NullDescriptionTest.java b/hamcrest-core/src/test/java/org/hamcrest/NullDescriptionTest.java new file mode 100644 index 0000000..cccece0 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/NullDescriptionTest.java @@ -0,0 +1,18 @@ +package org.hamcrest; + +import org.hamcrest.Description.NullDescription; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public final class NullDescriptionTest { + + private final NullDescription nullDescription = new Description.NullDescription(); + + @Test public void + isUnchangedByAppendedText() { + nullDescription.appendText("myText"); + assertEquals("", nullDescription.toString()); + } + +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/TypeSafeMatcherTest.java b/hamcrest-core/src/test/java/org/hamcrest/TypeSafeMatcherTest.java new file mode 100644 index 0000000..e23bab8 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/TypeSafeMatcherTest.java @@ -0,0 +1,40 @@ +package org.hamcrest; + +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.assertMismatchDescription; +import static org.junit.Assert.assertFalse; + +public final class TypeSafeMatcherTest { + private final Matcher<String> matcher = new TypeSafeMatcherSubclass(); + + public static class TypeSafeMatcherSubclass extends TypeSafeMatcher<String> { + @Override + public boolean matchesSafely(String item) { + return false; + } + + @Override + public void describeMismatchSafely(String item, Description mismatchDescription) { + mismatchDescription.appendText("The mismatch"); + } + + @Override + public void describeTo(Description description) { + } + } + + @Test public void + canDetermineMatcherTypeFromProtectedMatchesSafelyMethod() { + assertFalse(matcher.matches(null)); + assertFalse(matcher.matches(10)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Test public void + describesMismatches() { + assertMismatchDescription("was null", matcher, null); + assertMismatchDescription("was a java.lang.Integer (<3>)", (Matcher)matcher, 3); + assertMismatchDescription("The mismatch", matcher, "a string"); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/AllOfTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/AllOfTest.java new file mode 100644 index 0000000..4815002 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/AllOfTest.java @@ -0,0 +1,63 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.AllOf.allOf; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.StringEndsWith.endsWith; +import static org.hamcrest.core.StringStartsWith.startsWith; + +public final class AllOfTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = allOf(equalTo("irrelevant"), startsWith("irr")); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + evaluatesToTheTheLogicalConjunctionOfTwoOtherMatchers() { + Matcher<String> matcher = allOf(startsWith("goo"), endsWith("ood")); + + assertMatches("didn't pass both sub-matchers", matcher, "good"); + assertDoesNotMatch("didn't fail first sub-matcher", matcher, "mood"); + assertDoesNotMatch("didn't fail second sub-matcher", matcher, "goon"); + assertDoesNotMatch("didn't fail both sub-matchers", matcher, "fred"); + } + + @Test public void + evaluatesToTheTheLogicalConjunctionOfManyOtherMatchers() { + Matcher<String> matcher = allOf(startsWith("g"), startsWith("go"), endsWith("d"), startsWith("go"), startsWith("goo")); + + assertMatches("didn't pass all sub-matchers", matcher, "good"); + assertDoesNotMatch("didn't fail middle sub-matcher", matcher, "goon"); + } + + @Test public void + supportsMixedTypes() { + final Matcher<SampleSubClass> matcher = allOf( + equalTo(new SampleBaseClass("bad")), + is(notNullValue()), + equalTo(new SampleBaseClass("good")), + equalTo(new SampleSubClass("ugly"))); + + assertDoesNotMatch("didn't fail last sub-matcher", matcher, new SampleSubClass("good")); + } + + @Test public void + hasAReadableDescription() { + assertDescription("(\"good\" and \"bad\" and \"ugly\")", + allOf(equalTo("good"), equalTo("bad"), equalTo("ugly"))); + } + + @Test public void + hasAMismatchDescriptionDescribingTheFirstFailingMatch() { + assertMismatchDescription("\"good\" was \"bad\"", allOf(equalTo("bad"), equalTo("good")), "bad"); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/AnyOfTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/AnyOfTest.java new file mode 100644 index 0000000..11c053c --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/AnyOfTest.java @@ -0,0 +1,56 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.AnyOf.anyOf; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.StringEndsWith.endsWith; +import static org.hamcrest.core.StringStartsWith.startsWith; + +public final class AnyOfTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = anyOf(equalTo("irrelevant"), startsWith("irr")); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + evaluatesToTheTheLogicalDisjunctionOfTwoOtherMatchers() { + Matcher<String> matcher = anyOf(startsWith("goo"), endsWith("ood")); + + assertMatches("didn't pass both sub-matchers", matcher, "good"); + assertMatches("didn't pass second sub-matcher", matcher, "mood"); + assertMatches("didn't pass first sub-matcher", matcher, "goon"); + assertDoesNotMatch("didn't fail both sub-matchers", matcher, "flan"); + } + + @Test public void + evaluatesToTheTheLogicalDisjunctionOfManyOtherMatchers() { + Matcher<String> matcher = anyOf(startsWith("g"), startsWith("go"), endsWith("d"), startsWith("go"), startsWith("goo")); + + assertMatches("didn't pass middle sub-matcher", matcher, "vlad"); + assertDoesNotMatch("didn't fail all sub-matchers", matcher, "flan"); + } + + @SuppressWarnings("unchecked") + @Test public void + supportsMixedTypes() { + final Matcher<SampleSubClass> matcher = anyOf( + equalTo(new SampleBaseClass("bad")), + equalTo(new SampleBaseClass("good")), + equalTo(new SampleSubClass("ugly"))); + + assertMatches("didn't pass middle sub-matcher", matcher, new SampleSubClass("good")); + } + + @Test public void + hasAReadableDescription() { + assertDescription("(\"good\" or \"bad\" or \"ugly\")", + anyOf(equalTo("good"), equalTo("bad"), equalTo("ugly"))); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/CombinableTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/CombinableTest.java new file mode 100644 index 0000000..e89c493 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/CombinableTest.java @@ -0,0 +1,68 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.IsNull.notNullValue; + +public final class CombinableTest { + private static final CombinableMatcher<Integer> EITHER_3_OR_4 = CombinableMatcher.<Integer>either(equalTo(3)).or(equalTo(4)); + private static final CombinableMatcher<Integer> NOT_3_AND_NOT_4 = CombinableMatcher.<Integer>both(not(equalTo(3))).and(not(equalTo(4))); + + @Test public void + copesWithNullsAndUnknownTypes() { + assertNullSafe(EITHER_3_OR_4); + assertNullSafe(NOT_3_AND_NOT_4); + assertUnknownTypeSafe(EITHER_3_OR_4); + assertUnknownTypeSafe(NOT_3_AND_NOT_4); + } + + @Test public void + bothAcceptsAndRejects() { + assertMatches("both didn't pass", NOT_3_AND_NOT_4, 2); + assertDoesNotMatch("both didn't fail", NOT_3_AND_NOT_4, 3); + } + + @Test public void + acceptsAndRejectsThreeAnds() { + CombinableMatcher<? super Integer> tripleAnd = NOT_3_AND_NOT_4.and(equalTo(2)); + + assertMatches("tripleAnd didn't pass", tripleAnd, 2); + assertDoesNotMatch("tripleAnd didn't fail", tripleAnd, 3); + } + + @Test public void + bothDescribesItself() { + assertDescription("(not <3> and not <4>)", NOT_3_AND_NOT_4); + assertMismatchDescription("not <3> was <3>", NOT_3_AND_NOT_4, 3); + } + + @Test public void + eitherAcceptsAndRejects() { + assertMatches("either didn't pass", EITHER_3_OR_4, 3); + assertDoesNotMatch("either didn't fail", EITHER_3_OR_4, 6); + } + + @Test public void + acceptsAndRejectsThreeOrs() { + final CombinableMatcher<Integer> tripleOr = EITHER_3_OR_4.or(equalTo(11)); + + assertMatches("tripleOr didn't pass", tripleOr, 11); + assertDoesNotMatch("tripleOr didn't fail", tripleOr, 9); + } + + @Test public void + eitherDescribesItself() { + assertDescription("(<3> or <4>)", EITHER_3_OR_4); + assertMismatchDescription("was <6>", EITHER_3_OR_4, 6); + } + + @Test public void + picksUpTypeFromLeftHandSideOfExpression() { + @SuppressWarnings("unused") + Matcher<String> matcher = CombinableMatcher.both(equalTo("yellow")).and(notNullValue(String.class)); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/DescribedAsTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/DescribedAsTest.java new file mode 100644 index 0000000..5c76af9 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/DescribedAsTest.java @@ -0,0 +1,49 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.DescribedAs.describedAs; +import static org.hamcrest.core.IsAnything.anything; +import static org.hamcrest.core.IsEqual.equalTo; + +public final class DescribedAsTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<Object> matcher = describedAs("irrelevant", anything()); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + overridesDescriptionOfOtherMatcherWithThatPassedToConstructor() { + Matcher<?> matcher = describedAs("my description", anything()); + + assertDescription("my description", matcher); + } + + @Test public void + appendsValuesToDescription() { + Matcher<?> matcher = describedAs("value 1 = %0, value 2 = %1", anything(), 33, 97); + + assertDescription("value 1 = <33>, value 2 = <97>", matcher); + } + + @Test public void + celegatesMatchingToAnotherMatcher() { + Matcher<String> matcher = describedAs("irrelevant", equalTo("hi")); + + assertMatches(matcher, "hi"); + assertDoesNotMatch("matched", matcher, "oi"); + } + + @Test public void + delegatesMismatchDescriptionToAnotherMatcher() { + Matcher<Integer> matcher = describedAs("irrelevant", equalTo(2)); + + assertMismatchDescription("was <1>", matcher, 1); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/EveryTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/EveryTest.java new file mode 100644 index 0000000..e45e881 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/EveryTest.java @@ -0,0 +1,43 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import java.util.ArrayList; + +import static java.util.Arrays.asList; +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.StringContains.containsString; + +public final class EveryTest { + + private final Matcher<Iterable<? extends String>> matcher = Every.everyItem(containsString("a")); + + @Test public void + copesWithNullsAndUnknownTypes() { + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + matchesOnlyWhenEveryItemMatches() { + assertMatches(matcher, asList("AaA", "BaB", "CaC")); + assertDoesNotMatch(matcher, asList("AaA", "BXB", "CaC")); + } + + @Test public void + matchesEmptyLists() { + assertMatches("didn't match empty list", matcher, new ArrayList<String>()); + } + + @Test public void + describesItself() { + assertDescription("every item is a string containing \"a\"", matcher); + } + + @Test public void + describesAMismatch() { + assertMismatchDescription("an item was \"BXB\"", matcher, asList("BXB")); + } +} + diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsAnythingTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsAnythingTest.java new file mode 100644 index 0000000..4983bf7 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsAnythingTest.java @@ -0,0 +1,35 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.assertDescription; +import static org.hamcrest.AbstractMatcherTest.assertMatches; +import static org.hamcrest.core.IsAnything.anything; + +public final class IsAnythingTest { + + private final Matcher<Object> matcher = anything(); + + private static class CustomThing { } + + @Test public void + alwaysEvaluatesToTrue() { + assertMatches("didn't match null", matcher, null); + assertMatches("didn't match Object", matcher, new Object()); + assertMatches("didn't match custom object", matcher, new CustomThing()); + assertMatches("didn't match String", matcher, "hi"); + } + + @Test public void + hasUsefulDefaultDescription() { + assertDescription("ANYTHING", matcher); + } + + @Test public void + canOverrideDescription() { + String description = "description"; + assertDescription(description, anything(description)); + } + +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsCollectionContainingTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsCollectionContainingTest.java new file mode 100644 index 0000000..a9007cd --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsCollectionContainingTest.java @@ -0,0 +1,107 @@ +package org.hamcrest.core; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import static java.util.Arrays.asList; +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsCollectionContaining.hasItem; +import static org.hamcrest.core.IsCollectionContaining.hasItems; +import static org.hamcrest.core.IsEqual.equalTo; + +public final class IsCollectionContainingTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<?> matcher = hasItem(equalTo("irrelevant")); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + matchesACollectionThatContainsAnElementForTheGivenMatcher() { + final Matcher<Iterable<? super String>> itemMatcher = hasItem(equalTo("a")); + + assertMatches("list containing 'a'", itemMatcher, asList("a", "b", "c")); + } + + @Test public void + doesNotMatchCollectionWithoutAnElementForGivenMatcher() { + final Matcher<Iterable<? super String>> matcher = hasItem(mismatchable("a")); + + assertMismatchDescription("mismatches were: [mismatched: b, mismatched: c]", matcher, asList("b", "c")); + assertMismatchDescription("was empty", matcher, new ArrayList<String>()); + } + + @Test public void + doesNotMatchNull() { + assertDoesNotMatch("doesn't match null", hasItem(equalTo("a")), null); + } + + @Test public void + hasAReadableDescription() { + assertDescription("a collection containing mismatchable: a", hasItem(mismatchable("a"))); + } + + @Test public void + canMatchItemWhenCollectionHoldsSuperclass() { // Issue 24 + final Set<Number> s = new HashSet<Number>(); + s.add(2); + + assertMatches(new IsCollectionContaining<Number>(new IsEqual<Number>(2)), s); + assertMatches(IsCollectionContaining.hasItem(2), s); + } + + @SuppressWarnings("unchecked") + @Test public void + matchesMultipleItemsInCollection() { + final Matcher<Iterable<String>> matcher1 = hasItems(equalTo("a"), equalTo("b"), equalTo("c")); + assertMatches("list containing all items", matcher1, asList("a", "b", "c")); + + final Matcher<Iterable<String>> matcher2 = hasItems("a", "b", "c"); + assertMatches("list containing all items (without matchers)", matcher2, asList("a", "b", "c")); + + final Matcher<Iterable<String>> matcher3 = hasItems(equalTo("a"), equalTo("b"), equalTo("c")); + assertMatches("list containing all items in any order", matcher3, asList("c", "b", "a")); + + final Matcher<Iterable<String>> matcher4 = hasItems(equalTo("a"), equalTo("b"), equalTo("c")); + assertMatches("list containing all items plus others", matcher4, asList("e", "c", "b", "a", "d")); + + final Matcher<Iterable<String>> matcher5 = hasItems(equalTo("a"), equalTo("b"), equalTo("c")); + assertDoesNotMatch("not match list unless it contains all items", matcher5, asList("e", "c", "b", "d")); // 'a' missing + } + + @Test public void + reportsMismatchWithAReadableDescriptionForMultipleItems() { + final Matcher<Iterable<Integer>> matcher = hasItems(3, 4); + + assertMismatchDescription("a collection containing <4> mismatches were: [was <1>, was <2>, was <3>]", + matcher, asList(1, 2, 3)); + } + + private static Matcher<? super String> mismatchable(final String string) { + return new TypeSafeDiagnosingMatcher<String>() { + @Override + protected boolean matchesSafely(String item, Description mismatchDescription) { + if (string.equals(item)) + return true; + + mismatchDescription.appendText("mismatched: " + item); + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("mismatchable: " + string); + } + }; + } +} + diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsEqualTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsEqualTest.java new file mode 100644 index 0000000..9df73e4 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsEqualTest.java @@ -0,0 +1,143 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsEqual.equalToObject; + +public final class IsEqualTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<?> matcher = equalTo("irrelevant"); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + comparesObjectsUsingEqualsMethod() { + final Matcher<String> matcher1 = equalTo("hi"); + assertMatches(matcher1, "hi"); + assertDoesNotMatch(matcher1, "bye"); + assertDoesNotMatch(matcher1, null); + + final Matcher<Integer> matcher2 = equalTo(1); + assertMatches(matcher2, 1); + assertDoesNotMatch(matcher2, 2); + assertDoesNotMatch(matcher2, null); + } + + @Test public void + canCompareNullValues() { + final Matcher<Object> matcher = equalTo(null); + + assertMatches(matcher, null); + assertDoesNotMatch(matcher, 2); + assertDoesNotMatch(matcher, "hi"); + assertDoesNotMatch(matcher, new String[] {"a", "b"}); + } + + @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") + @Test public void + honoursIsEqualImplementationEvenWithNullValues() { + Object alwaysEqual = new Object() { + @Override + public boolean equals(Object obj) { + return true; + } + }; + Object neverEqual = new Object() { + @Override + public boolean equals(Object obj) { + return false; + } + }; + + Matcher<Object> matcher = equalTo(null); + + assertMatches(matcher, alwaysEqual); + assertDoesNotMatch(matcher, neverEqual); + } + + @Test public void + comparesTheElementsOfAnObjectArray() { + String[] s1 = {"a", "b"}; + String[] s2 = {"a", "b"}; + String[] s3 = {"c", "d"}; + String[] s4 = {"a", "b", "c", "d"}; + + final Matcher<String[]> matcher = equalTo(s1); + assertMatches(matcher, s1); + assertMatches(matcher, s2); + assertDoesNotMatch(matcher, s3); + assertDoesNotMatch(matcher, s4); + assertDoesNotMatch(matcher, null); + } + + @Test public void + comparesTheElementsOfAnArrayOfPrimitiveTypes() { + int[] i1 = new int[]{1, 2}; + int[] i2 = new int[]{1, 2}; + int[] i3 = new int[]{3, 4}; + int[] i4 = new int[]{1, 2, 3, 4}; + + final Matcher<int[]> matcher = equalTo(i1); + assertMatches(matcher, i1); + assertMatches(matcher, i2); + assertDoesNotMatch(matcher, i3); + assertDoesNotMatch(matcher, i4); + assertDoesNotMatch(matcher, null); + } + + @Test public void + recursivelyTestsElementsOfArrays() { + int[][] i1 = new int[][]{{1, 2}, {3, 4}}; + int[][] i2 = new int[][]{{1, 2}, {3, 4}}; + int[][] i3 = new int[][]{{5, 6}, {7, 8}}; + int[][] i4 = new int[][]{{1, 2, 3, 4}, {3, 4}}; + + final Matcher<int[][]> matcher = equalTo(i1); + assertMatches(matcher, i1); + assertMatches(matcher, i2); + assertDoesNotMatch(matcher, i3); + assertDoesNotMatch(matcher, i4); + assertDoesNotMatch(matcher, null); + } + + @Test public void + hasUntypedVariant() { + Object original = 10; + + assertMatches(equalToObject(10), original); + assertDoesNotMatch(equalToObject(0), original); + assertDoesNotMatch(equalToObject("10"), original); + assertDoesNotMatch(equalToObject(10), "10"); + } + + @Test public void + includesTheResultOfCallingToStringOnItsArgumentInTheDescription() { + final String argumentDescription = "ARGUMENT DESCRIPTION"; + Object argument = new Object() { + @Override + public String toString() { + return argumentDescription; + } + }; + assertDescription("<" + argumentDescription + ">", equalTo(argument)); + } + + @Test public void + returnsAnObviousDescriptionIfCreatedWithANestedMatcherByMistake() { + Matcher<? super String> innerMatcher = equalTo("NestedMatcher"); + assertDescription("<" + innerMatcher.toString() + ">", equalTo(innerMatcher)); + } + + @Test public void + returnsGoodDescriptionIfCreatedWithNullReference() { + assertDescription("null", equalTo(null)); + } +} + diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsInstanceOfTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsInstanceOfTest.java new file mode 100644 index 0000000..8dd85af --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsInstanceOfTest.java @@ -0,0 +1,69 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsInstanceOf.any; +import static org.hamcrest.core.IsInstanceOf.instanceOf; + +public final class IsInstanceOfTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<?> matcher = instanceOf(Number.class); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + evaluatesToTrueIfArgumentIsInstanceOfASpecificClass() { + final Matcher<Object> matcher = instanceOf(Number.class); + + assertMatches(matcher, 1); + assertMatches(matcher, 1.1); + assertDoesNotMatch(matcher, null); + assertDoesNotMatch(matcher, new Object()); + } + + @Test public void + hasAReadableDescription() { + assertDescription("an instance of java.lang.Number", instanceOf(Number.class)); + } + + @Test public void + describesActualClassInMismatchMessage() { + assertMismatchDescription("\"some text\" is a java.lang.String", instanceOf(Number.class), "some text"); + } + + @Test public void + matchesPrimitiveTypes() { + assertMatches(any(boolean.class), true); + assertMatches(any(byte.class), (byte)1); + assertMatches(any(char.class), 'x'); + assertMatches(any(double.class), 5.0); + assertMatches(any(float.class), 5.0f); + assertMatches(any(int.class), 2); + assertMatches(any(long.class), 4L); + assertMatches(any(short.class), (short)1); + } + + @Test public void + instanceOfRequiresACastToReturnTheCorrectTypeForUseInJMock() { + @SuppressWarnings("unused") + Integer anInteger = (Integer)with(instanceOf(Integer.class)); + } + + @Test public void + anyWillReturnTheCorrectTypeForUseInJMock() { + @SuppressWarnings("unused") + Integer anInteger = with(any(Integer.class)); + } + + + private static <T> T with(@SuppressWarnings("unused") Matcher<T> matcher) { + return null; + } +} + diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsNotTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsNotTest.java new file mode 100644 index 0000000..79f4683 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsNotTest.java @@ -0,0 +1,42 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.hamcrest.core.IsNot.not; + +public final class IsNotTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = not("something"); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + evaluatesToTheTheLogicalNegationOfAnotherMatcher() { + final Matcher<String> matcher = not(equalTo("A")); + + assertMatches(matcher, "B"); + assertDoesNotMatch(matcher, "A"); + } + + @Test public void + providesConvenientShortcutForNotEqualTo() { + final Matcher<String> matcher = not("A"); + + assertMatches(matcher, "B"); + assertDoesNotMatch(matcher, "A"); + } + + @Test public void + usesDescriptionOfNegatedMatcherWithPrefix() { + assertDescription("not an instance of java.lang.String", not(instanceOf(String.class))); + assertDescription("not \"A\"", not("A")); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsNullTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsNullTest.java new file mode 100644 index 0000000..74b046b --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsNullTest.java @@ -0,0 +1,43 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.IsNull.nullValue; + + +public final class IsNullTest { + + private final Matcher<Object> nullMatcher = nullValue(); + private final Matcher<Object> notNullMatcher = notNullValue(); + + @Test public void + copesWithNullsAndUnknownTypes() { + assertNullSafe(nullMatcher); + assertUnknownTypeSafe(nullMatcher); + + assertNullSafe(notNullMatcher); + assertUnknownTypeSafe(notNullMatcher); + } + + @Test public void + evaluatesToTrueIfArgumentIsNull() { + assertMatches(nullMatcher, null); + assertDoesNotMatch(nullMatcher, new Object()); + + assertMatches(notNullMatcher, new Object()); + assertDoesNotMatch(notNullMatcher, null); + } + + @Test public void + supportsStaticTyping() { + requiresStringMatcher(nullValue(String.class)); + requiresStringMatcher(notNullValue(String.class)); + } + + private void requiresStringMatcher(@SuppressWarnings("unused") Matcher<String> arg) { + // no-op + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsSameTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsSameTest.java new file mode 100644 index 0000000..a4a2010 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsSameTest.java @@ -0,0 +1,48 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsSame.sameInstance; +import static org.hamcrest.core.IsSame.theInstance; + + +public final class IsSameTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = sameInstance("irrelevant"); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + evaluatesToTrueIfArgumentIsReferenceToASpecifiedObject() { + Object o1 = new Object(); + Matcher<Object> matcher = sameInstance(o1); + + assertMatches(matcher, o1); + assertDoesNotMatch(matcher, new Object()); + } + + @Test public void + alternativeFactoryMethodAlsoMatchesOnlyIfArgumentIsReferenceToASpecifiedObject() { + Object o1 = new Object(); + Matcher<Object> matcher = theInstance(o1); + + assertMatches(matcher, o1); + assertDoesNotMatch(matcher, new Object()); + } + + @Test public void + returnsReadableDescriptionFromToString() { + assertDescription("sameInstance(\"ARG\")", sameInstance("ARG")); + } + + @Test public void + returnsReadableDescriptionFromToStringWhenInitialisedWithNull() { + assertDescription("sameInstance(null)", sameInstance(null)); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/IsTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/IsTest.java new file mode 100644 index 0000000..6656e6d --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/IsTest.java @@ -0,0 +1,51 @@ +package org.hamcrest.core; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.Is.isA; +import static org.hamcrest.core.IsEqual.equalTo; + +public final class IsTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = is("something"); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + matchesTheSameWayTheUnderlyingMatcherDoes() { + final Matcher<Boolean> matcher = is(equalTo(true)); + + assertMatches(matcher, true); + assertDoesNotMatch(matcher, false); + } + + @Test public void + generatesIsPrefixInDescription() { + assertDescription("is <true>", is(equalTo(true))); + assertDescription("is \"A\"", is("A")); + } + + @Test public void + providesConvenientShortcutForIsEqualTo() { + final Matcher<String> matcher = is("A"); + + assertMatches(matcher, "A"); + assertDoesNotMatch(is("A"), "B"); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Test public void + providesConvenientShortcutForIsInstanceOf() { + final Matcher matcher = isA(Integer.class); + assertMatches(matcher, 1); + assertDoesNotMatch(matcher, new Object()); + assertDoesNotMatch(matcher, null); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/SampleBaseClass.java b/hamcrest-core/src/test/java/org/hamcrest/core/SampleBaseClass.java new file mode 100644 index 0000000..baf4d8e --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/SampleBaseClass.java @@ -0,0 +1,24 @@ +package org.hamcrest.core; + +public class SampleBaseClass { + String value; + + public SampleBaseClass(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof SampleBaseClass && value.equals(((SampleBaseClass) obj).value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/SampleSubClass.java b/hamcrest-core/src/test/java/org/hamcrest/core/SampleSubClass.java new file mode 100644 index 0000000..bdaa160 --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/SampleSubClass.java @@ -0,0 +1,9 @@ +package org.hamcrest.core; + +public class SampleSubClass extends SampleBaseClass { + + public SampleSubClass(String value) { + super(value); + } + +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/StringContainsTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/StringContainsTest.java new file mode 100644 index 0000000..93dd05c --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/StringContainsTest.java @@ -0,0 +1,43 @@ +package org.hamcrest.core; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.core.StringContains.containsString; +import static org.hamcrest.core.StringContains.containsStringIgnoringCase; + + +public class StringContainsTest extends AbstractMatcherTest { + static final String EXCERPT = "EXCERPT"; + final Matcher<String> stringContains = containsString(EXCERPT); + + @Override + protected Matcher<?> createMatcher() { + return stringContains; + } + + public void testMatchesSubstrings() { + assertMatches(stringContains, EXCERPT + "END"); + assertMatches(stringContains, "START" + EXCERPT); + assertMatches(stringContains, "START" + EXCERPT + "END"); + assertMatches(stringContains, EXCERPT); + assertDoesNotMatch(stringContains, EXCERPT.toLowerCase()); + assertMatches(stringContains, EXCERPT + EXCERPT); + assertDoesNotMatch(stringContains, "XC"); + + assertMismatchDescription("was \"Something else\"", stringContains, "Something else"); + assertDescription("a string containing \"EXCERPT\"", stringContains); + } + + public void testMatchesSubstringsIgnoringCase() { + final Matcher<String> ignoringCase = containsStringIgnoringCase("ExCert"); + assertMatches(ignoringCase, "eXcERT" + "END"); + assertMatches(ignoringCase, "START" + "EXCert"); + assertMatches(ignoringCase, "START" + "excERT" + "END"); + assertMatches(ignoringCase, "eXCert" + "excErt"); + assertDoesNotMatch(ignoringCase, "xc"); + + assertMismatchDescription("was \"Something else\"", ignoringCase, "Something else"); + assertDescription("a string containing \"ExCert\" ignoring case", ignoringCase); + } +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/StringEndsWithTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/StringEndsWithTest.java new file mode 100644 index 0000000..f482cbf --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/StringEndsWithTest.java @@ -0,0 +1,45 @@ +package org.hamcrest.core; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.core.StringEndsWith.endsWith; +import static org.hamcrest.core.StringEndsWith.endsWithIgnoringCase; + + +public class StringEndsWithTest extends AbstractMatcherTest { + static final String EXCERPT = "EXCERPT"; + final Matcher<String> stringEndsWith = endsWith(EXCERPT); + + @Override + protected Matcher<?> createMatcher() { + return stringEndsWith; + } + + public void testMatchesSubstringAtEnd() { + assertDoesNotMatch(stringEndsWith, EXCERPT + "END"); + assertMatches(stringEndsWith, "START" + EXCERPT); + assertMatches(stringEndsWith, EXCERPT); + assertDoesNotMatch(stringEndsWith, EXCERPT.toLowerCase()); + assertDoesNotMatch(stringEndsWith, "START" + EXCERPT + "END"); + assertMatches(stringEndsWith, EXCERPT + EXCERPT); + assertDoesNotMatch(stringEndsWith, "EXCER"); + + assertMismatchDescription("was \"Something else\"", stringEndsWith, "Something else"); + assertDescription("a string ending with \"EXCERPT\"", stringEndsWith); + } + + public void testMatchesSubstringAtEndIngoringCase() { + final Matcher<String> ignoringCase = endsWithIgnoringCase("EXCERpt"); + assertDoesNotMatch(ignoringCase, "eXCErpt" + "END"); + assertMatches(ignoringCase, "START" + "EXceRpt"); + assertMatches(ignoringCase, "EXcerPT"); + assertDoesNotMatch(ignoringCase, "START" + "ExcERpt" + "END"); + assertMatches(ignoringCase, "exCERpt" + "EXCerPt"); + assertDoesNotMatch(ignoringCase, "ExcER"); + + assertMismatchDescription("was \"Something else\"", ignoringCase, "Something else"); + assertDescription("a string ending with \"EXCERpt\" ignoring case", ignoringCase); + } + +} diff --git a/hamcrest-core/src/test/java/org/hamcrest/core/StringStartsWithTest.java b/hamcrest-core/src/test/java/org/hamcrest/core/StringStartsWithTest.java new file mode 100644 index 0000000..f093acb --- /dev/null +++ b/hamcrest-core/src/test/java/org/hamcrest/core/StringStartsWithTest.java @@ -0,0 +1,46 @@ +package org.hamcrest.core; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.core.StringStartsWith.startsWith; +import static org.hamcrest.core.StringStartsWith.startsWithIgnoringCase; + + +public class StringStartsWithTest extends AbstractMatcherTest { + static final String EXCERPT = "EXCERPT"; + final Matcher<String> stringStartsWith = startsWith(EXCERPT); + + @Override + protected Matcher<?> createMatcher() { + return stringStartsWith; + } + + public void testMatchesStringAtStart() { + assertMatches(stringStartsWith, EXCERPT + "END"); + assertDoesNotMatch(stringStartsWith, "START" + EXCERPT); + assertDoesNotMatch(stringStartsWith, "START" + EXCERPT + "END"); + assertMatches(stringStartsWith, EXCERPT); + assertDoesNotMatch(stringStartsWith, EXCERPT.toLowerCase()); + assertMatches(stringStartsWith, EXCERPT + EXCERPT); + assertDoesNotMatch(stringStartsWith, "EXCER"); + + assertDescription("a string starting with \"EXCERPT\"", stringStartsWith); + assertMismatchDescription("was \"Something else\"", stringStartsWith, "Something else"); + } + + public void testMatchesStringAtStartIgnoringCase() { + final Matcher<String> ignoreCase = startsWithIgnoringCase("EXCerPT"); + + assertMatches(ignoreCase, "exCerPT" + "END"); + assertDoesNotMatch(ignoreCase, "START" + "EXCerpt"); + assertDoesNotMatch(ignoreCase, "START" + "EXcerpT" + "END"); + assertMatches(ignoreCase, "excERPT"); + assertMatches(ignoreCase, "ExcerPT" + "EXCerpt"); + assertDoesNotMatch(ignoreCase, "ExcER"); + + assertDescription("a string starting with \"EXCerPT\" ignoring case", ignoreCase); + assertMismatchDescription("was \"Something else\"", ignoreCase, "Something else"); + } + +} diff --git a/hamcrest-library/LICENSE.txt b/hamcrest-library/LICENSE.txt deleted file mode 100644 index 5ebe92c..0000000 --- a/hamcrest-library/LICENSE.txt +++ /dev/null @@ -1,27 +0,0 @@ -BSD License
-
-Copyright (c) 2000-2006, www.hamcrest.org
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list of
-conditions and the following disclaimer. Redistributions in binary form must reproduce
-the above copyright notice, this list of conditions and the following disclaimer in
-the documentation and/or other materials provided with the distribution.
-
-Neither the name of Hamcrest nor the names of its contributors may be used to endorse
-or promote products derived from this software without specific prior written
-permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
-WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
diff --git a/hamcrest-library/README.android b/hamcrest-library/README.android deleted file mode 100644 index dd099ed..0000000 --- a/hamcrest-library/README.android +++ /dev/null @@ -1 +0,0 @@ -Ssource obtained from https://hamcrest.googlecode.com/files/hamcrest-library-1.1.jar, with org.hamcrest.beans removed diff --git a/hamcrest-library/build.gradle b/hamcrest-library/build.gradle deleted file mode 100644 index 54ab15f..0000000 --- a/hamcrest-library/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -apply plugin: 'java' - -sourceSets { - main { - java { - srcDirs = ['src'] - } - } -} - -dependencies { - compile project(':hamcrest') -} diff --git a/hamcrest-library/src/main/java/org/hamcrest/Matchers.java b/hamcrest-library/src/main/java/org/hamcrest/Matchers.java index 2e82aa0..b04c45d 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/Matchers.java +++ b/hamcrest-library/src/main/java/org/hamcrest/Matchers.java @@ -1,28 +1,204 @@ -// Generated source. package org.hamcrest; public class Matchers { - /** - * Decorates another Matcher, retaining the behavior but allowing tests - * to be slightly more expressive. - * - * eg. assertThat(cheese, equalTo(smelly)) - * vs assertThat(cheese, is(equalTo(smelly))) - */ - public static <T> org.hamcrest.Matcher<T> is(org.hamcrest.Matcher<T> matcher) { - return org.hamcrest.core.Is.is(matcher); - } - - /** - * This is a shortcut to the frequently used is(equalTo(x)). - * - * eg. assertThat(cheese, is(equalTo(smelly))) - * vs assertThat(cheese, is(smelly)) - */ - public static <T> org.hamcrest.Matcher<T> is(T value) { - return org.hamcrest.core.Is.is(value); - } + /** + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.Matcher<T> allOf(java.lang.Iterable<org.hamcrest.Matcher<? super T>> matchers) { + return org.hamcrest.core.AllOf.<T>allOf(matchers); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T>... matchers) { + return org.hamcrest.core.AllOf.<T>allOf(matchers); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second) { + return org.hamcrest.core.AllOf.<T>allOf(first, second); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third) { + return org.hamcrest.core.AllOf.<T>allOf(first, second, third); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth) { + return org.hamcrest.core.AllOf.<T>allOf(first, second, third, fourth); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth, org.hamcrest.Matcher<? super T> fifth) { + return org.hamcrest.core.AllOf.<T>allOf(first, second, third, fourth, fifth); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ALL</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", allOf(startsWith("my"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? super T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth, org.hamcrest.Matcher<? super T> fifth, org.hamcrest.Matcher<? super T> sixth) { + return org.hamcrest.core.AllOf.<T>allOf(first, second, third, fourth, fifth, sixth); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.core.AnyOf<T> anyOf(java.lang.Iterable<org.hamcrest.Matcher<? super T>> matchers) { + return org.hamcrest.core.AnyOf.<T>anyOf(matchers); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<? super T>... matchers) { + return org.hamcrest.core.AnyOf.<T>anyOf(matchers); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second) { + return org.hamcrest.core.AnyOf.<T>anyOf(first, second); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third) { + return org.hamcrest.core.AnyOf.<T>anyOf(first, second, third); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth) { + return org.hamcrest.core.AnyOf.<T>anyOf(first, second, third, fourth); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth, org.hamcrest.Matcher<? super T> fifth) { + return org.hamcrest.core.AnyOf.<T>anyOf(first, second, third, fourth, fifth); + } + + /** + * Creates a matcher that matches if the examined object matches <b>ANY</b> of the specified matchers. + * For example: + * <pre>assertThat("myValue", anyOf(startsWith("foo"), containsString("Val")))</pre> + */ + public static <T> org.hamcrest.core.AnyOf<T> anyOf(org.hamcrest.Matcher<T> first, org.hamcrest.Matcher<? super T> second, org.hamcrest.Matcher<? super T> third, org.hamcrest.Matcher<? super T> fourth, org.hamcrest.Matcher<? super T> fifth, org.hamcrest.Matcher<? super T> sixth) { + return org.hamcrest.core.AnyOf.<T>anyOf(first, second, third, fourth, fifth, sixth); + } + + /** + * Creates a matcher that matches when both of the specified matchers match the examined object. + * For example: + * <pre>assertThat("fab", both(containsString("a")).and(containsString("b")))</pre> + */ + public static <LHS> org.hamcrest.core.CombinableMatcher.CombinableBothMatcher<LHS> both(org.hamcrest.Matcher<? super LHS> matcher) { + return org.hamcrest.core.CombinableMatcher.<LHS>both(matcher); + } + + /** + * Creates a matcher that matches when either of the specified matchers match the examined object. + * For example: + * <pre>assertThat("fan", either(containsString("a")).or(containsString("b")))</pre> + */ + public static <LHS> org.hamcrest.core.CombinableMatcher.CombinableEitherMatcher<LHS> either(org.hamcrest.Matcher<? super LHS> matcher) { + return org.hamcrest.core.CombinableMatcher.<LHS>either(matcher); + } + + /** + * Wraps an existing matcher, overriding its description with that specified. All other functions are + * delegated to the decorated matcher, including its mismatch description. + * For example: + * <pre>describedAs("a big decimal equal to %0", equalTo(myBigDecimal), myBigDecimal.toPlainString())</pre> + * + * @param description + * the new description for the wrapped matcher + * @param matcher + * the matcher to wrap + * @param values + * optional values to insert into the tokenised description + */ + public static <T> org.hamcrest.Matcher<T> describedAs(java.lang.String description, org.hamcrest.Matcher<T> matcher, java.lang.Object... values) { + return org.hamcrest.core.DescribedAs.<T>describedAs(description, matcher, values); + } + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields items that are all matched by the specified + * <code>itemMatcher</code>. + * For example: + * <pre>assertThat(Arrays.asList("bar", "baz"), everyItem(startsWith("ba")))</pre> + * + * @param itemMatcher + * the matcher to apply to every item provided by the examined {@link Iterable} + */ + public static <U> org.hamcrest.Matcher<java.lang.Iterable<? extends U>> everyItem(org.hamcrest.Matcher<U> itemMatcher) { + return org.hamcrest.core.Every.<U>everyItem(itemMatcher); + } + + /** + * Decorates another Matcher, retaining its behaviour, but allowing tests + * to be slightly more expressive. + * For example: + * <pre>assertThat(cheese, is(equalTo(smelly)))</pre> + * instead of: + * <pre>assertThat(cheese, equalTo(smelly))</pre> + */ + public static <T> org.hamcrest.Matcher<T> is(org.hamcrest.Matcher<T> matcher) { + return org.hamcrest.core.Is.<T>is(matcher); + } + + /** + * A shortcut to the frequently used <code>is(equalTo(x))</code>. + * For example: + * <pre>assertThat(cheese, is(smelly))</pre> + * instead of: + * <pre>assertThat(cheese, is(equalTo(smelly)))</pre> + */ + public static <T> org.hamcrest.Matcher<T> is(T value) { + return org.hamcrest.core.Is.<T>is(value); + } /** * Provided to cause compile time error when used in preference to a possible runtime error if @@ -40,275 +216,1370 @@ public class Matchers { public static void is(java.lang.Class<?> type) { } - /** - * Inverts the rule. - */ - public static <T> org.hamcrest.Matcher<T> not(org.hamcrest.Matcher<T> matcher) { - return org.hamcrest.core.IsNot.not(matcher); - } - - /** - * This is a shortcut to the frequently used not(equalTo(x)). - * - * eg. assertThat(cheese, is(not(equalTo(smelly)))) - * vs assertThat(cheese, is(not(smelly))) - */ - public static <T> org.hamcrest.Matcher<T> not(T value) { - return org.hamcrest.core.IsNot.not(value); - } - - /** - * Is the value equal to another value, as tested by the - * {@link java.lang.Object#equals} invokedMethod? - */ - public static <T> org.hamcrest.Matcher<T> equalTo(T operand) { - return org.hamcrest.core.IsEqual.equalTo(operand); - } - - /** - * Is the value an instance of a particular type? - */ - public static org.hamcrest.Matcher<java.lang.Object> instanceOf(java.lang.Class<?> type) { - return org.hamcrest.core.IsInstanceOf.instanceOf(type); - } - - /** - * Evaluates to true only if ALL of the passed in matchers evaluate to true. - */ - public static <T> org.hamcrest.Matcher<T> allOf(org.hamcrest.Matcher<? extends T>... matchers) { - return org.hamcrest.core.AllOf.<T>allOf(matchers); - } - - /** - * Evaluates to true only if ALL of the passed in matchers evaluate to true. - */ - public static <T> org.hamcrest.Matcher<T> allOf(java.lang.Iterable<org.hamcrest.Matcher<? extends T>> matchers) { - return org.hamcrest.core.AllOf.allOf(matchers); - } - - /** - * Evaluates to true if ANY of the passed in matchers evaluate to true. - */ - public static <T> org.hamcrest.Matcher<T> anyOf(org.hamcrest.Matcher<? extends T>... matchers) { - return org.hamcrest.core.AnyOf.<T>anyOf(matchers); - } - - /** - * Evaluates to true if ANY of the passed in matchers evaluate to true. - */ - public static <T> org.hamcrest.Matcher<T> anyOf(java.lang.Iterable<org.hamcrest.Matcher<? extends T>> matchers) { - return org.hamcrest.core.AnyOf.anyOf(matchers); - } - - /** - * Creates a new instance of IsSame - * - * @param object The predicate evaluates to true only when the argument is - * this object. - */ - public static <T> org.hamcrest.Matcher<T> sameInstance(T object) { - return org.hamcrest.core.IsSame.sameInstance(object); - } - - /** - * This matcher always evaluates to true. - */ - public static <T> org.hamcrest.Matcher<T> anything() { - return org.hamcrest.core.IsAnything.anything(); - } - - /** - * This matcher always evaluates to true. - * - * @param description A meaningful string used when describing itself. - */ - public static <T> org.hamcrest.Matcher<T> anything(java.lang.String description) { - return org.hamcrest.core.IsAnything.anything(description); - } - - /** - * This matcher always evaluates to true. With type inference. - */ - public static <T> org.hamcrest.Matcher<T> any(java.lang.Class<T> type) { - return org.hamcrest.core.IsAnything.any(type); - } - - /** - * Matches if value is null. - */ - public static <T> org.hamcrest.Matcher<T> nullValue() { - return org.hamcrest.core.IsNull.nullValue(); - } - - /** - * Matches if value is null. With type inference. - */ - public static <T> org.hamcrest.Matcher<T> nullValue(java.lang.Class<T> type) { - return org.hamcrest.core.IsNull.nullValue(type); - } - - /** - * Matches if value is not null. - */ - public static <T> org.hamcrest.Matcher<T> notNullValue() { - return org.hamcrest.core.IsNull.notNullValue(); - } - - /** - * Matches if value is not null. With type inference. - */ - public static <T> org.hamcrest.Matcher<T> notNullValue(java.lang.Class<T> type) { - return org.hamcrest.core.IsNull.notNullValue(type); - } - - /** - * Wraps an existing matcher and overrides the description when it fails. - */ - public static <T> org.hamcrest.Matcher<T> describedAs(java.lang.String description, org.hamcrest.Matcher<T> matcher, java.lang.Object... values) { - return org.hamcrest.core.DescribedAs.describedAs(description, matcher, values); - } - - public static <T> org.hamcrest.Matcher<T[]> hasItemInArray(org.hamcrest.Matcher<T> elementMatcher) { - return org.hamcrest.collection.IsArrayContaining.hasItemInArray(elementMatcher); - } - - public static <T> org.hamcrest.Matcher<T[]> hasItemInArray(T element) { - return org.hamcrest.collection.IsArrayContaining.hasItemInArray(element); - } - - public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItem(T element) { - return org.hamcrest.collection.IsCollectionContaining.hasItem(element); - } - - public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItem(org.hamcrest.Matcher<? extends T> elementMatcher) { - return org.hamcrest.collection.IsCollectionContaining.<T>hasItem(elementMatcher); - } - - public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(org.hamcrest.Matcher<? extends T>... elementMatchers) { - return org.hamcrest.collection.IsCollectionContaining.<T>hasItems(elementMatchers); - } - - public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... elements) { - return org.hamcrest.collection.IsCollectionContaining.hasItems(elements); - } - - public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasEntry(org.hamcrest.Matcher<K> keyMatcher, org.hamcrest.Matcher<V> valueMatcher) { - return org.hamcrest.collection.IsMapContaining.hasEntry(keyMatcher, valueMatcher); - } - - public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasEntry(K key, V value) { - return org.hamcrest.collection.IsMapContaining.hasEntry(key, value); - } - - public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasKey(org.hamcrest.Matcher<K> keyMatcher) { - return org.hamcrest.collection.IsMapContaining.hasKey(keyMatcher); - } - - public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasKey(K key) { - return org.hamcrest.collection.IsMapContaining.hasKey(key); - } - - public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasValue(org.hamcrest.Matcher<V> valueMatcher) { - return org.hamcrest.collection.IsMapContaining.hasValue(valueMatcher); - } - - public static <K, V> org.hamcrest.Matcher<java.util.Map<K, V>> hasValue(V value) { - return org.hamcrest.collection.IsMapContaining.hasValue(value); - } - - public static <T> org.hamcrest.Matcher<T> isIn(java.util.Collection<T> collection) { - return org.hamcrest.collection.IsIn.isIn(collection); - } - - public static <T> org.hamcrest.Matcher<T> isIn(T[] param1) { - return org.hamcrest.collection.IsIn.isIn(param1); - } - - public static <T> org.hamcrest.Matcher<T> isOneOf(T... elements) { - return org.hamcrest.collection.IsIn.isOneOf(elements); - } - - public static org.hamcrest.Matcher<java.lang.Double> closeTo(double operand, double error) { - return org.hamcrest.number.IsCloseTo.closeTo(operand, error); - } - - public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> greaterThan(T value) { - return org.hamcrest.number.OrderingComparisons.greaterThan(value); - } - - public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> greaterThanOrEqualTo(T value) { - return org.hamcrest.number.OrderingComparisons.greaterThanOrEqualTo(value); - } - - public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> lessThan(T value) { - return org.hamcrest.number.OrderingComparisons.lessThan(value); - } - - public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> lessThanOrEqualTo(T value) { - return org.hamcrest.number.OrderingComparisons.lessThanOrEqualTo(value); - } - - public static org.hamcrest.Matcher<java.lang.String> equalToIgnoringCase(java.lang.String string) { - return org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase(string); - } - - public static org.hamcrest.Matcher<java.lang.String> equalToIgnoringWhiteSpace(java.lang.String string) { - return org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace(string); - } - - public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) { - return org.hamcrest.text.StringContains.containsString(substring); - } - - public static org.hamcrest.Matcher<java.lang.String> endsWith(java.lang.String substring) { - return org.hamcrest.text.StringEndsWith.endsWith(substring); - } - - public static org.hamcrest.Matcher<java.lang.String> startsWith(java.lang.String substring) { - return org.hamcrest.text.StringStartsWith.startsWith(substring); - } + /** + * A shortcut to the frequently used <code>is(instanceOf(SomeClass.class))</code>. + * For example: + * <pre>assertThat(cheese, isA(Cheddar.class))</pre> + * instead of: + * <pre>assertThat(cheese, is(instanceOf(Cheddar.class)))</pre> + */ + public static <T> org.hamcrest.Matcher<T> isA(java.lang.Class<T> type) { + return org.hamcrest.core.Is.<T>isA(type); + } + + /** + * Creates a matcher that always matches, regardless of the examined object. + */ + public static org.hamcrest.Matcher<java.lang.Object> anything() { + return org.hamcrest.core.IsAnything.anything(); + } + + /** + * Creates a matcher that always matches, regardless of the examined object, but describes + * itself with the specified {@link String}. + * + * @param description + * a meaningful {@link String} used when describing itself + */ + public static org.hamcrest.Matcher<java.lang.Object> anything(java.lang.String description) { + return org.hamcrest.core.IsAnything.anything(description); + } + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields at least one item that is matched by the specified + * <code>itemMatcher</code>. Whilst matching, the traversal of the examined {@link Iterable} + * will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem(startsWith("ba")))</pre> + * + * @param itemMatcher + * the matcher to apply to items provided by the examined {@link Iterable} + */ + public static <T> org.hamcrest.Matcher<java.lang.Iterable<? super T>> hasItem(org.hamcrest.Matcher<? super T> itemMatcher) { + return org.hamcrest.core.IsCollectionContaining.<T>hasItem(itemMatcher); + } + + /** + * Creates a matcher for {@link Iterable}s that only matches when a single pass over the + * examined {@link Iterable} yields at least one item that is equal to the specified + * <code>item</code>. Whilst matching, the traversal of the examined {@link Iterable} + * will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasItem("bar"))</pre> + * + * @param item + * the item to compare against the items provided by the examined {@link Iterable} + */ + public static <T> org.hamcrest.Matcher<java.lang.Iterable<? super T>> hasItem(T item) { + return org.hamcrest.core.IsCollectionContaining.<T>hasItem(item); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the + * examined {@link Iterable} yield at least one item that is matched by the corresponding + * matcher from the specified <code>itemMatchers</code>. Whilst matching, each traversal of + * the examined {@link Iterable} will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems(endsWith("z"), endsWith("o")))</pre> + * + * @param itemMatchers + * the matchers to apply to items provided by the examined {@link Iterable} + */ + public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(org.hamcrest.Matcher<? super T>... itemMatchers) { + return org.hamcrest.core.IsCollectionContaining.<T>hasItems(itemMatchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the + * examined {@link Iterable} yield at least one item that is equal to the corresponding + * item from the specified <code>items</code>. Whilst matching, each traversal of the + * examined {@link Iterable} will stop as soon as a matching item is found. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar", "baz"), hasItems("baz", "foo"))</pre> + * + * @param items + * the items to compare against the items provided by the examined {@link Iterable} + */ + public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(T... items) { + return org.hamcrest.core.IsCollectionContaining.<T>hasItems(items); + } + + /** + * Creates a matcher that matches when the examined object is logically equal to the specified + * <code>operand</code>, as determined by calling the {@link java.lang.Object#equals} method on + * the <b>examined</b> object. + * + * <p>If the specified operand is <code>null</code> then the created matcher will only match if + * the examined object's <code>equals</code> method returns <code>true</code> when passed a + * <code>null</code> (which would be a violation of the <code>equals</code> contract), unless the + * examined object itself is <code>null</code>, in which case the matcher will return a positive + * match.</p> + * + * <p>The created matcher provides a special behaviour when examining <code>Array</code>s, whereby + * it will match if both the operand and the examined object are arrays of the same length and + * contain items that are equal to each other (according to the above rules) <b>in the same + * indexes</b>.</p> + * For example: + * <pre> + * assertThat("foo", equalTo("foo")); + * assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"})); + * </pre> + */ + public static <T> org.hamcrest.Matcher<T> equalTo(T operand) { + return org.hamcrest.core.IsEqual.<T>equalTo(operand); + } + + /** + * Creates an {@link org.hamcrest.core.IsEqual} matcher that does not enforce the values being + * compared to be of the same static type. + */ + public static org.hamcrest.Matcher<java.lang.Object> equalToObject(java.lang.Object operand) { + return org.hamcrest.core.IsEqual.equalToObject(operand); + } + + /** + * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>, + * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the + * the examined object. + * + * <p>The created matcher forces a relationship between specified type and the examined object, and should be + * used when it is necessary to make generics conform, for example in the JMock clause + * <code>with(any(Thing.class))</code></p> + * For example: + * <pre>assertThat(new Canoe(), instanceOf(Canoe.class));</pre> + */ + public static <T> org.hamcrest.Matcher<T> any(java.lang.Class<T> type) { + return org.hamcrest.core.IsInstanceOf.<T>any(type); + } + + /** + * Creates a matcher that matches when the examined object is an instance of the specified <code>type</code>, + * as determined by calling the {@link java.lang.Class#isInstance(Object)} method on that type, passing the + * the examined object. + * + * <p>The created matcher assumes no relationship between specified type and the examined object.</p> + * For example: + * <pre>assertThat(new Canoe(), instanceOf(Paddlable.class));</pre> + */ + public static <T> org.hamcrest.Matcher<T> instanceOf(java.lang.Class<?> type) { + return org.hamcrest.core.IsInstanceOf.<T>instanceOf(type); + } + + /** + * Creates a matcher that wraps an existing matcher, but inverts the logic by which + * it will match. + * For example: + * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre> + * + * @param matcher + * the matcher whose sense should be inverted + */ + public static <T> org.hamcrest.Matcher<T> not(org.hamcrest.Matcher<T> matcher) { + return org.hamcrest.core.IsNot.<T>not(matcher); + } + + /** + * A shortcut to the frequently used <code>not(equalTo(x))</code>. + * For example: + * <pre>assertThat(cheese, is(not(smelly)))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(equalTo(smelly))))</pre> + * + * @param value + * the value that any examined object should <b>not</b> equal + */ + public static <T> org.hamcrest.Matcher<T> not(T value) { + return org.hamcrest.core.IsNot.<T>not(value); + } + + /** + * A shortcut to the frequently used <code>not(nullValue())</code>. + * For example: + * <pre>assertThat(cheese, is(notNullValue()))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(nullValue())))</pre> + */ + public static org.hamcrest.Matcher<java.lang.Object> notNullValue() { + return org.hamcrest.core.IsNull.notNullValue(); + } + + /** + * A shortcut to the frequently used <code>not(nullValue(X.class)). Accepts a + * single dummy argument to facilitate type inference.</code>. + * For example: + * <pre>assertThat(cheese, is(notNullValue(X.class)))</pre> + * instead of: + * <pre>assertThat(cheese, is(not(nullValue(X.class))))</pre> + * + * @param type + * dummy parameter used to infer the generic type of the returned matcher + */ + public static <T> org.hamcrest.Matcher<T> notNullValue(java.lang.Class<T> type) { + return org.hamcrest.core.IsNull.<T>notNullValue(type); + } + + /** + * Creates a matcher that matches if examined object is <code>null</code>. + * For example: + * <pre>assertThat(cheese, is(nullValue())</pre> + */ + public static org.hamcrest.Matcher<java.lang.Object> nullValue() { + return org.hamcrest.core.IsNull.nullValue(); + } + + /** + * Creates a matcher that matches if examined object is <code>null</code>. Accepts a + * single dummy argument to facilitate type inference. + * For example: + * <pre>assertThat(cheese, is(nullValue(Cheese.class))</pre> + * + * @param type + * dummy parameter used to infer the generic type of the returned matcher + */ + public static <T> org.hamcrest.Matcher<T> nullValue(java.lang.Class<T> type) { + return org.hamcrest.core.IsNull.<T>nullValue(type); + } + + /** + * Creates a matcher that matches only when the examined object is the same instance as + * the specified target object. + * + * @param target + * the target instance against which others should be assessed + */ + public static <T> org.hamcrest.Matcher<T> sameInstance(T target) { + return org.hamcrest.core.IsSame.<T>sameInstance(target); + } + + /** + * Creates a matcher that matches only when the examined object is the same instance as + * the specified target object. + * + * @param target + * the target instance against which others should be assessed + */ + public static <T> org.hamcrest.Matcher<T> theInstance(T target) { + return org.hamcrest.core.IsSame.<T>theInstance(target); + } + + /** + * Creates a matcher that matches if the examined {@link String} contains the specified + * {@link String} anywhere. + * For example: + * <pre>assertThat("myStringOfNote", containsString("ring"))</pre> + * + * @param substring + * the substring that the returned matcher will expect to find within any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) { + return org.hamcrest.core.StringContains.containsString(substring); + } + + /** + * Creates a matcher that matches if the examined {@link String} contains the specified + * {@link String} anywhere, ignoring case. + * For example: + * <pre>assertThat("myStringOfNote", containsString("ring"))</pre> + * + * @param substring + * the substring that the returned matcher will expect to find within any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> containsStringIgnoringCase(java.lang.String substring) { + return org.hamcrest.core.StringContains.containsStringIgnoringCase(substring); + } + + /** + * <p> + * Creates a matcher that matches if the examined {@link String} starts with the specified + * {@link String}. + * </p> + * For example: + * <pre>assertThat("myStringOfNote", startsWith("my"))</pre> + * + * @param prefix + * the substring that the returned matcher will expect at the start of any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> startsWith(java.lang.String prefix) { + return org.hamcrest.core.StringStartsWith.startsWith(prefix); + } + + /** + * <p> + * Creates a matcher that matches if the examined {@link String} starts with the specified + * {@link String}, ignoring case + * </p> + * For example: + * <pre>assertThat("myStringOfNote", startsWith("my"))</pre> + * + * @param prefix + * the substring that the returned matcher will expect at the start of any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> startsWithIgnoringCase(java.lang.String prefix) { + return org.hamcrest.core.StringStartsWith.startsWithIgnoringCase(prefix); + } + + /** + * Creates a matcher that matches if the examined {@link String} ends with the specified + * {@link String}. + * For example: + * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre> + * + * @param suffix + * the substring that the returned matcher will expect at the end of any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> endsWith(java.lang.String suffix) { + return org.hamcrest.core.StringEndsWith.endsWith(suffix); + } + + /** + * Creates a matcher that matches if the examined {@link String} ends with the specified + * {@link String}, ignoring case. + * For example: + * <pre>assertThat("myStringOfNote", endsWith("Note"))</pre> + * + * @param suffix + * the substring that the returned matcher will expect at the end of any examined string + */ + public static org.hamcrest.Matcher<java.lang.String> endsWithIgnoringCase(java.lang.String suffix) { + return org.hamcrest.core.StringEndsWith.endsWithIgnoringCase(suffix); + } + + /** + * Creates a matcher that matches arrays whose elements are satisfied by the specified matchers. Matches + * positively only if the number of matchers specified is equal to the length of the examined array and + * each matcher[i] is satisfied by array[i]. + * For example: + * <pre>assertThat(new Integer[]{1,2,3}, is(array(equalTo(1), equalTo(2), equalTo(3))))</pre> + * + * @param elementMatchers + * the matchers that the elements of examined arrays should satisfy + */ + public static <T> org.hamcrest.collection.IsArray<T> array(org.hamcrest.Matcher<? super T>... elementMatchers) { + return org.hamcrest.collection.IsArray.<T>array(elementMatchers); + } + + /** + * Creates a matcher for arrays that matches when the examined array contains at least one item + * that is matched by the specified <code>elementMatcher</code>. Whilst matching, the traversal + * of the examined array will stop as soon as a matching element is found. + * For example: + * <pre>assertThat(new String[] {"foo", "bar"}, hasItemInArray(startsWith("ba")))</pre> + * + * @param elementMatcher + * the matcher to apply to elements in examined arrays + */ + public static <T> org.hamcrest.Matcher<T[]> hasItemInArray(org.hamcrest.Matcher<? super T> elementMatcher) { + return org.hamcrest.collection.IsArrayContaining.<T>hasItemInArray(elementMatcher); + } + + /** + * A shortcut to the frequently used <code>hasItemInArray(equalTo(x))</code>. + * For example: + * <pre>assertThat(hasItemInArray(x))</pre> + * instead of: + * <pre>assertThat(hasItemInArray(equalTo(x)))</pre> + * + * @param element + * the element that should be present in examined arrays + */ + public static <T> org.hamcrest.Matcher<T[]> hasItemInArray(T element) { + return org.hamcrest.collection.IsArrayContaining.<T>hasItemInArray(element); + } + + /** + * Creates a matcher for arrays that matches when each item in the examined array is + * logically equal to the corresponding item in the specified items. For a positive match, + * the examined array must be of the same length as the number of specified items. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, contains("foo", "bar"))</pre> + * + * @param items + * the items that must equal the items within an examined array + */ + public static <E> org.hamcrest.Matcher<E[]> arrayContaining(E... items) { + return org.hamcrest.collection.IsArrayContainingInOrder.<E>arrayContaining(items); + } + + /** + * Creates a matcher for arrays that matches when each item in the examined array satisfies the + * corresponding matcher in the specified matchers. For a positive match, the examined array + * must be of the same length as the number of specified matchers. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, contains(equalTo("foo"), equalTo("bar")))</pre> + * + * @param itemMatchers + * the matchers that must be satisfied by the items in the examined array + */ + public static <E> org.hamcrest.Matcher<E[]> arrayContaining(org.hamcrest.Matcher<? super E>... itemMatchers) { + return org.hamcrest.collection.IsArrayContainingInOrder.<E>arrayContaining(itemMatchers); + } + + /** + * Creates a matcher for arrays that matches when each item in the examined array satisfies the + * corresponding matcher in the specified list of matchers. For a positive match, the examined array + * must be of the same length as the specified list of matchers. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, contains(Arrays.asList(equalTo("foo"), equalTo("bar"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by the corresponding item in an examined array + */ + public static <E> org.hamcrest.Matcher<E[]> arrayContaining(java.util.List<org.hamcrest.Matcher<? super E>> itemMatchers) { + return org.hamcrest.collection.IsArrayContainingInOrder.<E>arrayContaining(itemMatchers); + } + + /** + * <p> + * Creates an order agnostic matcher for arrays that matches when each item in the + * examined array satisfies one matcher anywhere in the specified matchers. + * For a positive match, the examined array must be of the same length as the number of + * specified matchers. + * </p> + * <p> + * N.B. each of the specified matchers will only be used once during a given examination, so be + * careful when specifying matchers that may be satisfied by more than one entry in an examined + * array. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(new String[]{"foo", "bar"}, arrayContainingInAnyOrder(equalTo("bar"), equalTo("foo")))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by an entry in an examined array + */ + public static <E> org.hamcrest.Matcher<E[]> arrayContainingInAnyOrder(org.hamcrest.Matcher<? super E>... itemMatchers) { + return org.hamcrest.collection.IsArrayContainingInAnyOrder.<E>arrayContainingInAnyOrder(itemMatchers); + } + + /** + * <p> + * Creates an order agnostic matcher for arrays that matches when each item in the + * examined array satisfies one matcher anywhere in the specified collection of matchers. + * For a positive match, the examined array must be of the same length as the specified collection + * of matchers. + * </p> + * <p> + * N.B. each matcher in the specified collection will only be used once during a given + * examination, so be careful when specifying matchers that may be satisfied by more than + * one entry in an examined array. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(new String[]{"foo", "bar"}, arrayContainingInAnyOrder(Arrays.asList(equalTo("bar"), equalTo("foo"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by an item provided by an examined array + */ + public static <E> org.hamcrest.Matcher<E[]> arrayContainingInAnyOrder(java.util.Collection<org.hamcrest.Matcher<? super E>> itemMatchers) { + return org.hamcrest.collection.IsArrayContainingInAnyOrder.<E>arrayContainingInAnyOrder(itemMatchers); + } + + /** + * <p>Creates an order agnostic matcher for arrays that matches when each item in the + * examined array is logically equal to one item anywhere in the specified items. + * For a positive match, the examined array must be of the same length as the number of + * specified items. + * </p> + * <p>N.B. each of the specified items will only be used once during a given examination, so be + * careful when specifying items that may be equal to more than one entry in an examined + * array. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(new String[]{"foo", "bar"}, containsInAnyOrder("bar", "foo"))</pre> + * + * @param items + * the items that must equal the entries of an examined array, in any order + */ + public static <E> org.hamcrest.Matcher<E[]> arrayContainingInAnyOrder(E... items) { + return org.hamcrest.collection.IsArrayContainingInAnyOrder.<E>arrayContainingInAnyOrder(items); + } + + /** + * Creates a matcher for arrays that matches when the <code>length</code> of the array + * satisfies the specified matcher. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, arrayWithSize(equalTo(2)))</pre> + * + * @param sizeMatcher + * a matcher for the length of an examined array + */ + public static <E> org.hamcrest.Matcher<E[]> arrayWithSize(org.hamcrest.Matcher<? super java.lang.Integer> sizeMatcher) { + return org.hamcrest.collection.IsArrayWithSize.<E>arrayWithSize(sizeMatcher); + } + + /** + * Creates a matcher for arrays that matches when the <code>length</code> of the array + * equals the specified <code>size</code>. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, arrayWithSize(2))</pre> + * + * @param size + * the length that an examined array must have for a positive match + */ + public static <E> org.hamcrest.Matcher<E[]> arrayWithSize(int size) { + return org.hamcrest.collection.IsArrayWithSize.<E>arrayWithSize(size); + } + + /** + * Creates a matcher for arrays that matches when the <code>length</code> of the array + * is zero. + * For example: + * <pre>assertThat(new String[0], emptyArray())</pre> + */ + public static <E> org.hamcrest.Matcher<E[]> emptyArray() { + return org.hamcrest.collection.IsArrayWithSize.<E>emptyArray(); + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns + * a value that satisfies the specified matcher. + * For example: + * <pre>assertThat(myMap, is(aMapWithSize(equalTo(2))))</pre> + * + * @param sizeMatcher + * a matcher for the size of an examined {@link java.util.Map} + */ + public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> aMapWithSize(org.hamcrest.Matcher<? super java.lang.Integer> sizeMatcher) { + return org.hamcrest.collection.IsMapWithSize.<K,V>aMapWithSize(sizeMatcher); + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns + * a value equal to the specified <code>size</code>. + * For example: + * <pre>assertThat(myMap, is(aMapWithSize(2)))</pre> + * + * @param size + * the expected size of an examined {@link java.util.Map} + */ + public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> aMapWithSize(int size) { + return org.hamcrest.collection.IsMapWithSize.<K,V>aMapWithSize(size); + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns + * zero. + * For example: + * <pre>assertThat(myMap, is(anEmptyMap()))</pre> + */ + public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> anEmptyMap() { + return org.hamcrest.collection.IsMapWithSize.<K,V>anEmptyMap(); + } + + /** + * Creates a matcher for {@link java.util.Collection}s that matches when the <code>size()</code> method returns + * a value that satisfies the specified matcher. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasSize(equalTo(2)))</pre> + * + * @param sizeMatcher + * a matcher for the size of an examined {@link java.util.Collection} + */ + public static <E> org.hamcrest.Matcher<java.util.Collection<? extends E>> hasSize(org.hamcrest.Matcher<? super java.lang.Integer> sizeMatcher) { + return org.hamcrest.collection.IsCollectionWithSize.<E>hasSize(sizeMatcher); + } + + /** + * Creates a matcher for {@link java.util.Collection}s that matches when the <code>size()</code> method returns + * a value equal to the specified <code>size</code>. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasSize(2))</pre> + * + * @param size + * the expected size of an examined {@link java.util.Collection} + */ + public static <E> org.hamcrest.Matcher<java.util.Collection<? extends E>> hasSize(int size) { + return org.hamcrest.collection.IsCollectionWithSize.<E>hasSize(size); + } + + /** + * Creates a matcher for {@link java.util.Collection}s matching examined collections whose <code>isEmpty</code> + * method returns <code>true</code>. + * For example: + * <pre>assertThat(new ArrayList<String>(), is(empty()))</pre> + */ + public static <E> org.hamcrest.Matcher<java.util.Collection<? extends E>> empty() { + return org.hamcrest.collection.IsEmptyCollection.<E>empty(); + } + + /** + * Creates a matcher for {@link java.util.Collection}s matching examined collections whose <code>isEmpty</code> + * method returns <code>true</code>. + * For example: + * <pre>assertThat(new ArrayList<String>(), is(emptyCollectionOf(String.class)))</pre> + * + * @param unusedToForceReturnType + * the type of the collection's content + */ + public static <E> org.hamcrest.Matcher<java.util.Collection<E>> emptyCollectionOf(java.lang.Class<E> unusedToForceReturnType) { + return org.hamcrest.collection.IsEmptyCollection.<E>emptyCollectionOf(unusedToForceReturnType); + } + + /** + * Creates a matcher for {@link Iterable}s matching examined iterables that yield no items. + * For example: + * <pre>assertThat(new ArrayList<String>(), is(emptyIterable()))</pre> + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> emptyIterable() { + return org.hamcrest.collection.IsEmptyIterable.<E>emptyIterable(); + } + + /** + * Creates a matcher for {@link Iterable}s matching examined iterables that yield no items. + * For example: + * <pre>assertThat(new ArrayList<String>(), is(emptyIterableOf(String.class)))</pre> + * + * @param unusedToForceReturnType + * the type of the iterable's content + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<E>> emptyIterableOf(java.lang.Class<E> unusedToForceReturnType) { + return org.hamcrest.collection.IsEmptyIterable.<E>emptyIterableOf(unusedToForceReturnType); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, each logically equal to the + * corresponding item in the specified items. For a positive match, the examined iterable + * must be of the same length as the number of specified items. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), contains("foo", "bar"))</pre> + * + * @param items + * the items that must equal the items provided by an examined {@link Iterable} + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(E... items) { + return org.hamcrest.collection.IsIterableContainingInOrder.<E>contains(items); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a single item that satisfies the specified matcher. + * For a positive match, the examined iterable must only yield one item. + * For example: + * <pre>assertThat(Arrays.asList("foo"), contains(equalTo("foo")))</pre> + * + * @param itemMatcher + * the matcher that must be satisfied by the single item provided by an + * examined {@link Iterable} + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(org.hamcrest.Matcher<? super E> itemMatcher) { + return org.hamcrest.collection.IsIterableContainingInOrder.<E>contains(itemMatcher); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, each satisfying the corresponding + * matcher in the specified matchers. For a positive match, the examined iterable + * must be of the same length as the number of specified matchers. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), contains(equalTo("foo"), equalTo("bar")))</pre> + * + * @param itemMatchers + * the matchers that must be satisfied by the items provided by an examined {@link Iterable} + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(org.hamcrest.Matcher<? super E>... itemMatchers) { + return org.hamcrest.collection.IsIterableContainingInOrder.<E>contains(itemMatchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, each satisfying the corresponding + * matcher in the specified list of matchers. For a positive match, the examined iterable + * must be of the same length as the specified list of matchers. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), contains(Arrays.asList(equalTo("foo"), equalTo("bar"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by the corresponding item provided by + * an examined {@link Iterable} + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> contains(java.util.List<org.hamcrest.Matcher<? super E>> itemMatchers) { + return org.hamcrest.collection.IsIterableContainingInOrder.<E>contains(itemMatchers); + } + + /** + * <p> + * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over + * the examined {@link Iterable} yields a series of items, each satisfying one matcher anywhere + * in the specified matchers. For a positive match, the examined iterable must be of the same + * length as the number of specified matchers. + * </p> + * <p> + * N.B. each of the specified matchers will only be used once during a given examination, so be + * careful when specifying matchers that may be satisfied by more than one entry in an examined + * iterable. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder(equalTo("bar"), equalTo("foo")))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by an item provided by an examined {@link Iterable} + */ + public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(org.hamcrest.Matcher<? super T>... itemMatchers) { + return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder(itemMatchers); + } + + /** + * <p> + * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over + * the examined {@link Iterable} yields a series of items, each logically equal to one item + * anywhere in the specified items. For a positive match, the examined iterable + * must be of the same length as the number of specified items. + * </p> + * <p> + * N.B. each of the specified items will only be used once during a given examination, so be + * careful when specifying items that may be equal to more than one entry in an examined + * iterable. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder("bar", "foo"))</pre> + * + * @param items + * the items that must equal the items provided by an examined {@link Iterable} in any order + */ + public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(T... items) { + return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder(items); + } + + /** + * <p> + * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over + * the examined {@link Iterable} yields a series of items, each satisfying one matcher anywhere + * in the specified collection of matchers. For a positive match, the examined iterable + * must be of the same length as the specified collection of matchers. + * </p> + * <p> + * N.B. each matcher in the specified collection will only be used once during a given + * examination, so be careful when specifying matchers that may be satisfied by more than + * one entry in an examined iterable. + * </p> + * <p>For example:</p> + * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder(Arrays.asList(equalTo("bar"), equalTo("foo"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by an item provided by an examined {@link Iterable} + */ + public static <T> org.hamcrest.Matcher<java.lang.Iterable<? extends T>> containsInAnyOrder(java.util.Collection<org.hamcrest.Matcher<? super T>> itemMatchers) { + return org.hamcrest.collection.IsIterableContainingInAnyOrder.<T>containsInAnyOrder(itemMatchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, that contains items logically equal to the + * corresponding item in the specified items, in the same relative order + * For example: + * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder("b", "d"))</pre> + * + * @param items + * the items that must be contained within items provided by an examined {@link Iterable} in the same relative order + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> containsInRelativeOrder(E... items) { + return org.hamcrest.collection.IsIterableContainingInRelativeOrder.<E>containsInRelativeOrder(items); + } - public static <T> org.hamcrest.Matcher<T> hasToString(org.hamcrest.Matcher<java.lang.String> toStringMatcher) { - return org.hamcrest.object.HasToString.hasToString(toStringMatcher); - } + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, that each satisfying the corresponding + * matcher in the specified matchers, in the same relative order. + * For example: + * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder(equalTo("b"), equalTo("d")))</pre> + * + * @param itemMatchers + * the matchers that must be satisfied by the items provided by an examined {@link Iterable} in the same relative order + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> containsInRelativeOrder(org.hamcrest.Matcher<? super E>... itemMatchers) { + return org.hamcrest.collection.IsIterableContainingInRelativeOrder.<E>containsInRelativeOrder(itemMatchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, that contains items satisfying the corresponding + * matcher in the specified list of matchers, in the same relative order. + * For example: + * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), contains(Arrays.asList(equalTo("b"), equalTo("d"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by the items provided by + * an examined {@link Iterable} in the same relative order + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<? extends E>> containsInRelativeOrder(java.util.List<org.hamcrest.Matcher<? super E>> itemMatchers) { + return org.hamcrest.collection.IsIterableContainingInRelativeOrder.<E>containsInRelativeOrder(itemMatchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields an item count that satisfies the specified + * matcher. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), iterableWithSize(equalTo(2)))</pre> + * + * @param sizeMatcher + * a matcher for the number of items that should be yielded by an examined {@link Iterable} + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<E>> iterableWithSize(org.hamcrest.Matcher<? super java.lang.Integer> sizeMatcher) { + return org.hamcrest.collection.IsIterableWithSize.<E>iterableWithSize(sizeMatcher); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields an item count that is equal to the specified + * <code>size</code> argument. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), iterableWithSize(2))</pre> + * + * @param size + * the number of items that should be yielded by an examined {@link Iterable} + */ + public static <E> org.hamcrest.Matcher<java.lang.Iterable<E>> iterableWithSize(int size) { + return org.hamcrest.collection.IsIterableWithSize.<E>iterableWithSize(size); + } - public static <T> org.hamcrest.Matcher<java.lang.Class<?>> typeCompatibleWith(java.lang.Class<T> baseType) { - return org.hamcrest.object.IsCompatibleType.typeCompatibleWith(baseType); - } + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one entry whose key satisfies the specified <code>keyMatcher</code> <b>and</b> whose + * value satisfies the specified <code>valueMatcher</code>. + * For example: + * <pre>assertThat(myMap, hasEntry(equalTo("bar"), equalTo("foo")))</pre> + * + * @param keyMatcher + * the key matcher that, in combination with the valueMatcher, must be satisfied by at least one entry + * @param valueMatcher + * the value matcher that, in combination with the keyMatcher, must be satisfied by at least one entry + */ + public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher) { + return org.hamcrest.collection.IsMapContaining.<K,V>hasEntry(keyMatcher, valueMatcher); + } - /** - * Constructs an IsEventFrom Matcher that returns true for any object - * derived from <var>eventClass</var> announced by <var>source</var>. - */ - public static org.hamcrest.Matcher<java.util.EventObject> eventFrom(java.lang.Class<? extends java.util.EventObject> eventClass, java.lang.Object source) { - return org.hamcrest.object.IsEventFrom.eventFrom(eventClass, source); - } + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one entry whose key equals the specified <code>key</code> <b>and</b> whose value equals the + * specified <code>value</code>. + * For example: + * <pre>assertThat(myMap, hasEntry("bar", "foo"))</pre> + * + * @param key + * the key that, in combination with the value, must be describe at least one entry + * @param value + * the value that, in combination with the key, must be describe at least one entry + */ + public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K,? extends V>> hasEntry(K key, V value) { + return org.hamcrest.collection.IsMapContaining.<K,V>hasEntry(key, value); + } - /** - * Constructs an IsEventFrom Matcher that returns true for any object - * derived from {@link java.util.EventObject} announced by <var>source - * </var>. - */ - public static org.hamcrest.Matcher<java.util.EventObject> eventFrom(java.lang.Object source) { - return org.hamcrest.object.IsEventFrom.eventFrom(source); - } - - /* android-changed REMOVE - public static <T> org.hamcrest.Matcher<T> hasProperty(java.lang.String propertyName) { - return org.hamcrest.beans.HasProperty.hasProperty(propertyName); - } - - public static <T> org.hamcrest.Matcher<T> hasProperty(java.lang.String propertyName, org.hamcrest.Matcher value) { - return org.hamcrest.beans.HasPropertyWithValue.hasProperty(propertyName, value); - } - */ - - public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath, org.hamcrest.Matcher<java.lang.String> valueMatcher) { - return org.hamcrest.xml.HasXPath.hasXPath(xPath, valueMatcher); - } - - public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath) { - return org.hamcrest.xml.HasXPath.hasXPath(xPath); - } + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one key that satisfies the specified matcher. + * For example: + * <pre>assertThat(myMap, hasKey(equalTo("bar")))</pre> + * + * @param keyMatcher + * the matcher that must be satisfied by at least one key + */ + public static <K> org.hamcrest.Matcher<java.util.Map<? extends K,?>> hasKey(org.hamcrest.Matcher<? super K> keyMatcher) { + return org.hamcrest.collection.IsMapContaining.<K>hasKey(keyMatcher); + } + + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one key that is equal to the specified key. + * For example: + * <pre>assertThat(myMap, hasKey("bar"))</pre> + * + * @param key + * the key that satisfying maps must contain + */ + public static <K> org.hamcrest.Matcher<java.util.Map<? extends K,?>> hasKey(K key) { + return org.hamcrest.collection.IsMapContaining.<K>hasKey(key); + } + + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one value that satisfies the specified valueMatcher. + * For example: + * <pre>assertThat(myMap, hasValue(equalTo("foo")))</pre> + * + * @param valueMatcher + * the matcher that must be satisfied by at least one value + */ + public static <V> org.hamcrest.Matcher<java.util.Map<?,? extends V>> hasValue(org.hamcrest.Matcher<? super V> valueMatcher) { + return org.hamcrest.collection.IsMapContaining.<V>hasValue(valueMatcher); + } + + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one value that is equal to the specified value. + * For example: + * <pre>assertThat(myMap, hasValue("foo"))</pre> + * + * @param value + * the value that satisfying maps must contain + */ + public static <V> org.hamcrest.Matcher<java.util.Map<?,? extends V>> hasValue(V value) { + return org.hamcrest.collection.IsMapContaining.<V>hasValue(value); + } + + /** + * Creates a matcher that matches when the examined object is found within the + * specified collection. + * For example: + * <pre>assertThat("foo", is(in(Arrays.asList("bar", "foo"))))</pre> + * + * @param collection + * the collection in which matching items must be found + */ + public static <T> org.hamcrest.Matcher<T> in(java.util.Collection<T> collection) { + return org.hamcrest.collection.IsIn.<T>in(collection); + } + + /** + * Creates a matcher that matches when the examined object is found within the + * specified array. + * For example: + * <pre>assertThat("foo", is(in(new String[]{"bar", "foo"})))</pre> + * + * @param elements + * the array in which matching items must be found + */ + public static <T> org.hamcrest.Matcher<T> in(T[] elements) { + return org.hamcrest.collection.IsIn.<T>in(elements); + } + + /** + * Creates a matcher that matches when the examined object is found within the + * specified collection. + * For example: + * <pre>assertThat("foo", isIn(Arrays.asList("bar", "foo")))</pre> + * + * @deprecated use is(in(...)) instead + * @param collection + * the collection in which matching items must be found + */ + public static <T> org.hamcrest.Matcher<T> isIn(java.util.Collection<T> collection) { + return org.hamcrest.collection.IsIn.<T>isIn(collection); + } + + /** + * Creates a matcher that matches when the examined object is found within the + * specified array. + * For example: + * <pre>assertThat("foo", isIn(new String[]{"bar", "foo"}))</pre> + * + * @deprecated use is(in(...)) instead + * @param elements + * the array in which matching items must be found + */ + public static <T> org.hamcrest.Matcher<T> isIn(T[] elements) { + return org.hamcrest.collection.IsIn.<T>isIn(elements); + } + + /** + * Creates a matcher that matches when the examined object is equal to one of the + * specified elements. + * For example: + * <pre>assertThat("foo", isOneOf("bar", "foo"))</pre> + * + * @deprecated use is(oneOf(...)) instead + * @param elements + * the elements amongst which matching items will be found + */ + public static <T> org.hamcrest.Matcher<T> isOneOf(T... elements) { + return org.hamcrest.collection.IsIn.<T>isOneOf(elements); + } + + /** + * Creates a matcher that matches when the examined object is equal to one of the + * specified elements. + * For example: + * <pre>assertThat("foo", is(oneOf("bar", "foo")))</pre> + * + * @param elements + * the elements amongst which matching items will be found + */ + public static <T> org.hamcrest.Matcher<T> oneOf(T... elements) { + return org.hamcrest.collection.IsIn.<T>oneOf(elements); + } + + /** + * Creates a matcher of {@link Double}s that matches when an examined double is equal + * to the specified <code>operand</code>, within a range of +/- <code>error</code>. + * For example: + * <pre>assertThat(1.03, is(closeTo(1.0, 0.03)))</pre> + * + * @param operand + * the expected value of matching doubles + * @param error + * the delta (+/-) within which matches will be allowed + */ + public static org.hamcrest.Matcher<java.lang.Double> closeTo(double operand, double error) { + return org.hamcrest.number.IsCloseTo.closeTo(operand, error); + } + + /** + * Creates a matcher of {@link Double}s that matches when an examined double is not a number. + * For example: + * <pre>assertThat(Double.NaN, is(notANumber()))</pre> + */ + public static org.hamcrest.Matcher<java.lang.Double> notANumber() { + return org.hamcrest.number.IsNaN.notANumber(); + } + + /** + * Creates a matcher of {@link java.math.BigDecimal}s that matches when an examined BigDecimal is equal + * to the specified <code>operand</code>, within a range of +/- <code>error</code>. The comparison for equality + * is done by BigDecimals {@link java.math.BigDecimal#compareTo(java.math.BigDecimal)} method. + * For example: + * <pre>assertThat(new BigDecimal("1.03"), is(closeTo(new BigDecimal("1.0"), new BigDecimal("0.03"))))</pre> + * + * @param operand + * the expected value of matching BigDecimals + * @param error + * the delta (+/-) within which matches will be allowed + */ + public static org.hamcrest.Matcher<java.math.BigDecimal> closeTo(java.math.BigDecimal operand, java.math.BigDecimal error) { + return org.hamcrest.number.BigDecimalCloseTo.closeTo(operand, error); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * equal to the specified value, as reported by the <code>compareTo</code> method of the + * <b>examined</b> object. + * For example: + * <pre>assertThat(1, comparesEqualTo(1))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return zero + */ + public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> comparesEqualTo(T value) { + return org.hamcrest.number.OrderingComparison.<T>comparesEqualTo(value); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * greater than the specified value, as reported by the <code>compareTo</code> method of the + * <b>examined</b> object. + * For example: + * <pre>assertThat(2, greaterThan(1))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return greater + * than zero + */ + public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> greaterThan(T value) { + return org.hamcrest.number.OrderingComparison.<T>greaterThan(value); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * greater than or equal to the specified value, as reported by the <code>compareTo</code> method + * of the <b>examined</b> object. + * For example: + * <pre>assertThat(1, greaterThanOrEqualTo(1))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return greater + * than or equal to zero + */ + public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> greaterThanOrEqualTo(T value) { + return org.hamcrest.number.OrderingComparison.<T>greaterThanOrEqualTo(value); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * less than the specified value, as reported by the <code>compareTo</code> method of the + * <b>examined</b> object. + * For example: + * <pre>assertThat(1, lessThan(2))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return less + * than zero + */ + public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> lessThan(T value) { + return org.hamcrest.number.OrderingComparison.<T>lessThan(value); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * less than or equal to the specified value, as reported by the <code>compareTo</code> method + * of the <b>examined</b> object. + * For example: + * <pre>assertThat(1, lessThanOrEqualTo(1))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return less + * than or equal to zero + */ + public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<T> lessThanOrEqualTo(T value) { + return org.hamcrest.number.OrderingComparison.<T>lessThanOrEqualTo(value); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is equal to + * the specified expectedString, ignoring case. + * For example: + * <pre>assertThat("Foo", equalToIgnoringCase("FOO"))</pre> + * + * @param expectedString + * the expected value of matched strings + */ + public static org.hamcrest.Matcher<java.lang.String> equalToIgnoringCase(java.lang.String expectedString) { + return org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase(expectedString); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is equal to + * the specified expectedString, when whitespace differences are (mostly) ignored. To be + * exact, the following whitespace rules are applied: + * <ul> + * <li>all leading and trailing whitespace of both the expectedString and the examined string are ignored</li> + * <li>any remaining whitespace, appearing within either string, is collapsed to a single space before comparison</li> + * </ul> + * For example: + * <pre>assertThat(" my\tfoo bar ", equalToIgnoringWhiteSpace(" my foo bar"))</pre> + * + * @param expectedString + * the expected value of matched strings + */ + public static org.hamcrest.Matcher<java.lang.String> equalToIgnoringWhiteSpace(java.lang.String expectedString) { + return org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace(expectedString); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or + * has zero length. + * For example: + * <pre>assertThat(((String)null), is(emptyOrNullString()))</pre> + */ + public static org.hamcrest.Matcher<java.lang.String> emptyOrNullString() { + return org.hamcrest.text.IsEmptyString.emptyOrNullString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string has zero length. + * For example: + * <pre>assertThat("", is(emptyString()))</pre> + */ + public static org.hamcrest.Matcher<java.lang.String> emptyString() { + return org.hamcrest.text.IsEmptyString.emptyString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or + * has zero length. + * For example: + * <pre>assertThat(((String)null), isEmptyOrNullString())</pre> + * + * @deprecated use is(emptyOrNullString()) instead + */ + public static org.hamcrest.Matcher<java.lang.String> isEmptyOrNullString() { + return org.hamcrest.text.IsEmptyString.isEmptyOrNullString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string has zero length. + * For example: + * <pre>assertThat("", isEmptyString())</pre> + * + * @deprecated use is(emptyString()) instead + */ + public static org.hamcrest.Matcher<java.lang.String> isEmptyString() { + return org.hamcrest.text.IsEmptyString.isEmptyString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or + * contains zero or more whitespace characters and nothing else. + * For example: + * <pre>assertThat(((String)null), is(blankOrNullString()))</pre> + */ + public static org.hamcrest.Matcher<java.lang.String> blankOrNullString() { + return org.hamcrest.text.IsBlankString.blankOrNullString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string contains + * zero or more whitespace characters and nothing else. + * For example: + * <pre>assertThat(" ", is(blankString()))</pre> + */ + public static org.hamcrest.Matcher<java.lang.String> blankString() { + return org.hamcrest.text.IsBlankString.blankString(); + } + + /** + * Creates a matcher of {@link java.lang.String} that matches when the examined string + * exactly matches the given {@link java.util.regex.Pattern}. + */ + public static org.hamcrest.Matcher<java.lang.String> matchesPattern(java.util.regex.Pattern pattern) { + return org.hamcrest.text.MatchesPattern.matchesPattern(pattern); + } + + /** + * Creates a matcher of {@link java.lang.String} that matches when the examined string + * exactly matches the given regular expression, treated as a {@link java.util.regex.Pattern}. + */ + public static org.hamcrest.Matcher<java.lang.String> matchesPattern(java.lang.String regex) { + return org.hamcrest.text.MatchesPattern.matchesPattern(regex); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string contains all of + * the specified substrings, considering the order of their appearance. + * For example: + * <pre>assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("bar", "foo")))</pre> + * fails as "foo" occurs before "bar" in the string "myfoobarbaz" + * + * @param substrings + * the substrings that must be contained within matching strings + */ + public static org.hamcrest.Matcher<java.lang.String> stringContainsInOrder(java.lang.Iterable<java.lang.String> substrings) { + return org.hamcrest.text.StringContainsInOrder.stringContainsInOrder(substrings); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string contains all of + * the specified substrings, considering the order of their appearance. + * For example: + * <pre>assertThat("myfoobarbaz", stringContainsInOrder("bar", "foo"))</pre> + * fails as "foo" occurs before "bar" in the string "myfoobarbaz" + * + * @param substrings + * the substrings that must be contained within matching strings + */ + public static org.hamcrest.Matcher<java.lang.String> stringContainsInOrder(java.lang.String... substrings) { + return org.hamcrest.text.StringContainsInOrder.stringContainsInOrder(substrings); + } + + /** + * Creates a matcher that matches any examined object whose <code>toString</code> method + * returns a value that satisfies the specified matcher. + * For example: + * <pre>assertThat(true, hasToString(equalTo("TRUE")))</pre> + * + * @param toStringMatcher + * the matcher used to verify the toString result + */ + public static <T> org.hamcrest.Matcher<T> hasToString(org.hamcrest.Matcher<? super java.lang.String> toStringMatcher) { + return org.hamcrest.object.HasToString.<T>hasToString(toStringMatcher); + } + + /** + * Creates a matcher that matches any examined object whose <code>toString</code> method + * returns a value equalTo the specified string. + * For example: + * <pre>assertThat(true, hasToString("TRUE"))</pre> + * + * @param expectedToString + * the expected toString result + */ + public static <T> org.hamcrest.Matcher<T> hasToString(java.lang.String expectedToString) { + return org.hamcrest.object.HasToString.<T>hasToString(expectedToString); + } + + /** + * Creates a matcher of {@link Class} that matches when the specified baseType is + * assignable from the examined class. + * For example: + * <pre>assertThat(Integer.class, typeCompatibleWith(Number.class))</pre> + * + * @param baseType + * the base class to examine classes against + */ + public static <T> org.hamcrest.Matcher<java.lang.Class<?>> typeCompatibleWith(java.lang.Class<T> baseType) { + return org.hamcrest.object.IsCompatibleType.<T>typeCompatibleWith(baseType); + } + + /** + * Creates a matcher of {@link java.util.EventObject} that matches any object + * derived from <var>eventClass</var> announced by <var>source</var>. + * For example: + * <pre>assertThat(myEvent, is(eventFrom(PropertyChangeEvent.class, myBean)))</pre> + * + * @param eventClass + * the class of the event to match on + * @param source + * the source of the event + */ + public static org.hamcrest.Matcher<java.util.EventObject> eventFrom(java.lang.Class<? extends java.util.EventObject> eventClass, java.lang.Object source) { + return org.hamcrest.object.IsEventFrom.eventFrom(eventClass, source); + } + + /** + * Creates a matcher of {@link java.util.EventObject} that matches any EventObject + * announced by <var>source</var>. + * For example: + * <pre>assertThat(myEvent, is(eventFrom(myBean)))</pre> + * + * @param source + * the source of the event + */ + public static org.hamcrest.Matcher<java.util.EventObject> eventFrom(java.lang.Object source) { + return org.hamcrest.object.IsEventFrom.eventFrom(source); + } + + /** + * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the + * specified <code>xPath</code> that satisfies the specified <code>valueMatcher</code>. + * For example: + * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", equalTo("Cheddar")))</pre> + * + * @param xPath + * the target xpath + * @param valueMatcher + * matcher for the value at the specified xpath + */ + public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath, org.hamcrest.Matcher<java.lang.String> valueMatcher) { + return org.hamcrest.xml.HasXPath.hasXPath(xPath, valueMatcher); + } + + /** + * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the + * specified <code>xPath</code>, within the specified <code>namespaceContext</code>, that satisfies + * the specified <code>valueMatcher</code>. + * For example: + * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", myNs, equalTo("Cheddar")))</pre> + * + * @param xPath + * the target xpath + * @param namespaceContext + * the namespace for matching nodes + * @param valueMatcher + * matcher for the value at the specified xpath + */ + public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath, javax.xml.namespace.NamespaceContext namespaceContext, org.hamcrest.Matcher<java.lang.String> valueMatcher) { + return org.hamcrest.xml.HasXPath.hasXPath(xPath, namespaceContext, valueMatcher); + } + + /** + * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node + * at the specified <code>xPath</code>, with any content. + * For example: + * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese"))</pre> + * + * @param xPath + * the target xpath + */ + public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath) { + return org.hamcrest.xml.HasXPath.hasXPath(xPath); + } + + /** + * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node + * at the specified <code>xPath</code> within the specified namespace context, with any content. + * For example: + * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", myNs))</pre> + * + * @param xPath + * the target xpath + * @param namespaceContext + * the namespace for matching nodes + */ + public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String xPath, javax.xml.namespace.NamespaceContext namespaceContext) { + return org.hamcrest.xml.HasXPath.hasXPath(xPath, namespaceContext); + } } diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArray.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArray.java index 6a26ef1..38f5d91 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArray.java +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArray.java @@ -1,18 +1,23 @@ package org.hamcrest.collection; -import java.util.Arrays; - import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; +import java.util.Arrays; + +/** + * Matcher for array whose elements satisfy a sequence of matchers. + * The array size must equal the number of element matchers. + */ public class IsArray<T> extends TypeSafeMatcher<T[]> { - private final Matcher<T>[] elementMatchers; + private final Matcher<? super T>[] elementMatchers; - public IsArray(Matcher<T>[] elementMatchers) { + public IsArray(Matcher<? super T>[] elementMatchers) { this.elementMatchers = elementMatchers.clone(); } + @Override public boolean matchesSafely(T[] array) { if (array.length != elementMatchers.length) return false; @@ -22,7 +27,24 @@ public class IsArray<T> extends TypeSafeMatcher<T[]> { return true; } - + + @Override + public void describeMismatchSafely(T[] actual, Description mismatchDescription) { + if (actual.length != elementMatchers.length) { + mismatchDescription.appendText("array length was ").appendValue(actual.length); + return; + } + for (int i = 0; i < actual.length; i++) { + if (!elementMatchers[i].matches(actual[i])) { + mismatchDescription.appendText("element ").appendValue(i).appendText(" "); + elementMatchers[i].describeMismatch(actual[i], mismatchDescription); + return; + } + } + } + + @Override + @SuppressWarnings("unchecked") public void describeTo(Description description) { description.appendList(descriptionStart(), descriptionSeparator(), descriptionEnd(), Arrays.asList(elementMatchers)); @@ -58,7 +80,18 @@ public class IsArray<T> extends TypeSafeMatcher<T[]> { return "]"; } - public static <T> IsArray<T> array(Matcher<T>... elementMatchers) { + /** + * Creates a matcher that matches arrays whose elements are satisfied by the specified matchers. Matches + * positively only if the number of matchers specified is equal to the length of the examined array and + * each matcher[i] is satisfied by array[i]. + * For example: + * <pre>assertThat(new Integer[]{1,2,3}, is(array(equalTo(1), equalTo(2), equalTo(3))))</pre> + * + * @param elementMatchers + * the matchers that the elements of examined arrays should satisfy + */ + public static <T> IsArray<T> array(Matcher<? super T>... elementMatchers) { return new IsArray<T>(elementMatchers); } + } diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContaining.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContaining.java index 76ddf9d..749c7c6 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContaining.java +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContaining.java @@ -2,18 +2,23 @@ package org.hamcrest.collection; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; import org.hamcrest.TypeSafeMatcher; + +import java.util.Arrays; + import static org.hamcrest.core.IsEqual.equalTo; +/** + * Matches if an array contains an item satisfying a nested matcher. + */ public class IsArrayContaining<T> extends TypeSafeMatcher<T[]> { + private final Matcher<? super T> elementMatcher; - private final Matcher<T> elementMatcher; - - public IsArrayContaining(Matcher<T> elementMatcher) { + public IsArrayContaining(Matcher<? super T> elementMatcher) { this.elementMatcher = elementMatcher; } + @Override public boolean matchesSafely(T[] array) { for (T item : array) { if (elementMatcher.matches(item)) { @@ -22,21 +27,45 @@ public class IsArrayContaining<T> extends TypeSafeMatcher<T[]> { } return false; } + + @Override + public void describeMismatchSafely(T[] item, Description mismatchDescription) { + super.describeMismatch(Arrays.asList(item), mismatchDescription); + } + @Override public void describeTo(Description description) { description - .appendText("an array containing ") - .appendDescriptionOf(elementMatcher); + .appendText("an array containing ") + .appendDescriptionOf(elementMatcher); } - @Factory - public static <T> Matcher<T[]> hasItemInArray(Matcher<T> elementMatcher) { + /** + * Creates a matcher for arrays that matches when the examined array contains at least one item + * that is matched by the specified <code>elementMatcher</code>. Whilst matching, the traversal + * of the examined array will stop as soon as a matching element is found. + * For example: + * <pre>assertThat(new String[] {"foo", "bar"}, hasItemInArray(startsWith("ba")))</pre> + * + * @param elementMatcher + * the matcher to apply to elements in examined arrays + */ + public static <T> Matcher<T[]> hasItemInArray(Matcher<? super T> elementMatcher) { return new IsArrayContaining<T>(elementMatcher); } - @Factory + /** + * A shortcut to the frequently used <code>hasItemInArray(equalTo(x))</code>. + * For example: + * <pre>assertThat(hasItemInArray(x))</pre> + * instead of: + * <pre>assertThat(hasItemInArray(equalTo(x)))</pre> + * + * @param element + * the element that should be present in examined arrays + */ public static <T> Matcher<T[]> hasItemInArray(T element) { - return hasItemInArray(equalTo(element)); + Matcher<? super T> matcher = equalTo(element); + return IsArrayContaining.<T>hasItemInArray(matcher); } - } diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInAnyOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInAnyOrder.java new file mode 100644 index 0000000..a3a93c1 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInAnyOrder.java @@ -0,0 +1,112 @@ +package org.hamcrest.collection; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsArrayContainingInAnyOrder<E> extends TypeSafeMatcher<E[]> { + private final IsIterableContainingInAnyOrder<E> iterableMatcher; + private final Collection<Matcher<? super E>> matchers; + + public IsArrayContainingInAnyOrder(Collection<Matcher<? super E>> matchers) { + this.iterableMatcher = new IsIterableContainingInAnyOrder<E>(matchers); + this.matchers = matchers; + } + + @Override + public boolean matchesSafely(E[] item) { + return iterableMatcher.matches(Arrays.asList(item)); + } + + @Override + public void describeMismatchSafely(E[] item, Description mismatchDescription) { + iterableMatcher.describeMismatch(Arrays.asList(item), mismatchDescription); + } + + @Override + public void describeTo(Description description) { + description.appendList("[", ", ", "]", matchers) + .appendText(" in any order"); + } + + /** + * <p> + * Creates an order agnostic matcher for arrays that matches when each item in the + * examined array satisfies one matcher anywhere in the specified matchers. + * For a positive match, the examined array must be of the same length as the number of + * specified matchers. + * </p> + * <p> + * N.B. each of the specified matchers will only be used once during a given examination, so be + * careful when specifying matchers that may be satisfied by more than one entry in an examined + * array. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(new String[]{"foo", "bar"}, arrayContainingInAnyOrder(equalTo("bar"), equalTo("foo")))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by an entry in an examined array + */ + public static <E> Matcher<E[]> arrayContainingInAnyOrder(Matcher<? super E>... itemMatchers) { + return arrayContainingInAnyOrder((List) Arrays.asList(itemMatchers)); + } + + /** + * <p> + * Creates an order agnostic matcher for arrays that matches when each item in the + * examined array satisfies one matcher anywhere in the specified collection of matchers. + * For a positive match, the examined array must be of the same length as the specified collection + * of matchers. + * </p> + * <p> + * N.B. each matcher in the specified collection will only be used once during a given + * examination, so be careful when specifying matchers that may be satisfied by more than + * one entry in an examined array. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(new String[]{"foo", "bar"}, arrayContainingInAnyOrder(Arrays.asList(equalTo("bar"), equalTo("foo"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by an item provided by an examined array + */ + public static <E> Matcher<E[]> arrayContainingInAnyOrder(Collection<Matcher<? super E>> itemMatchers) { + return new IsArrayContainingInAnyOrder<E>(itemMatchers); + } + + /** + * <p>Creates an order agnostic matcher for arrays that matches when each item in the + * examined array is logically equal to one item anywhere in the specified items. + * For a positive match, the examined array must be of the same length as the number of + * specified items. + * </p> + * <p>N.B. each of the specified items will only be used once during a given examination, so be + * careful when specifying items that may be equal to more than one entry in an examined + * array. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(new String[]{"foo", "bar"}, containsInAnyOrder("bar", "foo"))</pre> + * + * @param items + * the items that must equal the entries of an examined array, in any order + */ + public static <E> Matcher<E[]> arrayContainingInAnyOrder(E... items) { + List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>(); + for (E item : items) { + matchers.add(equalTo(item)); + } + return new IsArrayContainingInAnyOrder<E>(matchers); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInOrder.java new file mode 100644 index 0000000..849920a --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayContainingInOrder.java @@ -0,0 +1,89 @@ +package org.hamcrest.collection; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.hamcrest.internal.NullSafety; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsArrayContainingInOrder<E> extends TypeSafeMatcher<E[]> { + private final Collection<Matcher<? super E>> matchers; + private final IsIterableContainingInOrder<E> iterableMatcher; + + public IsArrayContainingInOrder(List<Matcher<? super E>> matchers) { + this.iterableMatcher = new IsIterableContainingInOrder<E>(matchers); + this.matchers = matchers; + } + + @Override + public boolean matchesSafely(E[] item) { + return iterableMatcher.matches(asList(item)); + } + + @Override + public void describeMismatchSafely(E[] item, Description mismatchDescription) { + iterableMatcher.describeMismatch(asList(item), mismatchDescription); + } + + @Override + public void describeTo(Description description) { + description.appendList("[", ", ", "]", matchers); + } + + /** + * Creates a matcher for arrays that matches when each item in the examined array is + * logically equal to the corresponding item in the specified items. For a positive match, + * the examined array must be of the same length as the number of specified items. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, contains("foo", "bar"))</pre> + * + * @param items + * the items that must equal the items within an examined array + */ + public static <E> Matcher<E[]> arrayContaining(E... items) { + List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>(); + for (E item : items) { + matchers.add(equalTo(item)); + } + return arrayContaining(matchers); + } + + /** + * Creates a matcher for arrays that matches when each item in the examined array satisfies the + * corresponding matcher in the specified matchers. For a positive match, the examined array + * must be of the same length as the number of specified matchers. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, contains(equalTo("foo"), equalTo("bar")))</pre> + * + * @param itemMatchers + * the matchers that must be satisfied by the items in the examined array + */ + public static <E> Matcher<E[]> arrayContaining(Matcher<? super E>... itemMatchers) { + //required for JDK 1.6 + //noinspection RedundantTypeArguments + final List<Matcher<? super E>> nullSafeWithExplicitTypeMatchers = NullSafety.<E>nullSafe(itemMatchers); + + return arrayContaining(nullSafeWithExplicitTypeMatchers); + } + + /** + * Creates a matcher for arrays that matches when each item in the examined array satisfies the + * corresponding matcher in the specified list of matchers. For a positive match, the examined array + * must be of the same length as the specified list of matchers. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, contains(Arrays.asList(equalTo("foo"), equalTo("bar"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by the corresponding item in an examined array + */ + public static <E> Matcher<E[]> arrayContaining(List<Matcher<? super E>> itemMatchers) { + return new IsArrayContainingInOrder<E>(itemMatchers); + } + +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayWithSize.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayWithSize.java new file mode 100644 index 0000000..b3a0b1f --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsArrayWithSize.java @@ -0,0 +1,59 @@ +package org.hamcrest.collection; + +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; + +import static org.hamcrest.core.DescribedAs.describedAs; +import static org.hamcrest.core.IsEqual.equalTo; + +/** + * Matches if array size satisfies a nested matcher. + */ +public class IsArrayWithSize<E> extends FeatureMatcher<E[], Integer> { + public IsArrayWithSize(Matcher<? super Integer> sizeMatcher) { + super(sizeMatcher, "an array with size","array size"); + } + + @Override + protected Integer featureValueOf(E[] actual) { + return actual.length; + } + + /** + * Creates a matcher for arrays that matches when the <code>length</code> of the array + * satisfies the specified matcher. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, arrayWithSize(equalTo(2)))</pre> + * + * @param sizeMatcher + * a matcher for the length of an examined array + */ + public static <E> Matcher<E[]> arrayWithSize(Matcher<? super Integer> sizeMatcher) { + return new IsArrayWithSize<E>(sizeMatcher); + } + + /** + * Creates a matcher for arrays that matches when the <code>length</code> of the array + * equals the specified <code>size</code>. + * For example: + * <pre>assertThat(new String[]{"foo", "bar"}, arrayWithSize(2))</pre> + * + * @param size + * the length that an examined array must have for a positive match + */ + public static <E> Matcher<E[]> arrayWithSize(int size) { + return arrayWithSize(equalTo(size)); + } + + /** + * Creates a matcher for arrays that matches when the <code>length</code> of the array + * is zero. + * For example: + * <pre>assertThat(new String[0], emptyArray())</pre> + * + */ + public static <E> Matcher<E[]> emptyArray() { + Matcher<E[]> isEmpty = arrayWithSize(0); + return describedAs("an empty array", isEmpty); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionContaining.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionContaining.java deleted file mode 100644 index ba98630..0000000 --- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionContaining.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.hamcrest.collection; - -import static org.hamcrest.core.AllOf.allOf; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.TypeSafeMatcher; -import static org.hamcrest.core.IsEqual.equalTo; - -import java.util.Collection; -import java.util.ArrayList; - -public class IsCollectionContaining<T> extends TypeSafeMatcher<Iterable<T>> { - private final Matcher<? extends T> elementMatcher; - - public IsCollectionContaining(Matcher<? extends T> elementMatcher) { - this.elementMatcher = elementMatcher; - } - - public boolean matchesSafely(Iterable<T> collection) { - for (T item : collection) { - if (elementMatcher.matches(item)){ - return true; - } - } - return false; - } - - public void describeTo(Description description) { - description - .appendText("a collection containing ") - .appendDescriptionOf(elementMatcher); - } - - @Factory - public static <T> Matcher<Iterable<T>> hasItem(Matcher<? extends T> elementMatcher) { - return new IsCollectionContaining<T>(elementMatcher); - } - - @Factory - public static <T> Matcher<Iterable<T>> hasItem(T element) { - return hasItem(equalTo(element)); - } - - @Factory - public static <T> Matcher<Iterable<T>> hasItems(Matcher<? extends T>... elementMatchers) { - Collection<Matcher<? extends Iterable<T>>> all - = new ArrayList<Matcher<? extends Iterable<T>>>(elementMatchers.length); - for (Matcher<? extends T> elementMatcher : elementMatchers) { - all.add(hasItem(elementMatcher)); - } - return allOf(all); - } - - @Factory - public static <T> Matcher<Iterable<T>> hasItems(T... elements) { - Collection<Matcher<? extends Iterable<T>>> all - = new ArrayList<Matcher<? extends Iterable<T>>>(elements.length); - for (T element : elements) { - all.add(hasItem(element)); - } - return allOf(all); - } - -} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionWithSize.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionWithSize.java new file mode 100644 index 0000000..f12f57c --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsCollectionWithSize.java @@ -0,0 +1,50 @@ +package org.hamcrest.collection; + +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; + +import java.util.Collection; + +import static org.hamcrest.core.IsEqual.equalTo; + +/** + * Matches if collection size satisfies a nested matcher. + */ +public class IsCollectionWithSize<E> extends FeatureMatcher<Collection<? extends E>, Integer> { + public IsCollectionWithSize(Matcher<? super Integer> sizeMatcher) { + super(sizeMatcher, "a collection with size", "collection size"); + } + + @Override + protected Integer featureValueOf(Collection<? extends E> actual) { + return actual.size(); + } + + /** + * Creates a matcher for {@link java.util.Collection}s that matches when the <code>size()</code> method returns + * a value that satisfies the specified matcher. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasSize(equalTo(2)))</pre> + * + * @param sizeMatcher + * a matcher for the size of an examined {@link java.util.Collection} + */ + public static <E> Matcher<Collection<? extends E>> hasSize(Matcher<? super Integer> sizeMatcher) { + return new IsCollectionWithSize<E>(sizeMatcher); + } + + /** + * Creates a matcher for {@link java.util.Collection}s that matches when the <code>size()</code> method returns + * a value equal to the specified <code>size</code>. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), hasSize(2))</pre> + * + * @param size + * the expected size of an examined {@link java.util.Collection} + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static <E> Matcher<Collection<? extends E>> hasSize(int size) { + return (Matcher)IsCollectionWithSize.hasSize(equalTo(size)); + } + +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyCollection.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyCollection.java new file mode 100644 index 0000000..481b08c --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyCollection.java @@ -0,0 +1,53 @@ +package org.hamcrest.collection; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.Collection; + +/** + * Tests if collection is empty. + */ +public class IsEmptyCollection<E> extends TypeSafeMatcher<Collection<? extends E>> { + + @Override + public boolean matchesSafely(Collection<? extends E> item) { + return item.isEmpty(); + } + + @Override + public void describeMismatchSafely(Collection<? extends E> item, Description mismatchDescription) { + mismatchDescription.appendValue(item); + } + + @Override + public void describeTo(Description description) { + description.appendText("an empty collection"); + } + + /** + * Creates a matcher for {@link java.util.Collection}s matching examined collections whose <code>isEmpty</code> + * method returns <code>true</code>. + * For example: + * <pre>assertThat(new ArrayList<String>(), is(empty()))</pre> + * + */ + public static <E> Matcher<Collection<? extends E>> empty() { + return new IsEmptyCollection<E>(); + } + + /** + * Creates a matcher for {@link java.util.Collection}s matching examined collections whose <code>isEmpty</code> + * method returns <code>true</code>. + * For example: + * <pre>assertThat(new ArrayList<String>(), is(emptyCollectionOf(String.class)))</pre> + * + * @param unusedToForceReturnType + * the type of the collection's content + */ + @SuppressWarnings({"unchecked", "UnusedParameters"}) + public static <E> Matcher<Collection<E>> emptyCollectionOf(Class<E> unusedToForceReturnType) { + return (Matcher)empty(); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyIterable.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyIterable.java new file mode 100644 index 0000000..047e670 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsEmptyIterable.java @@ -0,0 +1,48 @@ +package org.hamcrest.collection; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +/** + * Tests if collection is empty. + */ +public class IsEmptyIterable<E> extends TypeSafeMatcher<Iterable<? extends E>> { + + @Override + public boolean matchesSafely(Iterable<? extends E> iterable) { + return !iterable.iterator().hasNext(); + } + @Override + public void describeMismatchSafely(Iterable<? extends E> iter, Description mismatchDescription) { + mismatchDescription.appendValueList("[", ",", "]", iter); + } + + @Override + public void describeTo(Description description) { + description.appendText("an empty iterable"); + } + + /** + * Creates a matcher for {@link Iterable}s matching examined iterables that yield no items. + * For example: + * <pre>assertThat(new ArrayList<String>(), is(emptyIterable()))</pre> + * + */ + public static <E> Matcher<Iterable<? extends E>> emptyIterable() { + return new IsEmptyIterable<E>(); + } + + /** + * Creates a matcher for {@link Iterable}s matching examined iterables that yield no items. + * For example: + * <pre>assertThat(new ArrayList<String>(), is(emptyIterableOf(String.class)))</pre> + * + * @param unusedToForceReturnType + * the type of the iterable's content + */ + @SuppressWarnings({"unchecked", "UnusedParameters"}) + public static <E> Matcher<Iterable<E>> emptyIterableOf(Class<E> unusedToForceReturnType) { + return (Matcher)emptyIterable(); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIn.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIn.java index 0a7bbb5..f030cab 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIn.java +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIn.java @@ -1,13 +1,12 @@ package org.hamcrest.collection; -import java.util.Arrays; -import java.util.Collection; - import org.hamcrest.BaseMatcher; import org.hamcrest.Description; -import org.hamcrest.Factory; import org.hamcrest.Matcher; +import java.util.Arrays; +import java.util.Collection; + public class IsIn<T> extends BaseMatcher<T> { private final Collection<T> collection; @@ -19,27 +18,108 @@ public class IsIn<T> extends BaseMatcher<T> { collection = Arrays.asList(elements); } + @SuppressWarnings("SuspiciousMethodCalls") + @Override public boolean matches(Object o) { return collection.contains(o); } + @Override public void describeTo(Description buffer) { buffer.appendText("one of "); buffer.appendValueList("{", ", ", "}", collection); } - @Factory + /** + * Creates a matcher that matches when the examined object is found within the + * specified collection. + * For example: + * <pre>assertThat("foo", isIn(Arrays.asList("bar", "foo")))</pre> + * + * @deprecated use is(in(...)) instead + * + * @param collection + * the collection in which matching items must be found + * + */ + @Deprecated public static <T> Matcher<T> isIn(Collection<T> collection) { - return new IsIn<T>(collection); + return in(collection); } - @Factory + /** + * Creates a matcher that matches when the examined object is found within the + * specified collection. + * For example: + * <pre>assertThat("foo", is(in(Arrays.asList("bar", "foo"))))</pre> + * + * @param collection + * the collection in which matching items must be found + * + */ + public static <T> Matcher<T> in(Collection<T> collection) { + return new IsIn<T>(collection); + } + + /** + * Creates a matcher that matches when the examined object is found within the + * specified array. + * For example: + * <pre>assertThat("foo", isIn(new String[]{"bar", "foo"}))</pre> + * + * @deprecated use is(in(...)) instead + * + * @param elements + * the array in which matching items must be found + * + */ + @Deprecated public static <T> Matcher<T> isIn(T[] elements) { + return in(elements); + } + + /** + * Creates a matcher that matches when the examined object is found within the + * specified array. + * For example: + * <pre>assertThat("foo", is(in(new String[]{"bar", "foo"})))</pre> + * + * @param elements + * the array in which matching items must be found + * + */ + public static <T> Matcher<T> in(T[] elements) { return new IsIn<T>(elements); } - @Factory + /** + * Creates a matcher that matches when the examined object is equal to one of the + * specified elements. + * For example: + * <pre>assertThat("foo", isOneOf("bar", "foo"))</pre> + * + * @deprecated use is(oneOf(...)) instead + * + * @param elements + * the elements amongst which matching items will be found + * + */ + @Deprecated public static <T> Matcher<T> isOneOf(T... elements) { - return isIn(elements); + return oneOf(elements); + } + + /** + * Creates a matcher that matches when the examined object is equal to one of the + * specified elements. + * For example: + * <pre>assertThat("foo", is(oneOf("bar", "foo")))</pre> + * + * @param elements + * the elements amongst which matching items will be found + * + */ + public static <T> Matcher<T> oneOf(T... elements) { + return in(elements); } } diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInAnyOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInAnyOrder.java new file mode 100644 index 0000000..6f2fc47 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInAnyOrder.java @@ -0,0 +1,154 @@ +package org.hamcrest.collection; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsIterableContainingInAnyOrder<T> extends TypeSafeDiagnosingMatcher<Iterable<? extends T>> { + private final Collection<Matcher<? super T>> matchers; + + public IsIterableContainingInAnyOrder(Collection<Matcher<? super T>> matchers) { + this.matchers = matchers; + } + + @Override + protected boolean matchesSafely(Iterable<? extends T> items, Description mismatchDescription) { + final Matching<T> matching = new Matching<T>(matchers, mismatchDescription); + for (T item : items) { + if (! matching.matches(item)) { + return false; + } + } + + return matching.isFinished(items); + } + + @Override + public void describeTo(Description description) { + description.appendText("iterable with items ") + .appendList("[", ", ", "]", matchers) + .appendText(" in any order"); + } + + private static class Matching<S> { + private final Collection<Matcher<? super S>> matchers; + private final Description mismatchDescription; + + public Matching(Collection<Matcher<? super S>> matchers, Description mismatchDescription) { + this.matchers = new ArrayList<Matcher<? super S>>(matchers); + this.mismatchDescription = mismatchDescription; + } + + public boolean matches(S item) { + if (matchers.isEmpty()) { + mismatchDescription.appendText("no match for: ").appendValue(item); + return false; + } + return isMatched(item); + } + + public boolean isFinished(Iterable<? extends S> items) { + if (matchers.isEmpty()) { + return true; + } + mismatchDescription + .appendText("no item matches: ").appendList("", ", ", "", matchers) + .appendText(" in ").appendValueList("[", ", ", "]", items); + return false; + } + + private boolean isMatched(S item) { + for (Matcher<? super S> matcher : matchers) { + if (matcher.matches(item)) { + matchers.remove(matcher); + return true; + } + } + mismatchDescription.appendText("not matched: ").appendValue(item); + return false; + } + } + + /** + * <p> + * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over + * the examined {@link Iterable} yields a series of items, each satisfying one matcher anywhere + * in the specified matchers. For a positive match, the examined iterable must be of the same + * length as the number of specified matchers. + * </p> + * <p> + * N.B. each of the specified matchers will only be used once during a given examination, so be + * careful when specifying matchers that may be satisfied by more than one entry in an examined + * iterable. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder(equalTo("bar"), equalTo("foo")))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by an item provided by an examined {@link Iterable} + */ + public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(Matcher<? super T>... itemMatchers) { + return containsInAnyOrder((List) Arrays.asList(itemMatchers)); + } + + /** + * <p> + * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over + * the examined {@link Iterable} yields a series of items, each logically equal to one item + * anywhere in the specified items. For a positive match, the examined iterable + * must be of the same length as the number of specified items. + * </p> + * <p> + * N.B. each of the specified items will only be used once during a given examination, so be + * careful when specifying items that may be equal to more than one entry in an examined + * iterable. + * </p> + * <p> + * For example: + * </p> + * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder("bar", "foo"))</pre> + * + * @param items + * the items that must equal the items provided by an examined {@link Iterable} in any order + */ + public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(T... items) { + List<Matcher<? super T>> matchers = new ArrayList<Matcher<? super T>>(); + for (T item : items) { + matchers.add(equalTo(item)); + } + + return new IsIterableContainingInAnyOrder<T>(matchers); + } + + /** + * <p> + * Creates an order agnostic matcher for {@link Iterable}s that matches when a single pass over + * the examined {@link Iterable} yields a series of items, each satisfying one matcher anywhere + * in the specified collection of matchers. For a positive match, the examined iterable + * must be of the same length as the specified collection of matchers. + * </p> + * <p> + * N.B. each matcher in the specified collection will only be used once during a given + * examination, so be careful when specifying matchers that may be satisfied by more than + * one entry in an examined iterable. + * </p> + * <p>For example:</p> + * <pre>assertThat(Arrays.asList("foo", "bar"), containsInAnyOrder(Arrays.asList(equalTo("bar"), equalTo("foo"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by an item provided by an examined {@link Iterable} + */ + public static <T> Matcher<Iterable<? extends T>> containsInAnyOrder(Collection<Matcher<? super T>> itemMatchers) { + return new IsIterableContainingInAnyOrder<T>(itemMatchers); + } +} + diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInOrder.java new file mode 100644 index 0000000..6309566 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInOrder.java @@ -0,0 +1,153 @@ +package org.hamcrest.collection; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; +import org.hamcrest.internal.NullSafety; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsIterableContainingInOrder<E> extends TypeSafeDiagnosingMatcher<Iterable<? extends E>> { + private final List<Matcher<? super E>> matchers; + + public IsIterableContainingInOrder(List<Matcher<? super E>> matchers) { + this.matchers = matchers; + } + + @Override + protected boolean matchesSafely(Iterable<? extends E> iterable, Description mismatchDescription) { + final MatchSeries<E> matchSeries = new MatchSeries<E>(matchers, mismatchDescription); + for (E item : iterable) { + if (!matchSeries.matches(item)) { + return false; + } + } + + return matchSeries.isFinished(); + } + + @Override + public void describeTo(Description description) { + description.appendText("iterable containing ").appendList("[", ", ", "]", matchers); + } + + private static class MatchSeries<F> { + private final List<Matcher<? super F>> matchers; + private final Description mismatchDescription; + private int nextMatchIx = 0; + + public MatchSeries(List<Matcher<? super F>> matchers, Description mismatchDescription) { + this.mismatchDescription = mismatchDescription; + if (matchers.isEmpty()) { + throw new IllegalArgumentException("Should specify at least one expected element"); + } + this.matchers = matchers; + } + + public boolean matches(F item) { + if (matchers.size() <= nextMatchIx) { + mismatchDescription.appendText("not matched: ").appendValue(item); + return false; + } + + return isMatched(item); + } + + public boolean isFinished() { + if (nextMatchIx < matchers.size()) { + mismatchDescription.appendText("no item was ").appendDescriptionOf(matchers.get(nextMatchIx)); + return false; + } + return true; + } + + private boolean isMatched(F item) { + final Matcher<? super F> matcher = matchers.get(nextMatchIx); + if (!matcher.matches(item)) { + describeMismatch(matcher, item); + return false; + } + nextMatchIx++; + return true; + } + + private void describeMismatch(Matcher<? super F> matcher, F item) { + mismatchDescription.appendText("item " + nextMatchIx + ": "); + matcher.describeMismatch(item, mismatchDescription); + } + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, each logically equal to the + * corresponding item in the specified items. For a positive match, the examined iterable + * must be of the same length as the number of specified items. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), contains("foo", "bar"))</pre> + * + * @param items + * the items that must equal the items provided by an examined {@link Iterable} + */ + public static <E> Matcher<Iterable<? extends E>> contains(E... items) { + List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>(); + for (E item : items) { + matchers.add(equalTo(item)); + } + + return contains(matchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a single item that satisfies the specified matcher. + * For a positive match, the examined iterable must only yield one item. + * For example: + * <pre>assertThat(Arrays.asList("foo"), contains(equalTo("foo")))</pre> + * + * @param itemMatcher + * the matcher that must be satisfied by the single item provided by an + * examined {@link Iterable} + */ + @SuppressWarnings("unchecked") + public static <E> Matcher<Iterable<? extends E>> contains(final Matcher<? super E> itemMatcher) { + return contains(new ArrayList<Matcher<? super E>>(asList(itemMatcher))); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, each satisfying the corresponding + * matcher in the specified matchers. For a positive match, the examined iterable + * must be of the same length as the number of specified matchers. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), contains(equalTo("foo"), equalTo("bar")))</pre> + * + * @param itemMatchers + * the matchers that must be satisfied by the items provided by an examined {@link Iterable} + */ + public static <E> Matcher<Iterable<? extends E>> contains(Matcher<? super E>... itemMatchers) { + // required for JDK 1.6 + //noinspection RedundantTypeArguments + final List<Matcher<? super E>> nullSafeWithExplicitTypeMatchers = NullSafety.<E>nullSafe(itemMatchers); + return contains(nullSafeWithExplicitTypeMatchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, each satisfying the corresponding + * matcher in the specified list of matchers. For a positive match, the examined iterable + * must be of the same length as the specified list of matchers. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), contains(Arrays.asList(equalTo("foo"), equalTo("bar"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by the corresponding item provided by + * an examined {@link Iterable} + */ + public static <E> Matcher<Iterable<? extends E>> contains(List<Matcher<? super E>> itemMatchers) { + return new IsIterableContainingInOrder<E>(itemMatchers); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInRelativeOrder.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInRelativeOrder.java new file mode 100644 index 0000000..f669835 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableContainingInRelativeOrder.java @@ -0,0 +1,117 @@ +package org.hamcrest.collection; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsIterableContainingInRelativeOrder<E> extends TypeSafeDiagnosingMatcher<Iterable<? extends E>> { + private final List<Matcher<? super E>> matchers; + + public IsIterableContainingInRelativeOrder(List<Matcher<? super E>> matchers) { + this.matchers = matchers; + } + + @Override + protected boolean matchesSafely(Iterable<? extends E> iterable, Description mismatchDescription) { + MatchSeriesInRelativeOrder<E> matchSeriesInRelativeOrder = new MatchSeriesInRelativeOrder<E>(matchers, mismatchDescription); + matchSeriesInRelativeOrder.processItems(iterable); + return matchSeriesInRelativeOrder.isFinished(); + } + + public void describeTo(Description description) { + description.appendText("iterable containing ").appendList("[", ", ", "]", matchers).appendText(" in relative order"); + } + + private static class MatchSeriesInRelativeOrder<F> { + public final List<Matcher<? super F>> matchers; + private final Description mismatchDescription; + private int nextMatchIx = 0; + private F lastMatchedItem = null; + + public MatchSeriesInRelativeOrder(List<Matcher<? super F>> matchers, Description mismatchDescription) { + this.mismatchDescription = mismatchDescription; + if (matchers.isEmpty()) { + throw new IllegalArgumentException("Should specify at least one expected element"); + } + this.matchers = matchers; + } + + public void processItems(Iterable<? extends F> iterable) { + for (F item : iterable) { + if (nextMatchIx < matchers.size()) { + Matcher<? super F> matcher = matchers.get(nextMatchIx); + if (matcher.matches(item)) { + lastMatchedItem = item; + nextMatchIx++; + } + } + } + } + + public boolean isFinished() { + if (nextMatchIx < matchers.size()) { + mismatchDescription.appendDescriptionOf(matchers.get(nextMatchIx)).appendText(" was not found"); + if (lastMatchedItem != null) { + mismatchDescription.appendText(" after ").appendValue(lastMatchedItem); + } + return false; + } + return true; + } + + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, that contains items logically equal to the + * corresponding item in the specified items, in the same relative order + * For example: + * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder("b", "d"))</pre> + * + * @param items + * the items that must be contained within items provided by an examined {@link Iterable} in the same relative order + */ + public static <E> Matcher<Iterable<? extends E>> containsInRelativeOrder(E... items) { + List<Matcher<? super E>> matchers = new ArrayList<Matcher<? super E>>(); + for (E item : items) { + matchers.add(equalTo(item)); + } + + return containsInRelativeOrder(matchers); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, that each satisfying the corresponding + * matcher in the specified matchers, in the same relative order. + * For example: + * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), containsInRelativeOrder(equalTo("b"), equalTo("d")))</pre> + * + * @param itemMatchers + * the matchers that must be satisfied by the items provided by an examined {@link Iterable} in the same relative order + */ + public static <E> Matcher<Iterable<? extends E>> containsInRelativeOrder(Matcher<? super E>... itemMatchers) { + return containsInRelativeOrder((List) asList(itemMatchers)); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields a series of items, that contains items satisfying the corresponding + * matcher in the specified list of matchers, in the same relative order. + * For example: + * <pre>assertThat(Arrays.asList("a", "b", "c", "d", "e"), contains(Arrays.asList(equalTo("b"), equalTo("d"))))</pre> + * + * @param itemMatchers + * a list of matchers, each of which must be satisfied by the items provided by + * an examined {@link Iterable} in the same relative order + */ + public static <E> Matcher<Iterable<? extends E>> containsInRelativeOrder(List<Matcher<? super E>> itemMatchers) { + return new IsIterableContainingInRelativeOrder<E>(itemMatchers); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableWithSize.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableWithSize.java new file mode 100644 index 0000000..0a1535f --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsIterableWithSize.java @@ -0,0 +1,53 @@ +package org.hamcrest.collection; + +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; + +import java.util.Iterator; + +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsIterableWithSize<E> extends FeatureMatcher<Iterable<E>, Integer> { + + public IsIterableWithSize(Matcher<? super Integer> sizeMatcher) { + super(sizeMatcher, "an iterable with size", "iterable size"); + } + + + @Override + protected Integer featureValueOf(Iterable<E> actual) { + int size = 0; + for (Iterator<E> iterator = actual.iterator(); iterator.hasNext(); iterator.next()) { + size++; + } + return size; + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields an item count that satisfies the specified + * matcher. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), iterableWithSize(equalTo(2)))</pre> + * + * @param sizeMatcher + * a matcher for the number of items that should be yielded by an examined {@link Iterable} + */ + public static <E> Matcher<Iterable<E>> iterableWithSize(Matcher<? super Integer> sizeMatcher) { + return new IsIterableWithSize<E>(sizeMatcher); + } + + /** + * Creates a matcher for {@link Iterable}s that matches when a single pass over the + * examined {@link Iterable} yields an item count that is equal to the specified + * <code>size</code> argument. + * For example: + * <pre>assertThat(Arrays.asList("foo", "bar"), iterableWithSize(2))</pre> + * + * @param size + * the number of items that should be yielded by an examined {@link Iterable} + */ + public static <E> Matcher<Iterable<E>> iterableWithSize(int size) { + return iterableWithSize(equalTo(size)); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapContaining.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapContaining.java index 74572dd..c29801e 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapContaining.java +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapContaining.java @@ -1,28 +1,27 @@ package org.hamcrest.collection; import org.hamcrest.Description; -import org.hamcrest.Factory; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; -import org.hamcrest.core.IsAnything; - -import static org.hamcrest.core.IsEqual.equalTo; import java.util.Map; import java.util.Map.Entry; -public class IsMapContaining<K,V> extends TypeSafeMatcher<Map<K, V>> { +import static org.hamcrest.core.IsAnything.anything; +import static org.hamcrest.core.IsEqual.equalTo; - private final Matcher<K> keyMatcher; - private final Matcher<V> valueMatcher; +public class IsMapContaining<K,V> extends TypeSafeMatcher<Map<? extends K, ? extends V>> { + private final Matcher<? super K> keyMatcher; + private final Matcher<? super V> valueMatcher; - public IsMapContaining(Matcher<K> keyMatcher, Matcher<V> valueMatcher) { + public IsMapContaining(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher) { this.keyMatcher = keyMatcher; this.valueMatcher = valueMatcher; } - public boolean matchesSafely(Map<K, V> map) { - for (Entry<K, V> entry : map.entrySet()) { + @Override + public boolean matchesSafely(Map<? extends K, ? extends V> map) { + for (Entry<? extends K, ? extends V> entry : map.entrySet()) { if (keyMatcher.matches(entry.getKey()) && valueMatcher.matches(entry.getValue())) { return true; } @@ -30,41 +29,101 @@ public class IsMapContaining<K,V> extends TypeSafeMatcher<Map<K, V>> { return false; } + @Override + public void describeMismatchSafely(Map<? extends K, ? extends V> map, Description mismatchDescription) { + mismatchDescription.appendText("map was ").appendValueList("[", ", ", "]", map.entrySet()); + } + + @Override public void describeTo(Description description) { description.appendText("map containing [") .appendDescriptionOf(keyMatcher) .appendText("->") - .appendDescriptionOf(valueMatcher) - .appendText("]"); + .appendDescriptionOf(valueMatcher) + .appendText("]"); } - @Factory - public static <K,V> Matcher<Map<K,V>> hasEntry(Matcher<K> keyMatcher, Matcher<V> valueMatcher) { + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one entry whose key satisfies the specified <code>keyMatcher</code> <b>and</b> whose + * value satisfies the specified <code>valueMatcher</code>. + * For example: + * <pre>assertThat(myMap, hasEntry(equalTo("bar"), equalTo("foo")))</pre> + * + * @param keyMatcher + * the key matcher that, in combination with the valueMatcher, must be satisfied by at least one entry + * @param valueMatcher + * the value matcher that, in combination with the keyMatcher, must be satisfied by at least one entry + */ + public static <K,V> Matcher<Map<? extends K,? extends V>> hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher) { return new IsMapContaining<K,V>(keyMatcher, valueMatcher); } - @Factory - public static <K,V> Matcher<Map<K,V>> hasEntry(K key, V value) { - return hasEntry(equalTo(key), equalTo(value)); + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one entry whose key equals the specified <code>key</code> <b>and</b> whose value equals the + * specified <code>value</code>. + * For example: + * <pre>assertThat(myMap, hasEntry("bar", "foo"))</pre> + * + * @param key + * the key that, in combination with the value, must be describe at least one entry + * @param value + * the value that, in combination with the key, must be describe at least one entry + */ + public static <K,V> Matcher<Map<? extends K,? extends V>> hasEntry(K key, V value) { + return new IsMapContaining<K,V>(equalTo(key), equalTo(value)); } - - @Factory - public static <K,V> Matcher<Map<K,V>> hasKey(Matcher<K> keyMatcher) { - return hasEntry(keyMatcher, IsAnything.<V>anything()); + + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one key that satisfies the specified matcher. + * For example: + * <pre>assertThat(myMap, hasKey(equalTo("bar")))</pre> + * + * @param keyMatcher + * the matcher that must be satisfied by at least one key + */ + public static <K> Matcher<Map<? extends K, ?>> hasKey(Matcher<? super K> keyMatcher) { + return new IsMapContaining<K,Object>(keyMatcher, anything()); } - @Factory - public static <K,V> Matcher<Map<K,V>> hasKey(K key) { - return hasKey(equalTo(key)); + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one key that is equal to the specified key. + * For example: + * <pre>assertThat(myMap, hasKey("bar"))</pre> + * + * @param key + * the key that satisfying maps must contain + */ + public static <K> Matcher<Map<? extends K, ?>> hasKey(K key) { + return new IsMapContaining<K,Object>(equalTo(key), anything()); } - @Factory - public static <K,V> Matcher<Map<K,V>> hasValue(Matcher<V> valueMatcher) { - return hasEntry(IsAnything.<K>anything(), valueMatcher); + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one value that satisfies the specified valueMatcher. + * For example: + * <pre>assertThat(myMap, hasValue(equalTo("foo")))</pre> + * + * @param valueMatcher + * the matcher that must be satisfied by at least one value + */ + public static <V> Matcher<Map<?, ? extends V>> hasValue(Matcher<? super V> valueMatcher) { + return new IsMapContaining<Object,V>(anything(), valueMatcher); } - @Factory - public static <K,V> Matcher<Map<K,V>> hasValue(V value) { - return hasValue(equalTo(value)); + /** + * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains + * at least one value that is equal to the specified value. + * For example: + * <pre>assertThat(myMap, hasValue("foo"))</pre> + * + * @param value + * the value that satisfying maps must contain + */ + public static <V> Matcher<Map<?, ? extends V>> hasValue(V value) { + return new IsMapContaining<Object,V>(anything(), equalTo(value)); } } diff --git a/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapWithSize.java b/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapWithSize.java new file mode 100644 index 0000000..0132390 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/collection/IsMapWithSize.java @@ -0,0 +1,60 @@ +package org.hamcrest.collection; + +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; + +import java.util.Map; + +import static org.hamcrest.core.IsEqual.equalTo; + +/** + * Matches if map size satisfies a nested matcher. + */ +public final class IsMapWithSize<K, V> extends FeatureMatcher<Map<? extends K, ? extends V>, Integer> { + public IsMapWithSize(Matcher<? super Integer> sizeMatcher) { + super(sizeMatcher, "a map with size", "map size"); + } + + @Override + protected Integer featureValueOf(Map<? extends K, ? extends V> actual) { + return actual.size(); + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns + * a value that satisfies the specified matcher. + * For example: + * <pre>assertThat(myMap, is(aMapWithSize(equalTo(2))))</pre> + * + * @param sizeMatcher + * a matcher for the size of an examined {@link java.util.Map} + */ + public static <K, V> Matcher<Map<? extends K, ? extends V>> aMapWithSize(Matcher<? super Integer> sizeMatcher) { + return new IsMapWithSize<K, V>(sizeMatcher); + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns + * a value equal to the specified <code>size</code>. + * For example: + * <pre>assertThat(myMap, is(aMapWithSize(2)))</pre> + * + * @param size + * the expected size of an examined {@link java.util.Map} + */ + public static <K, V> Matcher<Map<? extends K, ? extends V>> aMapWithSize(int size) { + Matcher<? super Integer> matcher = equalTo(size); + return IsMapWithSize.aMapWithSize(matcher); + } + + /** + * Creates a matcher for {@link java.util.Map}s that matches when the <code>size()</code> method returns + * zero. + * For example: + * <pre>assertThat(myMap, is(anEmptyMap()))</pre> + * + */ + public static <K, V> Matcher<Map<? extends K, ? extends V>> anEmptyMap() { + return IsMapWithSize.aMapWithSize(equalTo(0)); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/comparator/ComparatorMatcherBuilder.java b/hamcrest-library/src/main/java/org/hamcrest/comparator/ComparatorMatcherBuilder.java new file mode 100644 index 0000000..cf52211 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/comparator/ComparatorMatcherBuilder.java @@ -0,0 +1,178 @@ +package org.hamcrest.comparator; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.Comparator; + +import static java.lang.Integer.signum; + +public final class ComparatorMatcherBuilder<T> { + + private final Comparator<T> comparator; + private final boolean includeComparatorInDescription; + + /** + * Creates a matcher factory for matchers of {@code Comparable}s. + * For example: + * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThanOrEqualTo(1))</pre> + */ + public static <T extends Comparable<T>> ComparatorMatcherBuilder<T> usingNaturalOrdering() { + return new ComparatorMatcherBuilder<T>(new Comparator<T>() { + @Override + public int compare(T o1, T o2) { + return o1.compareTo(o2); + } + }, false); + } + + /** + * Creates a matcher factory for matchers of {@code Comparators}s of {@code T}. + * For example: + * <pre>assertThat(5, comparedBy(new Comparator<Integer>() { + * public int compare(Integer o1, Integer o2) { + * return -o1.compareTo(o2); + * } + * }).lessThan(4))</pre> + */ + public static <T> ComparatorMatcherBuilder<T> comparedBy(Comparator<T> comparator) { + return new ComparatorMatcherBuilder<T>(comparator, true); + } + + private ComparatorMatcherBuilder(Comparator<T> comparator, boolean includeComparatorInDescription) { + this.comparator = comparator; + this.includeComparatorInDescription = includeComparatorInDescription; + } + + private static final class ComparatorMatcher<T> extends TypeSafeMatcher<T> { + private static final int LESS_THAN = -1; + private static final int GREATER_THAN = 1; + private static final int EQUAL = 0; + + private final Comparator<T> comparator; + private final T expected; + private final int minCompare; + private final int maxCompare; + private final boolean includeComparatorInDescription; + + private static final String[] comparisonDescriptions = { + "less than", + "equal to", + "greater than" + }; + + private ComparatorMatcher(Comparator<T> comparator, T expected, int minCompare, int maxCompare, boolean includeComparatorInDescription) { + this.comparator = comparator; + this.expected = expected; + this.minCompare = minCompare; + this.maxCompare = maxCompare; + this.includeComparatorInDescription = includeComparatorInDescription; + } + + @Override + public boolean matchesSafely(T actual) { + try { + int compare = signum(comparator.compare(actual, expected)); + return minCompare <= compare && compare <= maxCompare; + } catch (ClassCastException e) { + return false; // type erasure means someone can shonk in a non-T :( + } + } + + @Override + public void describeMismatchSafely(T actual, Description mismatchDescription) { + mismatchDescription.appendValue(actual).appendText(" was ") + .appendText(asText(comparator.compare(actual, expected))) + .appendText(" ").appendValue(expected); + if (includeComparatorInDescription) { + mismatchDescription.appendText(" when compared by ").appendValue(comparator); + } + } + + @Override + public void describeTo(Description description) { + description.appendText("a value ").appendText(asText(minCompare)); + if (minCompare != maxCompare) { + description.appendText(" or ").appendText(asText(maxCompare)); + } + description.appendText(" ").appendValue(expected); + if (includeComparatorInDescription) { + description.appendText(" when compared by ").appendValue(comparator); + } + } + + private static String asText(int comparison) { + return comparisonDescriptions[signum(comparison) + 1]; + } + } + + /** + * Creates a matcher of {@code T} object that matches when the examined object is + * equal to the specified value, as reported by the {@code Comparator} used to + * create this builder. + * For example: + * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().comparesEqualTo(1))</pre> + * + * @param value the value which, when passed to the Comparator supplied to this builder, should return zero + */ + public Matcher<T> comparesEqualTo(T value) { + return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.EQUAL, ComparatorMatcher.EQUAL, includeComparatorInDescription); + } + + /** + * Creates a matcher of {@code T} object that matches when the examined object is + * greater than the specified value, as reported by the {@code Comparator} used to + * create this builder. + * For example: + * <pre>assertThat(2, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().greaterThan(1))</pre> + * + * @param value the value which, when passed to the Comparator supplied to this builder, should return greater + * than zero + */ + public Matcher<T> greaterThan(T value) { + return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.GREATER_THAN, ComparatorMatcher.GREATER_THAN, includeComparatorInDescription); + } + + /** + * Creates a matcher of {@code T} object that matches when the examined object is + * greater than or equal to the specified value, as reported by the {@code Comparator} used to + * create this builder. + * For example: + * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().greaterThanOrEqualTo(1))</pre> + * + * @param value the value which, when passed to the Comparator supplied to this builder, should return greater + * than or equal to zero + */ + public Matcher<T> greaterThanOrEqualTo(T value) { + return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.EQUAL, ComparatorMatcher.GREATER_THAN, includeComparatorInDescription); + } + + /** + * Creates a matcher of {@code T} object that matches when the examined object is + * less than the specified value, as reported by the {@code Comparator} used to + * create this builder. + * For example: + * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThan(2))</pre> + * + * @param value the value which, when passed to the Comparator supplied to this builder, should return less + * than zero + */ + public Matcher<T> lessThan(T value) { + return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.LESS_THAN, ComparatorMatcher.LESS_THAN, includeComparatorInDescription); + } + + /** + * Creates a matcher of {@code T} object that matches when the examined object is + * less than or equal to the specified value, as reported by the {@code Comparator} used to + * create this builder. + * For example: + * <pre>assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThanOrEqualTo(1))</pre> + * + * @param value the value which, when passed to the Comparator supplied to this builder, should return less + * than or equal to zero + */ + public Matcher<T> lessThanOrEqualTo(T value) { + return new ComparatorMatcher<T>(comparator, value, ComparatorMatcher.LESS_THAN, ComparatorMatcher.EQUAL, includeComparatorInDescription); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/io/FileMatchers.java b/hamcrest-library/src/main/java/org/hamcrest/io/FileMatchers.java new file mode 100644 index 0000000..88288b0 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/io/FileMatchers.java @@ -0,0 +1,107 @@ +package org.hamcrest.io; + +import org.hamcrest.Description; +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; + +import java.io.File; +import java.io.IOException; + +import static org.hamcrest.core.IsEqual.equalTo; + +public final class FileMatchers { + + public static Matcher<File> anExistingDirectory() { + return fileChecker(IS_DIRECTORY, "an existing directory", "is not a directory"); + } + + public static Matcher<File> anExistingFileOrDirectory() { + return fileChecker(EXISTS, "an existing file or directory", "does not exist"); + } + + public static Matcher<File> anExistingFile() { + return fileChecker(IS_FILE, "an existing File", "is not a file"); + } + + public static Matcher<File> aReadableFile() { + return fileChecker(CAN_READ, "a readable File", "cannot be read"); + } + + public static Matcher<File> aWritableFile() { + return fileChecker(CAN_WRITE, "a writable File", "cannot be written to"); + } + + public static Matcher<File> aFileWithSize(long size) { + return aFileWithSize(equalTo(size)); + } + + public static Matcher<File> aFileWithSize(final Matcher<Long> expected) { + return new FeatureMatcher<File, Long>(expected, "A file with size", "size") { + @Override protected Long featureValueOf(File actual) { return actual.length(); } + }; + } + + public static Matcher<File> aFileNamed(final Matcher<String> expected) { + return new FeatureMatcher<File, String>(expected, "A file with name", "name") { + @Override protected String featureValueOf(File actual) { return actual.getName(); } + }; + } + + public static Matcher<File> aFileWithCanonicalPath(final Matcher<String> expected) { + return new FeatureMatcher<File, String>(expected, "A file with canonical path", "path") { + @Override protected String featureValueOf(File actual) { + try { + return actual.getCanonicalPath(); + } catch (IOException e) { + return "Exception: " + e.getMessage(); + } + } + }; + } + + public static Matcher<File> aFileWithAbsolutePath(final Matcher<String> expected) { + return new FeatureMatcher<File, String>(expected, "A file with absolute path", "path") { + @Override protected String featureValueOf(File actual) { return actual.getAbsolutePath(); } + }; + } + + public static interface FileStatus { + boolean check(File actual); + } + + public static final FileStatus CAN_WRITE = new FileStatus() { + @Override public boolean check(File actual) { return actual.canWrite(); } + }; + public static final FileStatus CAN_READ = new FileStatus() { + @Override public boolean check(File actual) { return actual.canRead(); } + }; + + public static final FileStatus IS_FILE = new FileStatus() { + @Override public boolean check(File actual) { return actual.isFile(); } + }; + + public static final FileStatus IS_DIRECTORY = new FileStatus() { + @Override public boolean check(File actual) { return actual.isDirectory(); } + }; + + public static final FileStatus EXISTS = new FileStatus() { + @Override public boolean check(File actual) { return actual.exists(); } + }; + + private static Matcher<File> fileChecker(final FileStatus fileStatus, final String successDescription, final String failureDescription) { + return new TypeSafeDiagnosingMatcher<File>() { + public boolean matchesSafely(File actual, Description mismatchDescription) { + final boolean result = fileStatus.check(actual); + if (!result) { + mismatchDescription.appendText(failureDescription); + } + return result; + } + + public void describeTo(Description description) { + description.appendText(successDescription); + } + }; + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/BigDecimalCloseTo.java b/hamcrest-library/src/main/java/org/hamcrest/number/BigDecimalCloseTo.java new file mode 100644 index 0000000..d9cb026 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/number/BigDecimalCloseTo.java @@ -0,0 +1,63 @@ +package org.hamcrest.number; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.math.BigDecimal; +import java.math.MathContext; + +public class BigDecimalCloseTo extends TypeSafeMatcher<BigDecimal> { + + private final BigDecimal delta; + private final BigDecimal value; + + public BigDecimalCloseTo(BigDecimal value, BigDecimal error) { + this.delta = error; + this.value = value; + } + + @Override + public boolean matchesSafely(BigDecimal item) { + return actualDelta(item).compareTo(BigDecimal.ZERO) <= 0; + } + + @Override + public void describeMismatchSafely(BigDecimal item, Description mismatchDescription) { + mismatchDescription.appendValue(item) + .appendText(" differed by ") + .appendValue(actualDelta(item)) + .appendText(" more than delta ") + .appendValue(delta); + } + + @Override + public void describeTo(Description description) { + description.appendText("a numeric value within ") + .appendValue(delta) + .appendText(" of ") + .appendValue(value); + } + + private BigDecimal actualDelta(BigDecimal item) { + return item.subtract(value, MathContext.DECIMAL128).abs().subtract(delta, MathContext.DECIMAL128).stripTrailingZeros(); + } + + /** + * Creates a matcher of {@link java.math.BigDecimal}s that matches when an examined BigDecimal is equal + * to the specified <code>operand</code>, within a range of +/- <code>error</code>. The comparison for equality + * is done by BigDecimals {@link java.math.BigDecimal#compareTo(java.math.BigDecimal)} method. + * For example: + * <pre>assertThat(new BigDecimal("1.03"), is(closeTo(new BigDecimal("1.0"), new BigDecimal("0.03"))))</pre> + * + * @param operand + * the expected value of matching BigDecimals + * @param error + * the delta (+/-) within which matches will be allowed + */ + public static Matcher<BigDecimal> closeTo(BigDecimal operand, BigDecimal error) { + return new BigDecimalCloseTo(operand, error); + } + +} + diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/IsCloseTo.java b/hamcrest-library/src/main/java/org/hamcrest/number/IsCloseTo.java index dc183e8..3b6967d 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/number/IsCloseTo.java +++ b/hamcrest-library/src/main/java/org/hamcrest/number/IsCloseTo.java @@ -1,40 +1,63 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest.number; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; import org.hamcrest.TypeSafeMatcher; +import static java.lang.Math.abs; + /** * Is the value a number equal to a value within some range of * acceptable error? */ public class IsCloseTo extends TypeSafeMatcher<Double> { - private final double error; + private final double delta; private final double value; public IsCloseTo(double value, double error) { - this.error = error; + this.delta = error; this.value = value; } + @Override public boolean matchesSafely(Double item) { - return Math.abs((item - value)) <= error; + return actualDelta(item) <= 0.0; + } + + @Override + public void describeMismatchSafely(Double item, Description mismatchDescription) { + mismatchDescription.appendValue(item) + .appendText(" differed by ") + .appendValue(actualDelta(item)) + .appendText(" more than delta ") + .appendValue(delta); } + @Override public void describeTo(Description description) { description.appendText("a numeric value within ") - .appendValue(error) + .appendValue(delta) .appendText(" of ") .appendValue(value); } - @Factory + private double actualDelta(Double item) { + return abs(item - value) - delta; + } + + /** + * Creates a matcher of {@link Double}s that matches when an examined double is equal + * to the specified <code>operand</code>, within a range of +/- <code>error</code>. + * For example: + * <pre>assertThat(1.03, is(closeTo(1.0, 0.03)))</pre> + * + * @param operand + * the expected value of matching doubles + * @param error + * the delta (+/-) within which matches will be allowed + */ public static Matcher<Double> closeTo(double operand, double error) { return new IsCloseTo(operand, error); } - } diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/IsGreaterThan.java b/hamcrest-library/src/main/java/org/hamcrest/number/IsGreaterThan.java deleted file mode 100644 index 34046b7..0000000 --- a/hamcrest-library/src/main/java/org/hamcrest/number/IsGreaterThan.java +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ -package org.hamcrest.number; - -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; - -/** - * Is the value less than or greater than another {@link java.lang.Comparable} value? - */ -public class IsGreaterThan<T extends Comparable<T>> extends TypeSafeMatcher<T> { - private final Comparable<T> compareTo; - - public IsGreaterThan(Comparable<T> compareTo) { - this.compareTo = compareTo; - } - - public boolean matchesSafely(T item) { - return compareTo.compareTo(item) < 0; - } - - public void describeTo(Description description) { - description.appendText("a value greater than "); - description.appendValue(compareTo); - } -} diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/IsNaN.java b/hamcrest-library/src/main/java/org/hamcrest/number/IsNaN.java new file mode 100644 index 0000000..415a9a2 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/number/IsNaN.java @@ -0,0 +1,38 @@ +package org.hamcrest.number; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + + +/** + * Is the value a number actually not a number (NaN)? + */ +public final class IsNaN extends TypeSafeMatcher<Double> { + + private IsNaN() { } + + @Override + public boolean matchesSafely(Double item) { + return Double.isNaN(item); + } + + @Override + public void describeMismatchSafely(Double item, Description mismatchDescription) { + mismatchDescription.appendText("was ").appendValue(item); + } + + @Override + public void describeTo(Description description) { + description.appendText("a double value of NaN"); + } + + /** + * Creates a matcher of {@link Double}s that matches when an examined double is not a number. + * For example: + * <pre>assertThat(Double.NaN, is(notANumber()))</pre> + */ + public static Matcher<Double> notANumber() { + return new IsNaN(); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparison.java b/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparison.java new file mode 100644 index 0000000..8a77713 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparison.java @@ -0,0 +1,79 @@ +package org.hamcrest.number; + +import org.hamcrest.Matcher; +import org.hamcrest.comparator.ComparatorMatcherBuilder; + +public class OrderingComparison { + + private OrderingComparison() { + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * equal to the specified value, as reported by the <code>compareTo</code> method of the + * <b>examined</b> object. + * For example: + * <pre>assertThat(1, comparesEqualTo(1))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return zero + */ + public static <T extends Comparable<T>> Matcher<T> comparesEqualTo(T value) { + return ComparatorMatcherBuilder.<T>usingNaturalOrdering().comparesEqualTo(value); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * greater than the specified value, as reported by the <code>compareTo</code> method of the + * <b>examined</b> object. + * For example: + * <pre>assertThat(2, greaterThan(1))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return greater + * than zero + */ + public static <T extends Comparable<T>> Matcher<T> greaterThan(T value) { + return ComparatorMatcherBuilder.<T>usingNaturalOrdering().greaterThan(value); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * greater than or equal to the specified value, as reported by the <code>compareTo</code> method + * of the <b>examined</b> object. + * For example: + * <pre>assertThat(1, greaterThanOrEqualTo(1))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return greater + * than or equal to zero + */ + public static <T extends Comparable<T>> Matcher<T> greaterThanOrEqualTo(T value) { + return ComparatorMatcherBuilder.<T>usingNaturalOrdering().greaterThanOrEqualTo(value); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * less than the specified value, as reported by the <code>compareTo</code> method of the + * <b>examined</b> object. + * For example: + * <pre>assertThat(1, lessThan(2))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return less + * than zero + */ + public static <T extends Comparable<T>> Matcher<T> lessThan(T value) { + return ComparatorMatcherBuilder.<T>usingNaturalOrdering().lessThan(value); + } + + /** + * Creates a matcher of {@link Comparable} object that matches when the examined object is + * less than or equal to the specified value, as reported by the <code>compareTo</code> method + * of the <b>examined</b> object. + * For example: + * <pre>assertThat(1, lessThanOrEqualTo(1))</pre> + * + * @param value the value which, when passed to the compareTo method of the examined object, should return less + * than or equal to zero + */ + public static <T extends Comparable<T>> Matcher<T> lessThanOrEqualTo(T value) { + return ComparatorMatcherBuilder.<T>usingNaturalOrdering().lessThanOrEqualTo(value); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparisons.java b/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparisons.java deleted file mode 100644 index 1791a40..0000000 --- a/hamcrest-library/src/main/java/org/hamcrest/number/OrderingComparisons.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.hamcrest.number; - -import static org.hamcrest.core.AnyOf.anyOf; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.hamcrest.core.IsNot.not; -import static org.hamcrest.core.DescribedAs.describedAs; - -import org.hamcrest.Factory; -import org.hamcrest.Matcher; - -@SuppressWarnings("unchecked") -public class OrderingComparisons { - @Factory - public static <T extends Comparable<T>> Matcher<T> greaterThan(T value) { - return new IsGreaterThan<T>(value); - } - - @Factory - public static <T extends Comparable<T>> Matcher<T> greaterThanOrEqualTo(T value) { - return describedAs("a value greater than or equal to %0", - anyOf(greaterThan(value), equalTo(value)), - value); - } - - @Factory - public static <T extends Comparable<T>> Matcher<T> lessThan(T value) { - return describedAs("a value less than %0", - not(greaterThanOrEqualTo(value)), - value); - } - - @Factory - public static <T extends Comparable<T>> Matcher<T> lessThanOrEqualTo(T value) { - return describedAs("a value less than or equal to %0", - not(greaterThan(value)), - value); - } -} diff --git a/hamcrest-library/src/main/java/org/hamcrest/object/HasToString.java b/hamcrest-library/src/main/java/org/hamcrest/object/HasToString.java index 0f12ffd..2dab9de 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/object/HasToString.java +++ b/hamcrest-library/src/main/java/org/hamcrest/object/HasToString.java @@ -1,31 +1,43 @@ package org.hamcrest.object; -import org.hamcrest.Description; +import org.hamcrest.FeatureMatcher; import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.BaseMatcher; -public class HasToString<T> extends BaseMatcher<T> { +import static org.hamcrest.core.IsEqual.equalTo; - private final Matcher<String> toStringMatcher; - - public HasToString(Matcher<String> toStringMatcher) { - this.toStringMatcher = toStringMatcher; +public class HasToString<T> extends FeatureMatcher<T, String> { + public HasToString(Matcher<? super String> toStringMatcher) { + super(toStringMatcher, "with toString()", "toString()"); } - - public boolean matches(Object item) { - return item != null && toStringMatcher.matches(item.toString()); + + @Override + protected String featureValueOf(T actual) { + return String.valueOf(actual); } - public void describeTo(Description description) { - description - .appendText("asString(") - .appendDescriptionOf(toStringMatcher) - .appendText(")"); - } - - @Factory - public static <T> Matcher<T> hasToString(Matcher<String> toStringMatcher) { + /** + * Creates a matcher that matches any examined object whose <code>toString</code> method + * returns a value that satisfies the specified matcher. + * For example: + * <pre>assertThat(true, hasToString(equalTo("TRUE")))</pre> + * + * @param toStringMatcher + * the matcher used to verify the toString result + */ + public static <T> Matcher<T> hasToString(Matcher<? super String> toStringMatcher) { return new HasToString<T>(toStringMatcher); } + + /** + * Creates a matcher that matches any examined object whose <code>toString</code> method + * returns a value equalTo the specified string. + * For example: + * <pre>assertThat(true, hasToString("TRUE"))</pre> + * + * @param expectedToString + * the expected toString result + */ + public static <T> Matcher<T> hasToString(String expectedToString) { + return new HasToString<T>(equalTo(expectedToString)); + } } diff --git a/hamcrest-library/src/main/java/org/hamcrest/object/IsCompatibleType.java b/hamcrest-library/src/main/java/org/hamcrest/object/IsCompatibleType.java index 3a2dc7a..e1410a4 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/object/IsCompatibleType.java +++ b/hamcrest-library/src/main/java/org/hamcrest/object/IsCompatibleType.java @@ -2,7 +2,6 @@ package org.hamcrest.object; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; import org.hamcrest.TypeSafeMatcher; public class IsCompatibleType<T> extends TypeSafeMatcher<Class<?>> { @@ -12,15 +11,30 @@ public class IsCompatibleType<T> extends TypeSafeMatcher<Class<?>> { this.type = type; } + @Override public boolean matchesSafely(Class<?> cls) { return type.isAssignableFrom(cls); } + @Override + public void describeMismatchSafely(Class<?> cls, Description mismatchDescription) { + mismatchDescription.appendValue(cls.getName()); + } + + @Override public void describeTo(Description description) { description.appendText("type < ").appendText(type.getName()); } - @Factory + /** + * Creates a matcher of {@link Class} that matches when the specified baseType is + * assignable from the examined class. + * For example: + * <pre>assertThat(Integer.class, typeCompatibleWith(Number.class))</pre> + * + * @param baseType + * the base class to examine classes against + */ public static <T> Matcher<Class<?>> typeCompatibleWith(Class<T> baseType) { return new IsCompatibleType<T>(baseType); } diff --git a/hamcrest-library/src/main/java/org/hamcrest/object/IsEventFrom.java b/hamcrest-library/src/main/java/org/hamcrest/object/IsEventFrom.java index 504a8f5..43b64d4 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/object/IsEventFrom.java +++ b/hamcrest-library/src/main/java/org/hamcrest/object/IsEventFrom.java @@ -1,11 +1,8 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ package org.hamcrest.object; import org.hamcrest.Description; import org.hamcrest.Matcher; -import org.hamcrest.Factory; -import org.hamcrest.TypeSafeMatcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; import java.util.EventObject; @@ -13,24 +10,35 @@ import java.util.EventObject; /** * Tests if the value is an event announced by a specific object. */ -public class IsEventFrom extends TypeSafeMatcher<EventObject> { - private final Class eventClass; +public class IsEventFrom extends TypeSafeDiagnosingMatcher<EventObject> { + private final Class<?> eventClass; private final Object source; - public IsEventFrom(Class eventClass, Object source) { + public IsEventFrom(Class<?> eventClass, Object source) { this.eventClass = eventClass; this.source = source; } - public boolean matchesSafely(EventObject item) { - return eventClass.isInstance(item) - && eventHasSameSource(item); + @Override + public boolean matchesSafely(EventObject item, Description mismatchDescription) { + if (!eventClass.isInstance(item)) { + mismatchDescription.appendText("item type was " + item.getClass().getName()); + return false; + } + + if (!eventHasSameSource(item)) { + mismatchDescription.appendText("source was ").appendValue(item.getSource()); + return false; + } + return true; } + private boolean eventHasSameSource(EventObject ev) { return ev.getSource() == source; } + @Override public void describeTo(Description description) { description.appendText("an event of type ") .appendText(eventClass.getName()) @@ -39,20 +47,29 @@ public class IsEventFrom extends TypeSafeMatcher<EventObject> { } /** - * Constructs an IsEventFrom Matcher that returns true for any object + * Creates a matcher of {@link java.util.EventObject} that matches any object * derived from <var>eventClass</var> announced by <var>source</var>. + * For example: + * <pre>assertThat(myEvent, is(eventFrom(PropertyChangeEvent.class, myBean)))</pre> + * + * @param eventClass + * the class of the event to match on + * @param source + * the source of the event */ - @Factory public static Matcher<EventObject> eventFrom(Class<? extends EventObject> eventClass, Object source) { return new IsEventFrom(eventClass, source); } /** - * Constructs an IsEventFrom Matcher that returns true for any object - * derived from {@link java.util.EventObject} announced by <var>source - * </var>. + * Creates a matcher of {@link java.util.EventObject} that matches any EventObject + * announced by <var>source</var>. + * For example: + * <pre>assertThat(myEvent, is(eventFrom(myBean)))</pre> + * + * @param source + * the source of the event */ - @Factory public static Matcher<EventObject> eventFrom(Object source) { return eventFrom(EventObject.class, source); } diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/IsBlankString.java b/hamcrest-library/src/main/java/org/hamcrest/text/IsBlankString.java new file mode 100644 index 0000000..b168541 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/text/IsBlankString.java @@ -0,0 +1,55 @@ + +package org.hamcrest.text; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.regex.Pattern; + +import static org.hamcrest.core.AnyOf.anyOf; +import static org.hamcrest.core.IsNull.nullValue; + +/** + * Matches blank Strings (and null). + */ +public final class IsBlankString extends TypeSafeMatcher<String> { + private static final IsBlankString BLANK_INSTANCE = new IsBlankString(); + @SuppressWarnings("unchecked") + private static final Matcher<String> NULL_OR_BLANK_INSTANCE = anyOf(nullValue(), BLANK_INSTANCE); + + private static final Pattern REGEX_WHITESPACE = Pattern.compile("\\s*"); + + private IsBlankString() { } + + @Override + public boolean matchesSafely(String item) { + return REGEX_WHITESPACE.matcher(item).matches(); + } + + @Override + public void describeTo(Description description) { + description.appendText("a blank string"); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string contains + * zero or more whitespace characters and nothing else. + * For example: + * <pre>assertThat(" ", is(blankString()))</pre> + */ + public static Matcher<String> blankString() { + return BLANK_INSTANCE; + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or + * contains zero or more whitespace characters and nothing else. + * For example: + * <pre>assertThat(((String)null), is(blankOrNullString()))</pre> + * + */ + public static Matcher<String> blankOrNullString() { + return NULL_OR_BLANK_INSTANCE; + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/IsEmptyString.java b/hamcrest-library/src/main/java/org/hamcrest/text/IsEmptyString.java new file mode 100644 index 0000000..bbe5681 --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/text/IsEmptyString.java @@ -0,0 +1,77 @@ + +package org.hamcrest.text; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import static org.hamcrest.core.AnyOf.anyOf; +import static org.hamcrest.core.IsNull.nullValue; + +/** + * Matches empty Strings (and null). + */ +public final class IsEmptyString extends TypeSafeMatcher<String> { + private static final IsEmptyString INSTANCE = new IsEmptyString(); + @SuppressWarnings("unchecked") + private static final Matcher<String> NULL_OR_EMPTY_INSTANCE = anyOf(nullValue(), INSTANCE); + + private IsEmptyString() { } + + @Override + public boolean matchesSafely(String item) { + return item.equals(""); + } + + @Override + public void describeTo(Description description) { + description.appendText("an empty string"); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string has zero length. + * For example: + * <pre>assertThat("", isEmptyString())</pre> + * + * @deprecated use is(emptyString()) instead + */ + @Deprecated + public static Matcher<String> isEmptyString() { + return emptyString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string has zero length. + * For example: + * <pre>assertThat("", is(emptyString()))</pre> + * + */ + public static Matcher<String> emptyString() { + return INSTANCE; + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or + * has zero length. + * For example: + * <pre>assertThat(((String)null), isEmptyOrNullString())</pre> + * + * @deprecated use is(emptyOrNullString()) instead + * + */ + @Deprecated + public static Matcher<String> isEmptyOrNullString() { + return emptyOrNullString(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is <code>null</code>, or + * has zero length. + * For example: + * <pre>assertThat(((String)null), is(emptyOrNullString()))</pre> + * + */ + public static Matcher<String> emptyOrNullString() { + return NULL_OR_EMPTY_INSTANCE; + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringCase.java b/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringCase.java index cc78c71..00586f6 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringCase.java +++ b/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringCase.java @@ -1,42 +1,54 @@ -/* Copyright (c) 2000-2006 hamcrest.org
- */
-package org.hamcrest.text;
-
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.TypeSafeMatcher;
-
-/**
- * Tests if a string is equal to another string, regardless of the case.
- */
-public class IsEqualIgnoringCase extends TypeSafeMatcher<String> {
-
- // TODO: Replace String with CharSequence to allow for easy interopability between
- // String, StringBuffer, StringBuilder, CharBuffer, etc (joe).
-
- private final String string;
-
- public IsEqualIgnoringCase(String string) {
- if (string == null) {
- throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()");
- }
- this.string = string;
- }
-
- public boolean matchesSafely(String item) {
- return string.equalsIgnoreCase(item);
- }
-
- public void describeTo(Description description) {
- description.appendText("eqIgnoringCase(")
- .appendValue(string)
- .appendText(")");
- }
-
- @Factory
- public static Matcher<String> equalToIgnoringCase(String string) {
- return new IsEqualIgnoringCase(string);
- }
-
-}
+package org.hamcrest.text; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +/** + * Tests if a string is equal to another string, regardless of the case. + */ +public class IsEqualIgnoringCase extends TypeSafeMatcher<String> { + + // TODO: Replace String with CharSequence to allow for easy interoperability between + // String, StringBuffer, StringBuilder, CharBuffer, etc (joe). + + private final String string; + + public IsEqualIgnoringCase(String string) { + if (string == null) { + throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()"); + } + this.string = string; + } + + @Override + public boolean matchesSafely(String item) { + return string.equalsIgnoreCase(item); + } + + @Override + public void describeMismatchSafely(String item, Description mismatchDescription) { + mismatchDescription.appendText("was ").appendValue(item); + } + + @Override + public void describeTo(Description description) { + description.appendText("equalToIgnoringCase(") + .appendValue(string) + .appendText(")"); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is equal to + * the specified expectedString, ignoring case. + * For example: + * <pre>assertThat("Foo", equalToIgnoringCase("FOO"))</pre> + * + * @param expectedString + * the expected value of matched strings + */ + public static Matcher<String> equalToIgnoringCase(String expectedString) { + return new IsEqualIgnoringCase(expectedString); + } + +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringWhiteSpace.java b/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringWhiteSpace.java index dd390e8..f2b706c 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringWhiteSpace.java +++ b/hamcrest-library/src/main/java/org/hamcrest/text/IsEqualIgnoringWhiteSpace.java @@ -1,60 +1,79 @@ -/* Copyright (c) 2000-2006 hamcrest.org
- */
-package org.hamcrest.text;
-
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.Factory;
-import org.hamcrest.TypeSafeMatcher;
-
-/**
- * Tests if a string is equal to another string, ignoring any changes in whitespace.
- */
-public class IsEqualIgnoringWhiteSpace extends TypeSafeMatcher<String> {
-
- // TODO: Replace String with CharSequence to allow for easy interopability between
- // String, StringBuffer, StringBuilder, CharBuffer, etc (joe).
-
- private final String string;
-
- public IsEqualIgnoringWhiteSpace(String string) {
- if (string == null) {
- throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()");
- }
- this.string = string;
- }
-
- public boolean matchesSafely(String item) {
- return stripSpace(string).equalsIgnoreCase(stripSpace(item));
- }
-
- public void describeTo(Description description) {
- description.appendText("eqIgnoringWhiteSpace(")
- .appendValue(string)
- .appendText(")");
- }
-
- public String stripSpace(String string) {
- StringBuilder result = new StringBuilder();
- boolean lastWasSpace = true;
- for (int i = 0; i < string.length(); i++) {
- char c = string.charAt(i);
- if (Character.isWhitespace(c)) {
- if (!lastWasSpace) {
- result.append(' ');
- }
- lastWasSpace = true;
- } else {
- result.append(c);
- lastWasSpace = false;
- }
- }
- return result.toString().trim();
- }
-
- @Factory
- public static Matcher<String> equalToIgnoringWhiteSpace(String string) {
- return new IsEqualIgnoringWhiteSpace(string);
- }
-
-}
+package org.hamcrest.text; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import static java.lang.Character.isWhitespace; + +/** + * Tests if a string is equal to another string, ignoring any changes in whitespace. + */ +public class IsEqualIgnoringWhiteSpace extends TypeSafeMatcher<String> { + + // TODO: Replace String with CharSequence to allow for easy interoperability between + // String, StringBuffer, StringBuilder, CharBuffer, etc (joe). + + private final String string; + + public IsEqualIgnoringWhiteSpace(String string) { + if (string == null) { + throw new IllegalArgumentException("Non-null value required by IsEqualIgnoringCase()"); + } + this.string = string; + } + + @Override + public boolean matchesSafely(String item) { + return stripSpace(string).equalsIgnoreCase(stripSpace(item)); + } + + @Override + public void describeMismatchSafely(String item, Description mismatchDescription) { + mismatchDescription.appendText("was ").appendText(stripSpace(item)); + } + + @Override + public void describeTo(Description description) { + description.appendText("equalToIgnoringWhiteSpace(") + .appendValue(string) + .appendText(")"); + } + + public String stripSpace(String toBeStripped) { + final StringBuilder result = new StringBuilder(); + boolean lastWasSpace = true; + for (int i = 0; i < toBeStripped.length(); i++) { + char c = toBeStripped.charAt(i); + if (isWhitespace(c)) { + if (!lastWasSpace) { + result.append(' '); + } + lastWasSpace = true; + } else { + result.append(c); + lastWasSpace = false; + } + } + return result.toString().trim(); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string is equal to + * the specified expectedString, when whitespace differences are (mostly) ignored. To be + * exact, the following whitespace rules are applied: + * <ul> + * <li>all leading and trailing whitespace of both the expectedString and the examined string are ignored</li> + * <li>any remaining whitespace, appearing within either string, is collapsed to a single space before comparison</li> + * </ul> + * For example: + * <pre>assertThat(" my\tfoo bar ", equalToIgnoringWhiteSpace(" my foo bar"))</pre> + * + * @param expectedString + * the expected value of matched strings + */ + public static Matcher<String> equalToIgnoringWhiteSpace(String expectedString) { + return new IsEqualIgnoringWhiteSpace(expectedString); + } + +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/MatchesPattern.java b/hamcrest-library/src/main/java/org/hamcrest/text/MatchesPattern.java new file mode 100644 index 0000000..e0eda0a --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/text/MatchesPattern.java @@ -0,0 +1,41 @@ +package org.hamcrest.text; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.regex.Pattern; + +public class MatchesPattern extends TypeSafeMatcher<String> { + private final Pattern pattern; + + public MatchesPattern(Pattern pattern) { + this.pattern = pattern; + } + + @Override + protected boolean matchesSafely(String item) { + return pattern.matcher(item).matches(); + } + + @Override + public void describeTo(Description description) { + description.appendText("a string matching the pattern '" + pattern + "'"); + } + + /** + * Creates a matcher of {@link java.lang.String} that matches when the examined string + * exactly matches the given {@link java.util.regex.Pattern}. + */ + public static Matcher<String> matchesPattern(Pattern pattern) { + return new MatchesPattern(pattern); + } + + /** + * Creates a matcher of {@link java.lang.String} that matches when the examined string + * exactly matches the given regular expression, treated as a {@link java.util.regex.Pattern}. + */ + public static Matcher<String> matchesPattern(String regex) { + return new MatchesPattern(Pattern.compile(regex)); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/StringContains.java b/hamcrest-library/src/main/java/org/hamcrest/text/StringContains.java deleted file mode 100644 index 9e55560..0000000 --- a/hamcrest-library/src/main/java/org/hamcrest/text/StringContains.java +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ -package org.hamcrest.text; - -import org.hamcrest.Factory; -import org.hamcrest.Matcher; - -/** - * Tests if the argument is a string that contains a substring. - */ -public class StringContains extends SubstringMatcher { - public StringContains(String substring) { - super(substring); - } - - protected boolean evalSubstringOf(String s) { - return s.indexOf(substring) >= 0; - } - - protected String relationship() { - return "containing"; - } - - @Factory - public static Matcher<String> containsString(String substring) { - return new StringContains(substring); - } - -}
\ No newline at end of file diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/StringContainsInOrder.java b/hamcrest-library/src/main/java/org/hamcrest/text/StringContainsInOrder.java new file mode 100644 index 0000000..f5d24ff --- /dev/null +++ b/hamcrest-library/src/main/java/org/hamcrest/text/StringContainsInOrder.java @@ -0,0 +1,69 @@ +package org.hamcrest.text; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.util.Arrays; + +public class StringContainsInOrder extends TypeSafeMatcher<String> { + private final Iterable<String> substrings; + + public StringContainsInOrder(Iterable<String> substrings) { + this.substrings = substrings; + } + + @Override + public boolean matchesSafely(String s) { + int fromIndex = 0; + + for (String substring : substrings) { + fromIndex = s.indexOf(substring, fromIndex); + if (fromIndex == -1) { + return false; + } + } + + return true; + } + + @Override + public void describeMismatchSafely(String item, Description mismatchDescription) { + mismatchDescription.appendText("was \"").appendText(item).appendText("\""); + } + + @Override + public void describeTo(Description description) { + description.appendText("a string containing ") + .appendValueList("", ", ", "", substrings) + .appendText(" in order"); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string contains all of + * the specified substrings, considering the order of their appearance. + * For example: + * <pre>assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("bar", "foo")))</pre> + * fails as "foo" occurs before "bar" in the string "myfoobarbaz" + * + * @param substrings + * the substrings that must be contained within matching strings + */ + public static Matcher<String> stringContainsInOrder(Iterable<String> substrings) { + return new StringContainsInOrder(substrings); + } + + /** + * Creates a matcher of {@link String} that matches when the examined string contains all of + * the specified substrings, considering the order of their appearance. + * For example: + * <pre>assertThat("myfoobarbaz", stringContainsInOrder("bar", "foo"))</pre> + * fails as "foo" occurs before "bar" in the string "myfoobarbaz" + * + * @param substrings + * the substrings that must be contained within matching strings + */ + public static Matcher<String> stringContainsInOrder(String... substrings) { + return new StringContainsInOrder(Arrays.asList(substrings)); + } +} diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/StringEndsWith.java b/hamcrest-library/src/main/java/org/hamcrest/text/StringEndsWith.java deleted file mode 100644 index 10e4764..0000000 --- a/hamcrest-library/src/main/java/org/hamcrest/text/StringEndsWith.java +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ -package org.hamcrest.text; - -import org.hamcrest.Factory; -import org.hamcrest.Matcher; - -/** - * Tests if the argument is a string that contains a substring. - */ -public class StringEndsWith extends SubstringMatcher { - public StringEndsWith(String substring) { - super(substring); - } - - protected boolean evalSubstringOf(String s) { - return s.endsWith(substring); - } - - protected String relationship() { - return "ending with"; - } - - @Factory - public static Matcher<String> endsWith(String substring) { - return new StringEndsWith(substring); - } - -} diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/StringStartsWith.java b/hamcrest-library/src/main/java/org/hamcrest/text/StringStartsWith.java deleted file mode 100644 index 4613101..0000000 --- a/hamcrest-library/src/main/java/org/hamcrest/text/StringStartsWith.java +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2000-2006 hamcrest.org - */ -package org.hamcrest.text; - -import org.hamcrest.Factory; -import org.hamcrest.Matcher; - -/** - * Tests if the argument is a string that contains a substring. - */ -public class StringStartsWith extends SubstringMatcher { - public StringStartsWith(String substring) { - super(substring); - } - - protected boolean evalSubstringOf(String s) { - return s.startsWith(substring); - } - - protected String relationship() { - return "starting with"; - } - - @Factory - public static Matcher<String> startsWith(String substring) { - return new StringStartsWith(substring); - } - -}
\ No newline at end of file diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/SubstringMatcher.java b/hamcrest-library/src/main/java/org/hamcrest/text/SubstringMatcher.java deleted file mode 100644 index 8ebe739..0000000 --- a/hamcrest-library/src/main/java/org/hamcrest/text/SubstringMatcher.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.hamcrest.text; - -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; - -public abstract class SubstringMatcher extends TypeSafeMatcher<String> { - - // TODO: Replace String with CharSequence to allow for easy interopability between - // String, StringBuffer, StringBuilder, CharBuffer, etc (joe). - - protected final String substring; - - protected SubstringMatcher(final String substring) { - this.substring = substring; - } - - public boolean matchesSafely(String item) { - return evalSubstringOf(item); - } - - public void describeTo(Description description) { - description.appendText("a string ") - .appendText(relationship()) - .appendText(" ") - .appendValue(substring); - } - - protected abstract boolean evalSubstringOf(String string); - - protected abstract String relationship(); -}
\ No newline at end of file diff --git a/hamcrest-library/src/main/java/org/hamcrest/text/X.java b/hamcrest-library/src/main/java/org/hamcrest/text/X.java deleted file mode 100644 index 7e85bd9..0000000 --- a/hamcrest-library/src/main/java/org/hamcrest/text/X.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.hamcrest.text; - -import org.hamcrest.Matcher; -import org.hamcrest.CoreMatchers; - -public class X { - - public static void main(String[] args) { - - x(CoreMatchers.any(String.class)); - - - } - - private static void x(Matcher<String> s) { - - } -} diff --git a/hamcrest-library/src/main/java/org/hamcrest/xml/HasXPath.java b/hamcrest-library/src/main/java/org/hamcrest/xml/HasXPath.java index 742935b..30ed081 100644 --- a/hamcrest-library/src/main/java/org/hamcrest/xml/HasXPath.java +++ b/hamcrest-library/src/main/java/org/hamcrest/xml/HasXPath.java @@ -1,27 +1,34 @@ package org.hamcrest.xml; +import org.hamcrest.Condition; import org.hamcrest.Description; -import org.hamcrest.Factory; import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; +import org.hamcrest.core.IsAnything; import org.w3c.dom.Node; -import javax.xml.xpath.XPath; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.xpath.*; + +import static javax.xml.xpath.XPathConstants.STRING; +import static org.hamcrest.Condition.matched; +import static org.hamcrest.Condition.notMatched; /** * Applies a Matcher to a given XML Node in an existing XML Node tree, specified by an XPath expression. * * @author Joe Walnes + * @author Steve Freeman */ -public class HasXPath extends TypeSafeMatcher<Node> { - +public class HasXPath extends TypeSafeDiagnosingMatcher<Node> { + public static final NamespaceContext NO_NAMESPACE_CONTEXT = null; + private static final IsAnything<String> WITH_ANY_CONTENT = new IsAnything<String>(""); + private static final Condition.Step<Object,String> NODE_EXISTS = nodeExists(); private final Matcher<String> valueMatcher; private final XPathExpression compiledXPath; private final String xpathString; + private final QName evaluationMode; /** * @param xPathExpression XPath expression. @@ -29,46 +36,134 @@ public class HasXPath extends TypeSafeMatcher<Node> { * May be null to specify that the XPath must exist but the value is irrelevant. */ public HasXPath(String xPathExpression, Matcher<String> valueMatcher) { + this(xPathExpression, NO_NAMESPACE_CONTEXT, valueMatcher); + } + + /** + * @param xPathExpression XPath expression. + * @param namespaceContext Resolves XML namespace prefixes in the XPath expression + * @param valueMatcher Matcher to use at given XPath. + * May be null to specify that the XPath must exist but the value is irrelevant. + */ + public HasXPath(String xPathExpression, NamespaceContext namespaceContext, Matcher<String> valueMatcher) { + this(xPathExpression, namespaceContext, valueMatcher, STRING); + } + + private HasXPath(String xPathExpression, NamespaceContext namespaceContext, Matcher<String> valueMatcher, QName mode) { + this.compiledXPath = compiledXPath(xPathExpression, namespaceContext); + this.xpathString = xPathExpression; + this.valueMatcher = valueMatcher; + this.evaluationMode = mode; + } + + @Override + public boolean matchesSafely(Node item, Description mismatch) { + return evaluated(item, mismatch) + .and(NODE_EXISTS) + .matching(valueMatcher); + } + + @Override + public void describeTo(Description description) { + description.appendText("an XML document with XPath ").appendText(xpathString); + if (valueMatcher != null) { + description.appendText(" ").appendDescriptionOf(valueMatcher); + } + } + + private Condition<Object> evaluated(Node item, Description mismatch) { try { - XPath xPath = XPathFactory.newInstance().newXPath(); - compiledXPath = xPath.compile(xPathExpression); - this.xpathString = xPathExpression; - this.valueMatcher = valueMatcher; + return matched(compiledXPath.evaluate(item, evaluationMode), mismatch); } catch (XPathExpressionException e) { - throw new IllegalArgumentException("Invalid XPath : " + xPathExpression, e); + mismatch.appendText(e.getMessage()); } + return notMatched(); } - public boolean matchesSafely(Node item) { + private static Condition.Step<Object, String> nodeExists() { + return new Condition.Step<Object, String>() { + @Override + public Condition<String> apply(Object value, Description mismatch) { + if (value == null) { + mismatch.appendText("xpath returned no results."); + return notMatched(); + } + return matched(String.valueOf(value), mismatch); + } + }; + } + + private static XPathExpression compiledXPath(String xPathExpression, NamespaceContext namespaceContext) { try { - String result = (String) compiledXPath.evaluate(item, XPathConstants.STRING); - if (result == null) { - return false; - } else if (valueMatcher == null) { - return !result.equals(""); - } else { - return valueMatcher.matches(result); + final XPath xPath = XPathFactory.newInstance().newXPath(); + if (namespaceContext != null) { + xPath.setNamespaceContext(namespaceContext); } + return xPath.compile(xPathExpression); } catch (XPathExpressionException e) { - return false; + throw new IllegalArgumentException("Invalid XPath : " + xPathExpression, e); } } - public void describeTo(Description description) { - description.appendText("an XML document with XPath ").appendText(xpathString); - if (valueMatcher != null) { - description.appendText(" ").appendDescriptionOf(valueMatcher); - } - } - - @Factory + + /** + * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the + * specified <code>xPath</code> that satisfies the specified <code>valueMatcher</code>. + * For example: + * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", equalTo("Cheddar")))</pre> + * + * @param xPath + * the target xpath + * @param valueMatcher + * matcher for the value at the specified xpath + */ public static Matcher<Node> hasXPath(String xPath, Matcher<String> valueMatcher) { - return new HasXPath(xPath, valueMatcher); + return hasXPath(xPath, NO_NAMESPACE_CONTEXT, valueMatcher); + } + + /** + * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node has a value at the + * specified <code>xPath</code>, within the specified <code>namespaceContext</code>, that satisfies + * the specified <code>valueMatcher</code>. + * For example: + * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", myNs, equalTo("Cheddar")))</pre> + * + * @param xPath + * the target xpath + * @param namespaceContext + * the namespace for matching nodes + * @param valueMatcher + * matcher for the value at the specified xpath + */ + public static Matcher<Node> hasXPath(String xPath, NamespaceContext namespaceContext, Matcher<String> valueMatcher) { + return new HasXPath(xPath, namespaceContext, valueMatcher, STRING); } - @Factory + /** + * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node + * at the specified <code>xPath</code>, with any content. + * For example: + * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese"))</pre> + * + * @param xPath + * the target xpath + */ public static Matcher<Node> hasXPath(String xPath) { - return hasXPath(xPath, null); + return hasXPath(xPath, NO_NAMESPACE_CONTEXT); } + /** + * Creates a matcher of {@link org.w3c.dom.Node}s that matches when the examined node contains a node + * at the specified <code>xPath</code> within the specified namespace context, with any content. + * For example: + * <pre>assertThat(xml, hasXPath("/root/something[2]/cheese", myNs))</pre> + * + * @param xPath + * the target xpath + * @param namespaceContext + * the namespace for matching nodes + */ + public static Matcher<Node> hasXPath(String xPath, NamespaceContext namespaceContext) { + return new HasXPath(xPath, namespaceContext, WITH_ANY_CONTENT, XPathConstants.NODE); + } } diff --git a/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyTest.java b/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyTest.java new file mode 100644 index 0000000..314797f --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyTest.java @@ -0,0 +1,48 @@ +package org.hamcrest.beans; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.beans.HasProperty.hasProperty; + +/** + * @author Iain McGinniss + * @author Nat Pryce + * @author Steve Freeman + * @author Tom Denley + * @since 1.1.0 + */ +public final class HasPropertyTest { + + private final HasPropertyWithValueTest.BeanWithoutInfo bean = new HasPropertyWithValueTest.BeanWithoutInfo("a bean"); + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<Object> matcher = hasProperty("irrelevant"); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + matchesWhenThePropertyExists() { + assertMatches(hasProperty("writeOnlyProperty"), bean); + } + + @Test public void + doesNotMatchIfPropertyDoesNotExist() { + assertDoesNotMatch(hasProperty("aNonExistentProp"), bean); + } + + @Test public void + describesItself() { + assertDescription("hasProperty(\"property\")", hasProperty("property")); + } + + @Test public void + describesAMismatch() { + assertMismatchDescription("no \"aNonExistentProp\" in <[Person: a bean]>", + hasProperty("aNonExistentProp"), bean); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyWithValueTest.java b/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyWithValueTest.java new file mode 100644 index 0000000..eeaa113 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/beans/HasPropertyWithValueTest.java @@ -0,0 +1,139 @@ +package org.hamcrest.beans; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; +import org.hamcrest.core.IsEqual; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; +import static org.hamcrest.core.IsAnything.anything; +import static org.hamcrest.core.IsEqual.equalTo; + +/** + * @author Iain McGinniss + * @author Nat Pryce + * @author Steve Freeman + * @since 1.1.0 + */ +@SuppressWarnings("UnusedDeclaration") +public class HasPropertyWithValueTest extends AbstractMatcherTest { + private final BeanWithoutInfo shouldMatch = new BeanWithoutInfo("is expected"); + private final BeanWithoutInfo shouldNotMatch = new BeanWithoutInfo("not expected"); + + private final BeanWithInfo beanWithInfo = new BeanWithInfo("with info"); + + @Override + protected Matcher<?> createMatcher() { + return hasProperty("irrelevant", anything()); + } + + public void testMatchesInfolessBeanWithMatchedNamedProperty() { + assertMatches("with property", hasProperty("property", equalTo("is expected")), shouldMatch); + assertMismatchDescription("property 'property' was \"not expected\"", + hasProperty("property", equalTo("is expected")), shouldNotMatch); + } + + public void testMatchesBeanWithInfoWithMatchedNamedProperty() { + assertMatches("with bean info", hasProperty("property", equalTo("with info")), beanWithInfo); + assertMismatchDescription("property 'property' was \"with info\"", + hasProperty("property", equalTo("without info")), beanWithInfo); + } + + public void testDoesNotMatchInfolessBeanWithoutMatchedNamedProperty() { + assertMismatchDescription("No property \"nonExistentProperty\"", + hasProperty("nonExistentProperty", anything()), shouldNotMatch); + } + + public void testDoesNotMatchWriteOnlyProperty() { + assertMismatchDescription("property \"writeOnlyProperty\" is not readable", + hasProperty("writeOnlyProperty", anything()), shouldNotMatch); + } + + public void testDescribeTo() { + assertDescription("hasProperty(\"property\", <true>)", hasProperty("property", equalTo(true))); + } + + public void testMatchesPropertyAndValue() { + assertMatches("property with value", hasProperty( "property", anything()), beanWithInfo); + } + + public void testDoesNotWriteMismatchIfPropertyMatches() { + Description description = new StringDescription(); + hasProperty( "property", anything()).describeMismatch(beanWithInfo, description); + assertEquals("Expected mismatch description", "", description.toString()); + } + + public void testDescribesMissingPropertyMismatch() { + assertMismatchDescription("No property \"honk\"", hasProperty( "honk", anything()), shouldNotMatch); + } + + public void testCanAccessAnAnonymousInnerClass() { + class X implements IX { + @Override + public int getTest() { + return 1; + } + } + + assertThat(new X(), HasPropertyWithValue.hasProperty("test", IsEqual.equalTo(1))); + } + + interface IX { + int getTest(); + } + + public static class BeanWithoutInfo { + private String property; + + public BeanWithoutInfo(String property) { + this.property = property; + } + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + + public void setWriteOnlyProperty(@SuppressWarnings("unused") float property) { + } + + @Override + public String toString() { + return "[Person: " + property + "]"; + } + } + + public static class BeanWithInfo { + private final String propertyValue; + + public BeanWithInfo(String propertyValue) { + this.propertyValue = propertyValue; + } + + public String property() { + return propertyValue; + } + } + + public static class BeanWithInfoBeanInfo extends SimpleBeanInfo { + @Override + public PropertyDescriptor[] getPropertyDescriptors() { + try { + return new PropertyDescriptor[] { + new PropertyDescriptor("property", BeanWithInfo.class, "property", null) + }; + } catch (IntrospectionException e) { + throw new RuntimeException("Introspection exception: " + e.getMessage()); + } + } + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/beans/SamePropertyValuesAsTest.java b/hamcrest-library/src/test/java/org/hamcrest/beans/SamePropertyValuesAsTest.java new file mode 100644 index 0000000..173457f --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/beans/SamePropertyValuesAsTest.java @@ -0,0 +1,98 @@ +package org.hamcrest.beans; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs; + +@SuppressWarnings("UnusedDeclaration") +public class SamePropertyValuesAsTest extends AbstractMatcherTest { + private static final Value aValue = new Value("expected"); + private static final ExampleBean expectedBean = new ExampleBean("same", 1, aValue); + private static final ExampleBean actualBean = new ExampleBean("same", 1, aValue); + + + @Override + protected Matcher<?> createMatcher() { + return samePropertyValuesAs(expectedBean); + } + + public void testReportsMatchWhenAllPropertiesMatch() { + assertMatches("matched properties", samePropertyValuesAs(expectedBean), actualBean); + } + + public void testReportsMismatchWhenActualTypeIsNotAssignableToExpectedType() { + assertMismatchDescription("is incompatible type: ExampleBean", + samePropertyValuesAs((Object)aValue), actualBean); + } + + public void testReportsMismatchOnFirstPropertyDifference() { + assertMismatchDescription("string was \"different\"", + samePropertyValuesAs(expectedBean), new ExampleBean("different", 1, aValue)); + assertMismatchDescription("int was <2>", + samePropertyValuesAs(expectedBean), new ExampleBean("same", 2, aValue)); + assertMismatchDescription("value was <Value other>", + samePropertyValuesAs(expectedBean), new ExampleBean("same", 1, new Value("other"))); + } + + public void testMatchesBeansWithInheritanceButNoExtraProperties() { + assertMatches("sub type with same properties", + samePropertyValuesAs(expectedBean), new SubBeanWithNoExtraProperties("same", 1, aValue)); + } + + public void testRejectsSubTypeThatHasExtraProperties() { + assertMismatchDescription("has extra properties called [extra]", + samePropertyValuesAs(expectedBean), new SubBeanWithExtraProperty("same", 1, aValue)); + } + + public void testDescribesItself() { + assertDescription("same property values as ExampleBean [int: <1>, string: \"same\", value: <Value expected>]", samePropertyValuesAs(expectedBean)); + } + + public static class Value { + public Value(Object value) { + this.value = value; + } + + public final Object value; + @Override + public String toString() { + return "Value " + value; + } + } + + public static class ExampleBean { + private String stringProperty; + private int intProperty; + private Value valueProperty; + + public ExampleBean(String stringProperty, int intProperty, Value valueProperty) { + this.stringProperty = stringProperty; + this.intProperty = intProperty; + this.valueProperty = valueProperty; + } + + public String getString() { + return stringProperty; + } + public int getInt() { + return intProperty; + } + public Value getValue() { + return valueProperty; + } + } + + public static class SubBeanWithNoExtraProperties extends ExampleBean { + public SubBeanWithNoExtraProperties(String stringProperty, int intProperty, Value valueProperty) { + super(stringProperty, intProperty, valueProperty); + } + } + + public static class SubBeanWithExtraProperty extends ExampleBean { + public SubBeanWithExtraProperty(String stringProperty, int intProperty, Value valueProperty) { + super(stringProperty, intProperty, valueProperty); + } + public String getExtra() { return "extra"; } + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInAnyOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInAnyOrderTest.java new file mode 100644 index 0000000..d4dc270 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInAnyOrderTest.java @@ -0,0 +1,43 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.collection.IsArrayContainingInAnyOrder.arrayContainingInAnyOrder; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsArrayContainingInAnyOrderTest extends AbstractMatcherTest { + + @SuppressWarnings("unchecked") + @Override + protected Matcher<?> createMatcher() { + return arrayContainingInAnyOrder(equalTo(1), equalTo(2)); + } + + @SuppressWarnings("unchecked") + public void testHasAReadableDescription() { + assertDescription("[<1>, <2>] in any order", arrayContainingInAnyOrder(equalTo(1), equalTo(2))); + assertDescription("[<1>, <2>] in any order", arrayContainingInAnyOrder(1, 2)); + } + + public void testMatchesItemsInAnyOrder() { + assertMatches("in order", arrayContainingInAnyOrder(1, 2, 3), new Integer[] {1, 2, 3}); + assertMatches("out of order", arrayContainingInAnyOrder(1, 2, 3), new Integer[] {3, 2, 1}); + assertMatches("single", arrayContainingInAnyOrder(1), new Integer[] {1}); + } + + @SuppressWarnings("unchecked") + public void testAppliesMatchersInAnyOrder() { + assertMatches("in order", arrayContainingInAnyOrder(equalTo(1), equalTo(2), equalTo(3)), new Integer[] {1, 2, 3}); + assertMatches("out of order", arrayContainingInAnyOrder(equalTo(1), equalTo(2), equalTo(3)), new Integer[] {3, 2, 1}); + assertMatches("single", arrayContainingInAnyOrder(equalTo(1)), new Integer[] {1}); + } + + public void testMismatchesItemsInAnyOrder() { + Matcher<Integer[]> matcher = arrayContainingInAnyOrder(1, 2, 3); + assertMismatchDescription("was null", matcher, null); + assertMismatchDescription("no item matches: <1>, <2>, <3> in []", matcher, new Integer[] {}); + assertMismatchDescription("no item matches: <2>, <3> in [<1>]", matcher, new Integer[] {1}); + assertMismatchDescription("not matched: <4>", matcher, new Integer[] {4,3,2,1}); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInOrderTest.java new file mode 100644 index 0000000..ab1d821 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingInOrderTest.java @@ -0,0 +1,45 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.collection.IsArrayContainingInOrder.arrayContaining; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsArrayContainingInOrderTest extends AbstractMatcherTest { + + @SuppressWarnings("unchecked") + @Override + protected Matcher<?> createMatcher() { + return arrayContaining(equalTo(1), equalTo(2)); + } + + @SuppressWarnings("unchecked") + public void testHasAReadableDescription() { + assertDescription("[<1>, <2>]", arrayContaining(equalTo(1), equalTo(2))); + } + + public void testMatchesItemsInOrder() { + assertMatches("in order", arrayContaining(1, 2, 3), new Integer[] {1, 2, 3}); + assertMatches("single", arrayContaining(1), new Integer[] {1}); + } + + @SuppressWarnings("unchecked") + public void testAppliesMatchersInOrder() { + assertMatches("in order", arrayContaining(equalTo(1), equalTo(2), equalTo(3)), new Integer[] {1, 2, 3}); + assertMatches("single", arrayContaining(equalTo(1)), new Integer[] {1}); + } + + public void testMismatchesItemsInOrder() { + Matcher<Integer[]> matcher = arrayContaining(1, 2, 3); + assertMismatchDescription("was null", matcher, null); + assertMismatchDescription("no item was <1>", matcher, new Integer[] {}); + assertMismatchDescription("no item was <2>", matcher, new Integer[] {1}); + assertMismatchDescription("item 0: was <4>", matcher, new Integer[] {4,3,2,1}); + assertMismatchDescription("item 2: was <4>", matcher, new Integer[] {1,2, 4}); + } + + public void testCanHandleNullValuesInAnArray() { + assertMatches("with nulls", arrayContaining(null, null), new Object[]{null, null}); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingTest.java new file mode 100644 index 0000000..275984c --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayContainingTest.java @@ -0,0 +1,72 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.collection.IsArrayContaining.hasItemInArray; + +public class IsArrayContainingTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return hasItemInArray("irrelevant"); + } + + public void testMatchesAnArrayThatContainsAnElementMatchingTheGivenMatcher() { + assertMatches("should matches array that contains 'a'", + hasItemInArray("a"), new String[]{"a", "b", "c"}); + } + + public void testDoesNotMatchAnArrayThatDoesntContainAnElementMatchingTheGivenMatcher() { + assertDoesNotMatch("should not matches array that doesn't contain 'a'", + hasItemInArray("a"), new String[]{"b", "c"}); + assertDoesNotMatch("should not matches empty array", + hasItemInArray("a"), new String[0]); + } + + public void testDoesNotMatchNull() { + assertDoesNotMatch("should not matches null", + hasItemInArray("a"), null); + } + + public void testHasAReadableDescription() { + assertDescription("an array containing \"a\"", hasItemInArray("a")); + } + + // Remaining code no longer compiles, thanks to generics. I think that's a good thing, but + // I still need to investigate how this behaves with code that doesn't use generics. + // I expect ClassCastExceptions will be thrown. + // -Joe. + +// public void testDoesNotMatchObjectThatIsNotAnArray() { +// assertDoesNotMatch("should not matches empty list", +// arrayContaining("a"), "not a collection"); +// } + +// public void testMatchesPrimitiveArrayElements() { +// assertMatches("boolean", arrayContaining(true), new boolean[]{true, false}); +// assertDoesNotMatch("boolean", arrayContaining(false), new boolean[]{false}); +// +// assertMatches("byte", arrayContaining((byte) 1), new byte[]{1, 2, 3}); +// assertDoesNotMatch("byte", arrayContaining((byte) 0), new byte[]{1, 2, 3}); +// +// assertMatches("char", arrayContaining('a'), new char[]{'a', 'b', 'c'}); +// assertDoesNotMatch("char", arrayContaining('z'), new char[]{'a', 'b', 'c'}); +// +// assertMatches("short", arrayContaining((short) 1), new short[]{1, 2, 3}); +// assertDoesNotMatch("short", arrayContaining((short) 0), new short[]{1, 2, 3}); +// +// assertMatches("int", arrayContaining(1), new int[]{1, 2, 3}); +// assertDoesNotMatch("int", arrayContaining(0), new int[]{1, 2, 3}); +// +// assertMatches("long", arrayContaining(1L), new long[]{1, 2, 3}); +// assertDoesNotMatch("long", arrayContaining(0L), new long[]{1, 2, 3}); +// +// assertMatches("float", arrayContaining(1f), new float[]{1f, 2f, 3f}); +// assertDoesNotMatch("float", arrayContaining(0f), new float[]{1f, 2f, 3f}); +// +// assertMatches("double", arrayContaining(1.0), new double[]{1.0, 2.0, 3.0}); +// assertDoesNotMatch("double", arrayContaining(0.0), new double[]{1.0, 2.0, 3.0}); +// } + +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayTest.java new file mode 100644 index 0000000..4135d9f --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayTest.java @@ -0,0 +1,59 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; + +import static org.hamcrest.collection.IsArray.array; +import static org.hamcrest.core.IsEqual.equalTo; + +@SuppressWarnings("unchecked") +public class IsArrayTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return array(equalTo("irrelevant")); + } + + public void testMatchesAnArrayThatMatchesAllTheElementMatchers() { + assertMatches("should match array with matching elements", + array(equalTo("a"), equalTo("b"), equalTo("c")), new String[]{"a", "b", "c"}); + } + + public void testDoesNotMatchAnArrayWhenElementsDoNotMatch() { + assertDoesNotMatch("should not match array with different elements", + array(equalTo("a"), equalTo("b")), new String[]{"b", "c"}); + } + + public void testDoesNotMatchAnArrayOfDifferentSize() { + assertDoesNotMatch("should not match larger array", + array(equalTo("a"), equalTo("b")), new String[]{"a", "b", "c"}); + assertDoesNotMatch("should not match smaller array", + array(equalTo("a"), equalTo("b")), new String[]{"a"}); + } + + public void testDoesNotMatchNull() { + assertDoesNotMatch("should not match null", + array(equalTo("a")), null); + } + + public void testHasAReadableDescription() { + assertDescription("[\"a\", \"b\"]", array(equalTo("a"), equalTo("b"))); + } + + public void testHasAReadableMismatchDescriptionUsing() { + assertMismatchDescription("element <0> was \"c\"", array(equalTo("a"), equalTo("b")), new String[]{"c", "b"}); + } + + public void testHasAReadableMismatchDescriptionUsingCustomMatchers() { + final BaseMatcher<String> m = new BaseMatcher<String>() { + @Override public boolean matches(Object item) { return false; } + @Override public void describeTo(Description description) { description.appendText("c"); } + @Override public void describeMismatch(Object item, Description description) { + description.appendText("didn't match"); + } + }; + assertMismatchDescription("element <0> didn't match", array(m, equalTo("b")), new String[]{"c", "b"}); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayWithSizeTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayWithSizeTest.java new file mode 100644 index 0000000..18f607e --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsArrayWithSizeTest.java @@ -0,0 +1,36 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize; +import static org.hamcrest.collection.IsArrayWithSize.emptyArray; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsArrayWithSizeTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return arrayWithSize(equalTo(2)); + } + + public void testMatchesWhenSizeIsCorrect() { + assertMatches("correct size", arrayWithSize(equalTo(3)), new Object[] {1, 2, 3}); + assertDoesNotMatch("incorrect size", arrayWithSize(equalTo(2)), new Object[] {1, 2, 3}); + } + + public void testProvidesConvenientShortcutForArrayWithSizeEqualTo() { + assertMatches("correct size", arrayWithSize(3), new Object[] {1, 2, 3}); + assertDoesNotMatch("incorrect size", arrayWithSize(2), new Object[] {1, 2, 3}); + } + + public void testEmptyArray() { + assertMatches("correct size", emptyArray(), new Object[] {}); + assertDoesNotMatch("incorrect size", emptyArray(), new Object[] {1}); + } + + public void testHasAReadableDescription() { + assertDescription("an array with size <3>", arrayWithSize(equalTo(3))); + assertDescription("an empty array", emptyArray()); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsCollectionWithSizeTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsCollectionWithSizeTest.java new file mode 100644 index 0000000..b04a0c5 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsCollectionWithSizeTest.java @@ -0,0 +1,77 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; +import org.hamcrest.MatcherAssert; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsCollectionWithSizeTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return hasSize(7); + } + + public void testMatchesWhenSizeIsCorrect() { + assertMatches("correct size", hasSize(equalTo(2)), asList(null, null)); + assertMismatchDescription("collection size was <3>", hasSize(equalTo(2)), asList(null, null, null)); + } + + public void testMatchesCollectionWhenSizeIsCorrectUsingObjectElementType() { + Collection<Object> list = asList(null, null); + assertMatches("correct size", hasSize(equalTo(2)), list); + assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list); + } + + public void testMatchesCollectionWhenSizeIsCorrectUsingStringElementType() { + Collection<String> list = asList("a", "b"); + assertMatches("correct size", hasSize(equalTo(2)), list); + assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list); + } + + public void testMatchesCollectionWhenSizeIsCorrectUsingWildcardElementType() { + Collection<?> list = asList("a", "b"); + assertMatches("correct size", hasSize(equalTo(2)), list); + assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list); + } + + public void testMatchesListWhenSizeIsCorrectUsingObjectElementType() { + List<Object> list = asList(null, null); + assertMatches("correct size", hasSize(equalTo(2)), list); + assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list); + } + + public void testMatchesListWhenSizeIsCorrectUsingStringElementType() { + List<String> list = asList("a", "b"); + assertMatches("correct size", hasSize(equalTo(2)), list); + assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list); + } + + public void testMatchesListWhenSizeIsCorrectUsingWildcardElementType() { + List<?> list = asList("a", "b"); + assertMatches("correct size", hasSize(equalTo(2)), list); + assertMismatchDescription("collection size was <2>", hasSize(equalTo(3)), list); + } + + public void testProvidesConvenientShortcutForHasSizeEqualTo() { + assertMatches("correct size", hasSize(2), asList(null, null)); + assertMismatchDescription("collection size was <3>", hasSize(2), asList(null, null, null)); + } + + public void testHasAReadableDescription() { + assertDescription("a collection with size <3>", hasSize(equalTo(3))); + } + + public void testCompilesWithATypedCollection() { + // To prove Issue 43 + ArrayList<String> arrayList = new ArrayList<String>(); + MatcherAssert.assertThat(arrayList, hasSize(0)); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyCollectionTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyCollectionTest.java new file mode 100644 index 0000000..ea875e8 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyCollectionTest.java @@ -0,0 +1,45 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.util.ArrayList; +import java.util.Collection; + +import static java.util.Arrays.asList; +import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.hamcrest.core.Is.is; + +public class IsEmptyCollectionTest extends AbstractMatcherTest { + + @Override + protected Matcher<Collection<?>> createMatcher() { + return empty(); + } + + public void testMatchesAnEmptyCollection() { + assertMatches("empty collection", createMatcher(), emptyCollection()); + } + + public void testDoesNotMatchACollectionWithAnItem() { + assertMismatchDescription("<[one, three]>", is(createMatcher()), collectionOfValues()); + } + + public void testHasAReadableDescription() { + assertDescription("an empty collection", createMatcher()); + } + + public void testCompiles() { + needs(IsEmptyCollection.emptyCollectionOf(String.class)); + } + + private void needs(@SuppressWarnings("unused") Matcher<Collection<String>> bar) { } + + private static Collection<String> collectionOfValues() { + return new ArrayList<String>(asList("one", "three")); + } + + private static Collection<Integer> emptyCollection() { + return new ArrayList<Integer>(); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyIterableTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyIterableTest.java new file mode 100644 index 0000000..600b576 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsEmptyIterableTest.java @@ -0,0 +1,44 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.util.ArrayList; +import java.util.Collection; + +import static java.util.Arrays.asList; +import static org.hamcrest.collection.IsEmptyIterable.emptyIterable; + +public class IsEmptyIterableTest extends AbstractMatcherTest { + + @Override + protected Matcher<Iterable<?>> createMatcher() { + return emptyIterable(); + } + + public void testMatchesAnEmptyIterable() { + assertMatches("empty iterable", createMatcher(), emptyCollection()); + } + + public void testDoesNotMatchAnIterableWithItems() { + assertDoesNotMatch("iterable with an item", createMatcher(), collectionOfValues()); + } + + public void testHasAReadableDescription() { + assertDescription("an empty iterable", createMatcher()); + } + + public void testCompiles() { + needs(IsEmptyIterable.emptyIterableOf(String.class)); + } + + private void needs(@SuppressWarnings("unused") Matcher<Iterable<String>> bar) { } + + private static Collection<String> collectionOfValues() { + return new ArrayList<String>(asList("one", "three")); + } + + private static Collection<Integer> emptyCollection() { + return new ArrayList<Integer>(); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsInTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsInTest.java new file mode 100644 index 0000000..e9fcbdc --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsInTest.java @@ -0,0 +1,44 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; +import org.hamcrest.StringDescription; + +import java.util.Arrays; +import java.util.Collection; + +public class IsInTest extends AbstractMatcherTest { + String[] elements = {"a", "b", "c"}; + + @Override + protected Matcher<?> createMatcher() { + return new IsIn<String>(elements); + } + + public void testReturnsTrueIfArgumentIsInCollection() { + Collection<String> collection = Arrays.asList(elements); + Matcher<String> isIn = new IsIn<String>(collection); + + assertMatches("a", isIn, "a"); + assertMatches("b", isIn, "b"); + assertMatches("c", isIn, "c"); + assertDoesNotMatch("d", isIn, "d"); + } + + public void testReturnsTrueIfArgumentIsInArray() { + Matcher<String> isIn = new IsIn<String>(elements); + + assertMatches("a", isIn, "a"); + assertMatches("b", isIn, "b"); + assertMatches("c", isIn, "c"); + assertDoesNotMatch("d", isIn, "d"); + } + + public void testHasReadableDescription() { + Matcher<String> isIn = new IsIn<String>(elements); + + assertEquals("description", + "one of {\"a\", \"b\", \"c\"}", + StringDescription.toString(isIn)); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInAnyOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInAnyOrderTest.java new file mode 100644 index 0000000..091c347 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInAnyOrderTest.java @@ -0,0 +1,54 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; +import org.hamcrest.collection.IsIterableContainingInOrderTest.WithValue; + +import java.util.Collections; + +import static java.util.Arrays.asList; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.hamcrest.collection.IsIterableContainingInOrderTest.make; +import static org.hamcrest.collection.IsIterableContainingInOrderTest.value; + +public class IsIterableContainingInAnyOrderTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return containsInAnyOrder(1, 2); + } + + public void testMatchesSingleItemIterable() { + assertMatches("single item", containsInAnyOrder(1), asList(1)); + } + + public void testDoesNotMatchEmpty() { + assertMismatchDescription("no item matches: <1>, <2> in []", containsInAnyOrder(1, 2), Collections.<Integer>emptyList()); + } + + public void testMatchesIterableOutOfOrder() { + assertMatches("Out of order", containsInAnyOrder(1, 2), asList(2, 1)); + } + + public void testMatchesIterableInOrder() { + assertMatches("In order", containsInAnyOrder(1, 2), asList(1, 2)); + } + + public void testDoesNotMatchIfOneOfMultipleElementsMismatches() { + assertMismatchDescription("not matched: <4>", containsInAnyOrder(1, 2, 3), asList(1, 2, 4)); + } + + @SuppressWarnings("unchecked") + public void testDoesNotMatchIfThereAreMoreElementsThanMatchers() { + final Matcher<Iterable<? extends WithValue>> helpTheCompilerOut = containsInAnyOrder(value(1), value(3)); + assertMismatchDescription("not matched: <WithValue 2>", helpTheCompilerOut, asList(make(1), make(2), make(3))); + } + + public void testDoesNotMatchIfThereAreMoreMatchersThanElements() { + assertMismatchDescription("no item matches: <4> in [<1>, <2>, <3>]", containsInAnyOrder(1, 2, 3, 4), asList(1, 2, 3)); + } + + public void testHasAReadableDescription() { + assertDescription("iterable with items [<1>, <2>] in any order", containsInAnyOrder(1, 2)); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInOrderTest.java new file mode 100644 index 0000000..8cb1bf8 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInOrderTest.java @@ -0,0 +1,77 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.hamcrest.core.IsEqual.equalTo; + +@SuppressWarnings("unchecked") +public class IsIterableContainingInOrderTest extends AbstractMatcherTest { + // temporary hack until the Java type system works + private final Matcher<Iterable<? extends WithValue>> contains123 = contains(value(1), value(2), value(3)); + + @Override + protected Matcher<?> createMatcher() { + return contains(1, 2); + } + + public void testMatchingSingleItemIterable() throws Exception { + assertMatches("Single item iterable", contains(1), asList(1)); + } + + public void testMatchingMultipleItemIterable() throws Exception { + assertMatches("Multiple item iterable", contains(1, 2, 3), asList(1, 2, 3)); + } + + public void testDoesNotMatchWithMoreElementsThanExpected() throws Exception { + assertMismatchDescription("not matched: <4>", contains(1, 2, 3), asList(1, 2, 3, 4)); + } + + public void testDoesNotMatchWithFewerElementsThanExpected() throws Exception { + List<WithValue> valueList = asList(make(1), make(2)); + assertMismatchDescription("no item was value with <3>", contains123, valueList); + } + + public void testDoesNotMatchIfSingleItemMismatches() throws Exception { + assertMismatchDescription("item 0: value was <3>", contains(value(4)), asList(make(3))); + } + + public void testDoesNotMatchIfOneOfMultipleItemsMismatch() throws Exception { + assertMismatchDescription("item 2: value was <4>", contains123, asList(make(1), make(2), make(4))); + } + + public void testDoesNotMatchEmptyIterable() throws Exception { + assertMismatchDescription("no item was value with <4>", contains(value(4)), new ArrayList<WithValue>()); + } + + public void testHasAReadableDescription() { + assertDescription("iterable containing [<1>, <2>]", contains(1, 2)); + } + + public void testCanHandleNullMatchers() { + assertMatches(contains(null, null), asList(null, null)); + } + + public static class WithValue { + private final int value; + public WithValue(int value) { this.value = value; } + public int getValue() { return value; } + @Override public String toString() { return "WithValue " + value; } + } + + public static WithValue make(int value) { + return new WithValue(value); + } + + public static Matcher<WithValue> value(int value) { + return new FeatureMatcher<WithValue, Integer>(equalTo(value), "value with", "value") { + @Override protected Integer featureValueOf(WithValue actual) { return actual.getValue(); } + }; + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInRelativeOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInRelativeOrderTest.java new file mode 100644 index 0000000..8192c8b --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableContainingInRelativeOrderTest.java @@ -0,0 +1,93 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.FeatureMatcher; +import org.hamcrest.Matcher; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.hamcrest.collection.IsIterableContainingInRelativeOrder.containsInRelativeOrder; +import static org.hamcrest.core.IsEqual.equalTo; + +@SuppressWarnings("unchecked") +public class IsIterableContainingInRelativeOrderTest extends AbstractMatcherTest { + // temporary hack until the Java type system works + private final Matcher<Iterable<? extends WithValue>> contains123 = containsInRelativeOrder(value(1), value(2), value(3)); + + @Override + protected Matcher<?> createMatcher() { + return containsInRelativeOrder(1, 2); + } + + public void testMatchingSingleItemIterable() throws Exception { + assertMatches("Single item iterable", containsInRelativeOrder(1), asList(1)); + } + + public void testMatchingMultipleItemIterable() throws Exception { + assertMatches("Multiple item iterable", containsInRelativeOrder(1, 2, 3), asList(1, 2, 3)); + } + + public void testMatchesWithMoreElementsThanExpectedAtBeginning() throws Exception { + assertMatches("More elements at beginning", containsInRelativeOrder(2, 3, 4), asList(1, 2, 3, 4)); + } + + public void testMatchesWithMoreElementsThanExpectedAtEnd() throws Exception { + assertMatches("More elements at end", containsInRelativeOrder(1, 2, 3), asList(1, 2, 3, 4)); + } + + public void testMatchesWithMoreElementsThanExpectedInBetween() throws Exception { + assertMatches("More elements in between", containsInRelativeOrder(1, 3), asList(1, 2, 3)); + } + + public void testMatchesSubSection() throws Exception { + assertMatches("Sub section of iterable", containsInRelativeOrder(2, 3), asList(1, 2, 3, 4)); + } + + public void testMatchesWithSingleGapAndNotFirstOrLast() throws Exception { + assertMatches("Sub section with single gaps without a first or last match", containsInRelativeOrder(2, 4), asList(1, 2, 3, 4, 5)); + } + + public void testMatchingSubSectionWithManyGaps() throws Exception { + assertMatches("Sub section with many gaps iterable", containsInRelativeOrder(2, 4, 6), asList(1, 2, 3, 4, 5, 6, 7)); + } + + public void testDoesNotMatchWithFewerElementsThanExpected() throws Exception { + List<WithValue> valueList = asList(make(1), make(2)); + assertMismatchDescription("value with <3> was not found after <WithValue 2>", contains123, valueList); + } + + public void testDoesNotMatchIfSingleItemNotFound() throws Exception { + assertMismatchDescription("value with <4> was not found", containsInRelativeOrder(value(4)), asList(make(3))); + } + + public void testDoesNotMatchIfOneOfMultipleItemsNotFound() throws Exception { + assertMismatchDescription("value with <3> was not found after <WithValue 2>", contains123, asList(make(1), make(2), make(4))); + } + + public void testDoesNotMatchEmptyIterable() throws Exception { + assertMismatchDescription("value with <4> was not found", containsInRelativeOrder(value(4)), new ArrayList<WithValue>()); + } + + public void testHasAReadableDescription() { + assertDescription("iterable containing [<1>, <2>] in relative order", containsInRelativeOrder(1, 2)); + } + + public static class WithValue { + private final int value; + public WithValue(int value) { this.value = value; } + public int getValue() { return value; } + @Override public String toString() { return "WithValue " + value; } + } + + public static WithValue make(int value) { + return new WithValue(value); + } + + public static Matcher<WithValue> value(int value) { + return new FeatureMatcher<WithValue, Integer>(equalTo(value), "value with", "value") { + @Override protected Integer featureValueOf(WithValue actual) { return actual.getValue(); } + }; + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableWithSizeTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableWithSizeTest.java new file mode 100644 index 0000000..8bf65d1 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsIterableWithSizeTest.java @@ -0,0 +1,37 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.util.Arrays; +import java.util.Collections; + +import static org.hamcrest.collection.IsIterableWithSize.iterableWithSize; + +public class IsIterableWithSizeTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return iterableWithSize(7); + } + + public void testMatchesEmptyIterable() throws Exception { + assertMatches("Empty iterable", iterableWithSize(0), Collections.emptyList()); + } + + public void testMatchingSingleItemIterable() throws Exception { + assertMatches("Single item iterable", iterableWithSize(1), Arrays.<Object>asList(1)); + } + + public void testMatchingMultipleItemIterable() throws Exception { + assertMatches("Multiple item iterable", iterableWithSize(3), Arrays.<Object>asList(1, 2, 3)); + } + + public void testDoesNotMatchIncorrectSize() throws Exception { + assertDoesNotMatch("Incorrect size", iterableWithSize(3), Arrays.<Object>asList(1)); + } + + public void testHasAReadableDescription() { + assertDescription("an iterable with size <4>", iterableWithSize(4)); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingKeyTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingKeyTest.java new file mode 100644 index 0000000..13f067c --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingKeyTest.java @@ -0,0 +1,84 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsMapContaining.hasKey; + +public class IsMapContainingKeyTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return hasKey("foo"); + } + + public void testMatchesSingletonMapContainingKey() { + Map<String,Integer> map = new HashMap<String, Integer>(); + map.put("a", 1); + + assertMatches("Matches single key", hasKey("a"), map); + } + + public void testMatchesMapContainingKey() { + Map<String,Integer> map = new HashMap<String, Integer>(); + map.put("a", 1); + map.put("b", 2); + map.put("c", 3); + + assertMatches("Matches a", hasKey("a"), map); + assertMatches("Matches c", hasKey("c"), map); + } + + +// No longer compiles +// public void testMatchesMapContainingKeyWithNoGenerics() { +// Map map = new HashMap(); +// map.put("a", 1); +// map.put("b", 2); +// map.put("c", 3); +// +// assertMatches("Matches a", hasKey("a"), map); +// assertMatches("Matches c", hasKey("c"), map); +// } + + public void testMatchesMapContainingKeyWithIntegerKeys() throws Exception { + Map<Integer, String> map = new HashMap<Integer, String>(); + map.put(1, "A"); + map.put(2, "B"); + + assertThat(map, hasKey(1)); + } + + public void testMatchesMapContainingKeyWithNumberKeys() throws Exception { + Map<Number, String> map = new HashMap<Number, String>(); + map.put(1, "A"); + map.put(2, "B"); + + assertThat(map, hasKey((Number)1)); + + // TODO: work out the correct sprinkling of wildcards to get this to work! +// assertThat(map, hasKey(1)); + } + + public void testHasReadableDescription() { + assertDescription("map containing [\"a\"->ANYTHING]", hasKey("a")); + } + + public void testDoesNotMatchEmptyMap() { + assertMismatchDescription("map was []", hasKey("Foo"), new HashMap<String,Integer>()); + } + + public void testDoesNotMatchMapMissingKey() { + Map<String,Integer> map = new TreeMap<String, Integer>(); + map.put("a", 1); + map.put("b", 2); + map.put("c", 3); + + assertMismatchDescription("map was [<a=1>, <b=2>, <c=3>]", hasKey("d"), map); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingTest.java new file mode 100644 index 0000000..f472224 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingTest.java @@ -0,0 +1,58 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.util.Map; +import java.util.TreeMap; + +import static org.hamcrest.collection.IsMapContaining.hasEntry; +import static org.hamcrest.core.IsAnything.anything; +import static org.hamcrest.core.IsEqual.equalTo; + +public class IsMapContainingTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return IsMapContaining.hasEntry("irrelevant", "irrelevant"); + } + + public void testMatchesMapContainingMatchingKeyAndValue() { + Map<String,Integer> map = new TreeMap<String,Integer>(); + map.put("a", 1); + map.put("b", 2); + + assertMatches("matcherA", hasEntry(equalTo("a"), equalTo(1)), map); + assertMatches("matcherB", hasEntry(equalTo("b"), equalTo(2)), map); + assertMismatchDescription("map was [<a=1>, <b=2>]", hasEntry(equalTo("c"), equalTo(3)), map); + } + +// no longer compiles. SF +// public void testMatchesMapContainingMatchingKeyAndValueWithoutGenerics() { +// Map map = new HashMap(); +// map.put("a", 1); +// map.put("b", 2); +// +// assertMatches("matcherA", hasEntry(equalTo("a"), equalTo(1)), map); +// assertMatches("matcherB", hasEntry(equalTo("b"), equalTo(2)), map); +// assertDoesNotMatch("matcherC", hasEntry(equalTo("c"), equalTo(3)), map); +// } +// + public void testDoesNotMatchNull() { + assertMismatchDescription("was null", hasEntry(anything(), anything()), null); + } + + public void testHasReadableDescription() { + assertDescription("map containing [\"a\"-><2>]", hasEntry(equalTo("a"), (equalTo(2)))); + } + + // Remaining code no longer compiles, thanks to generics. I think that's a good thing, but + // I still need to investigate how this behaves with code that doesn't use generics. + // I expect ClassCastExceptions will be thrown. + // -Joe. + +// public void testDoesNotMatchAnObjectThatIsNotAMap() { +// assertDoesNotMatch("should not matches a string", +// mapContaining(ANYTHING, ANYTHING), "not a map"); +// } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingValueTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingValueTest.java new file mode 100644 index 0000000..a2d7f90 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapContainingValueTest.java @@ -0,0 +1,46 @@ +package org.hamcrest.collection; + + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import static org.hamcrest.collection.IsMapContaining.hasValue; + +public class IsMapContainingValueTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return hasValue("foo"); + } + + public void testHasReadableDescription() { + assertDescription("map containing [ANYTHING->\"a\"]", hasValue("a")); + } + + public void testDoesNotMatchEmptyMap() { + Map<String,Integer> map = new HashMap<String,Integer>(); + assertMismatchDescription("map was []", hasValue(1), map); + } + + public void testMatchesSingletonMapContainingValue() { + Map<String,Integer> map = new HashMap<String,Integer>(); + map.put("a", 1); + + assertMatches("Singleton map", hasValue(1), map); + } + + public void testMatchesMapContainingValue() { + Map<String,Integer> map = new TreeMap<String,Integer>(); + map.put("a", 1); + map.put("b", 2); + map.put("c", 3); + + assertMatches("hasValue 1", hasValue(1), map); + assertMatches("hasValue 3", hasValue(3), map); + assertMismatchDescription("map was [<a=1>, <b=2>, <c=3>]", hasValue(4), map); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapWithSizeTest.java b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapWithSizeTest.java new file mode 100644 index 0000000..c050924 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/collection/IsMapWithSizeTest.java @@ -0,0 +1,82 @@ +package org.hamcrest.collection; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; +import org.hamcrest.MatcherAssert; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.collection.IsMapWithSize.aMapWithSize; +import static org.hamcrest.core.IsEqual.equalTo; + +public final class IsMapWithSizeTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return aMapWithSize(7); + } + + public void testMatchesWhenSizeIsCorrect() { + assertMatches("correct size", aMapWithSize(equalTo(2)), mapWithKeys("a", "b")); + assertMismatchDescription("map size was <3>", aMapWithSize(equalTo(2)), mapWithKeys("a", "b", "c")); + } + + public void testMatchesMapWhenSizeIsCorrectUsingObjectElementType() { + Map<Object, Object> map = mapWithKeys(new Object(), new Object()); + assertMatches("correct size", aMapWithSize(equalTo(2)), map); + assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), map); + } + + public void testMatchesMapWhenSizeIsCorrectUsingStringElementType() { + Map<String, Integer> map = mapWithKeys("a", "b"); + assertMatches("correct size", aMapWithSize(equalTo(2)), map); + assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), map); + } + + public void testMatchesMapWhenSizeIsCorrectUsingWildcardElementType() { + Map<?, ?> map = mapWithKeys("a", "b"); + assertMatches("correct size", aMapWithSize(equalTo(2)), map); + assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), map); + } + + public void testMatchesListWhenSizeIsCorrectUsingObjectElementType() { + Map<Object, Object> map = mapWithKeys(new Object(), new Object()); + assertMatches("correct size", aMapWithSize(equalTo(2)), map); + assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), map); + } + + public void testMatchesListWhenSizeIsCorrectUsingStringElementType() { + Map<String, Integer> list = mapWithKeys("a", "b"); + assertMatches("correct size", aMapWithSize(equalTo(2)), list); + assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), list); + } + + public void testMatchesListWhenSizeIsCorrectUsingWildcardElementType() { + Map<?, ?> list = mapWithKeys("a", "b"); + assertMatches("correct size", aMapWithSize(equalTo(2)), list); + assertMismatchDescription("map size was <2>", aMapWithSize(equalTo(3)), list); + } + + public void testProvidesConvenientShortcutForHasSizeEqualTo() { + assertMatches("correct size", aMapWithSize(2), mapWithKeys(new Object(), new Object())); + assertMismatchDescription("map size was <3>", aMapWithSize(2), mapWithKeys(new Object(), new Object(), new Object())); + } + + public void testHasAReadableDescription() { + assertDescription("a map with size <3>", aMapWithSize(equalTo(3))); + } + + public void testCompilesWithATypedMap() { + Map<String, Integer> arrayList = new HashMap<String, Integer>(); + MatcherAssert.assertThat(arrayList, aMapWithSize(0)); + } + + private static <K, V> Map<K, V> mapWithKeys(K... keys) { + final Map<K, V> result = new HashMap<K, V>(); + for (K key : keys) { + result.put(key, null); + } + return result; + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherBuilderTest.java b/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherBuilderTest.java new file mode 100644 index 0000000..a5fdb4a --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherBuilderTest.java @@ -0,0 +1,128 @@ +package org.hamcrest.comparator; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.math.BigDecimal; +import java.util.Comparator; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.comparator.ComparatorMatcherBuilder.comparedBy; +import static org.hamcrest.core.IsNot.not; + +public class ComparatorMatcherBuilderTest extends AbstractMatcherTest { + + private final ComparatorMatcherBuilder<Integer> integerComparatorMatcherBuilder = ComparatorMatcherBuilder.usingNaturalOrdering(); + private final ComparatorMatcherBuilder<Double> doubleComparatorMatcherBuilder = ComparatorMatcherBuilder.usingNaturalOrdering(); + private final ComparatorMatcherBuilder<String> stringComparatorMatcherBuilder = ComparatorMatcherBuilder.usingNaturalOrdering(); + private final ComparatorMatcherBuilder<BigDecimal> bigDecimalComparatorMatcherBuilder = ComparatorMatcherBuilder.usingNaturalOrdering(); + private final Comparator<Integer> backwardsIntegerComparator = new Comparator<Integer>() { + @Override + public int compare(Integer o1, Integer o2) { + return -o1.compareTo(o2); + } + + @Override + public String toString() { + return "backwards integer comparator"; + } + }; + + @Override + protected Matcher<Integer> createMatcher() { + return integerComparatorMatcherBuilder.greaterThan(1); + } + + public void testDescription() { + assertDescription("a value greater than <1>", integerComparatorMatcherBuilder.greaterThan(1)); + assertDescription("a value equal to or greater than <1>", integerComparatorMatcherBuilder.greaterThanOrEqualTo(1)); + assertDescription("a value equal to <1>", integerComparatorMatcherBuilder.comparesEqualTo(1)); + assertDescription("a value less than or equal to <1>", integerComparatorMatcherBuilder.lessThanOrEqualTo(1)); + assertDescription("a value less than <1>", integerComparatorMatcherBuilder.lessThan(1)); + + assertDescription("a value greater than <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).greaterThan(1)); + assertDescription("a value equal to or greater than <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).greaterThanOrEqualTo(1)); + assertDescription("a value equal to <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).comparesEqualTo(1)); + assertDescription("a value less than or equal to <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).lessThanOrEqualTo(1)); + assertDescription("a value less than <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).lessThan(1)); + } + + public void testMismatchDescriptions() { + assertMismatchDescription("<0> was less than <1>", integerComparatorMatcherBuilder.greaterThan(1), 0); + assertMismatchDescription("<1> was equal to <1>", integerComparatorMatcherBuilder.greaterThan(1), 1); + assertMismatchDescription("<1> was greater than <0>", integerComparatorMatcherBuilder.lessThan(0), 1); + assertMismatchDescription("<2> was equal to <2>", integerComparatorMatcherBuilder.lessThan(2), 2); + + assertMismatchDescription("<1> was less than <0> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).greaterThan(0), 1); + assertMismatchDescription("<1> was equal to <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).greaterThan(1), 1); + assertMismatchDescription("<0> was greater than <1> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).lessThan(1), 0); + assertMismatchDescription("<2> was equal to <2> when compared by <backwards integer comparator>", comparedBy(backwardsIntegerComparator).lessThan(2), 2); + } + + public void testComparesObjectsForGreaterThan() { + assertThat(2, integerComparatorMatcherBuilder.greaterThan(1)); + assertThat(0, not(integerComparatorMatcherBuilder.greaterThan(1))); + } + + public void testComparesObjectsForLessThan() { + assertThat(2, integerComparatorMatcherBuilder.lessThan(3)); + assertThat(0, integerComparatorMatcherBuilder.lessThan(1)); + } + + + public void testComparesObjectsForEquality() { + assertThat(3, integerComparatorMatcherBuilder.comparesEqualTo(3)); + assertThat("aa", stringComparatorMatcherBuilder.comparesEqualTo("aa")); + } + + public void testAllowsForInclusiveComparisons() { + assertThat("less", 1, integerComparatorMatcherBuilder.lessThanOrEqualTo(1)); + assertThat("greater", 1, integerComparatorMatcherBuilder.greaterThanOrEqualTo(1)); + } + + public void testSupportsDifferentTypesOfComparableObjects() { + assertThat(1.1, doubleComparatorMatcherBuilder.greaterThan(1.0)); + assertThat("cc", stringComparatorMatcherBuilder.greaterThan("bb")); + } + + public void testComparesBigDecimalsWithDifferentScalesCorrectlyForIssue20() { + assertThat(new BigDecimal("10.0"), bigDecimalComparatorMatcherBuilder.greaterThanOrEqualTo(new BigDecimal("10"))); + assertThat(new BigDecimal(10), bigDecimalComparatorMatcherBuilder.greaterThanOrEqualTo(new BigDecimal("10.0"))); + assertThat(new BigDecimal("2"), bigDecimalComparatorMatcherBuilder.comparesEqualTo(new BigDecimal("2.000"))); + } + + public void testComparesCustomTypesWhoseCompareToReturnsValuesGreaterThatOne() { + assertThat(new CustomInt(5), ComparatorMatcherBuilder.<CustomInt>usingNaturalOrdering().lessThan(new CustomInt(10))); + } + + public void testComparesByCustomComparator() { + assertThat(5, comparedBy(backwardsIntegerComparator).lessThan(4)); + } + + public void testJavadocExamples() { + assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().comparesEqualTo(1)); + assertThat(2, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().greaterThan(1)); + assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().greaterThanOrEqualTo(1)); + assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThan(2)); + assertThat(1, ComparatorMatcherBuilder.<Integer>usingNaturalOrdering().lessThanOrEqualTo(1)); + assertThat(5, comparedBy(new Comparator<Integer>() { + @Override + public int compare(Integer o1, Integer o2) { + return -o1.compareTo(o2); + } + }).lessThan(4)); + } + + private static final class CustomInt implements Comparable<CustomInt> { + private final int value; + + public CustomInt(int value) { + this.value = value; + } + + @Override + public int compareTo(CustomInt other) { + return value - other.value; + } + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherTest.java b/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherTest.java new file mode 100644 index 0000000..2bc53d4 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/comparator/ComparatorMatcherTest.java @@ -0,0 +1,87 @@ +package org.hamcrest.comparator; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.math.BigDecimal; +import java.util.Comparator; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.number.OrderingComparison.*; + +public class ComparatorMatcherTest extends AbstractMatcherTest { + + @Override + protected Matcher<Integer> createMatcher() { + return ComparatorMatcherBuilder.comparedBy(new Comparator<Integer>() { + @Override + public int compare(Integer o1, Integer o2) { + return o1.compareTo(o2); + } + }).greaterThan(1); + } + + public void testDescription() { + assertDescription("a value greater than <1>", greaterThan(1)); + assertDescription("a value equal to or greater than <1>", greaterThanOrEqualTo(1)); + assertDescription("a value equal to <1>", comparesEqualTo(1)); + assertDescription("a value less than or equal to <1>", lessThanOrEqualTo(1)); + assertDescription("a value less than <1>", lessThan(1)); + } + + public void testMismatchDescriptions() { + assertMismatchDescription("<0> was less than <1>", greaterThan(1), 0); + assertMismatchDescription("<1> was equal to <1>", greaterThan(1), 1); + assertMismatchDescription("<1> was greater than <0>", lessThan(0), 1); + assertMismatchDescription("<2> was equal to <2>", lessThan(2), 2); + } + + public void testComparesObjectsForGreaterThan() { + assertThat(2, greaterThan(1)); + assertThat(0, not(greaterThan(1))); + } + + public void testComparesObjectsForLessThan() { + assertThat(2, lessThan(3)); + assertThat(0, lessThan(1)); + } + + + public void testComparesObjectsForEquality() { + assertThat(3, comparesEqualTo(3)); + assertThat("aa", comparesEqualTo("aa")); + } + + public void testAllowsForInclusiveComparisons() { + assertThat("less", 1, lessThanOrEqualTo(1)); + assertThat("greater", 1, greaterThanOrEqualTo(1)); + } + + public void testSupportsDifferentTypesOfComparableObjects() { + assertThat(1.1, greaterThan(1.0)); + assertThat("cc", greaterThan("bb")); + } + + public void testComparesBigDecimalsWithDifferentScalesCorrectlyForIssue20() { + assertThat(new BigDecimal("10.0"), greaterThanOrEqualTo(new BigDecimal("10"))); + assertThat(new BigDecimal(10), greaterThanOrEqualTo(new BigDecimal("10.0"))); + assertThat(new BigDecimal("2"), comparesEqualTo(new BigDecimal("2.000"))); + } + + public void testComparesCustomTypesWhoseCompareToReturnsValuesGreaterThatOne() { + assertThat(new CustomInt(5), lessThan(new CustomInt(10))); + } + + private static final class CustomInt implements Comparable<CustomInt> { + private final int value; + + public CustomInt(int value) { + this.value = value; + } + + public int compareTo(CustomInt other) { + return value - other.value; + } + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/io/FileMatchersTest.java b/hamcrest-library/src/test/java/org/hamcrest/io/FileMatchersTest.java new file mode 100644 index 0000000..b186549 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/io/FileMatchersTest.java @@ -0,0 +1,93 @@ +package org.hamcrest.io; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.io.File; + +import static org.hamcrest.core.IsEqual.equalTo; + +@SuppressWarnings("ResultOfMethodCallIgnored") +public class FileMatchersTest extends AbstractMatcherTest { + + private File directory; + private File file; + + @Override + protected void setUp() throws Exception { + directory = File.createTempFile("myDir", ""); + directory.delete(); + directory.mkdirs(); + + file = new File(directory, "myFile"); + file.createNewFile(); + } + + public void testAnExistingDirectory() { + assertMatches("matches existing directory", FileMatchers.anExistingDirectory(), directory); + assertDoesNotMatch("doesn't match existing file", FileMatchers.anExistingDirectory(), file); + assertDoesNotMatch("doesn't match missing file", FileMatchers.anExistingDirectory(), new File("foo")); + } + + public void testAnExistingFileOrDirectory() { + assertMatches("matches existing file", FileMatchers.anExistingFileOrDirectory(), file); + assertMatches("matches existing directory", FileMatchers.anExistingFileOrDirectory(), directory); + assertDoesNotMatch("doesn't match missing file", FileMatchers.anExistingFileOrDirectory(), new File("foo")); + } + + public void testAnExistingFile() { + assertMatches("matches existing file", FileMatchers.anExistingFile(), file); + assertDoesNotMatch("doesn't match existing directory", FileMatchers.anExistingFile(), directory); + assertDoesNotMatch("doesn't match missing file", FileMatchers.anExistingFile(), new File("foo")); + } + + public void testAReadableFile() { + file.setReadable(true); + assertMatches("matches readable file", FileMatchers.aReadableFile(), file); + if (file.setReadable(false)) { + assertDoesNotMatch("doesn't match unreadable file", FileMatchers.aReadableFile(), file); + } + } + + public void testAWritableFile() { + assertMatches("matches writable file", FileMatchers.aWritableFile(), file); + file.setWritable(false); + assertDoesNotMatch("doesn't match unwritable file", FileMatchers.aWritableFile(), file); + } + + public void testAFileWithSizeLong() { + assertMatches("matches file size", FileMatchers.aFileWithSize(0L), file); + file.setWritable(false); + assertDoesNotMatch("doesn't match incorrect file size", FileMatchers.aFileWithSize(34L), file); + } + + public void testAFileWithSizeMatcherOfLong() { + assertMatches("matches file size", FileMatchers.aFileWithSize(equalTo(0L)), file); + file.setWritable(false); + assertDoesNotMatch("doesn't match incorrect file size", FileMatchers.aFileWithSize(equalTo(23L)), file); + } + + public void testAFileNamed() { + assertMatches("matches file name", FileMatchers.aFileNamed(equalTo(file.getName())), file); + file.setWritable(false); + assertDoesNotMatch("doesn't match incorrect file name", FileMatchers.aFileNamed(equalTo("foo")), file); + } + + public void testAFileWithCanonicalPath() throws Exception { + assertMatches("matches file canonical path", FileMatchers.aFileWithCanonicalPath(equalTo(file.getCanonicalPath())), file); + file.setWritable(false); + assertDoesNotMatch("doesn't match incorrect canonical path", FileMatchers.aFileWithCanonicalPath(equalTo("foo")), file); + } + + public void testAFileWithAbsolutePath() { + assertMatches("matches file absolute path", FileMatchers.aFileWithAbsolutePath(equalTo(file.getAbsolutePath())), file); + file.setWritable(false); + assertDoesNotMatch("doesn't match incorrect absolute path", FileMatchers.aFileWithAbsolutePath(equalTo("foo")), file); + } + + @Override + protected Matcher<?> createMatcher() { + return FileMatchers.aFileWithSize(1L); + } + +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/number/BigDecimalCloseToTest.java b/hamcrest-library/src/test/java/org/hamcrest/number/BigDecimalCloseToTest.java new file mode 100644 index 0000000..c82e6f4 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/number/BigDecimalCloseToTest.java @@ -0,0 +1,45 @@ +package org.hamcrest.number; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.math.BigDecimal; + +import static org.hamcrest.number.BigDecimalCloseTo.closeTo; + +public class BigDecimalCloseToTest extends AbstractMatcherTest { + private final Matcher<BigDecimal> matcher = closeTo(new BigDecimal("1.0"), new BigDecimal("0.5")); + + @Override + protected Matcher<?> createMatcher() { + BigDecimal irrelevant = new BigDecimal("0.01"); + return closeTo(irrelevant, irrelevant); + } + + public void testEvaluatesToTrueIfArgumentIsEqualToABigDecimalWithinSomeError() { + assertTrue(matcher.matches(new BigDecimal("1.0"))); + assertTrue(matcher.matches(new BigDecimal("0.5"))); + assertTrue(matcher.matches(new BigDecimal("1.5"))); + + assertDoesNotMatch("too large", matcher, new BigDecimal("2.0")); + assertMismatchDescription("<2.0> differed by <0.5> more than delta <0.5>", matcher, new BigDecimal("2.0")); + assertDoesNotMatch("number too small", matcher, new BigDecimal("0.0")); + assertMismatchDescription("<0.0> differed by <0.5> more than delta <0.5>", matcher, new BigDecimal("0.0")); + } + + public void testEvaluatesToTrueIfArgumentHasDifferentScale() { + assertTrue(matcher.matches(new BigDecimal("1.000000"))); + assertTrue(matcher.matches(new BigDecimal("0.500000"))); + assertTrue(matcher.matches(new BigDecimal("1.500000"))); + + assertDoesNotMatch("too large", matcher, new BigDecimal("2.000000")); + assertMismatchDescription("<2.000000> differed by <0.5> more than delta <0.5>", matcher, new BigDecimal("2.000000")); + assertDoesNotMatch("number too small", matcher, new BigDecimal("0.000000")); + assertMismatchDescription("<0.000000> differed by <0.5> more than delta <0.5>", matcher, new BigDecimal("0.000000")); + } + + public void test_is_self_describing() { + assertDescription("a numeric value within <0.5> of <1.0>", matcher); + } + +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/number/IsCloseToTest.java b/hamcrest-library/src/test/java/org/hamcrest/number/IsCloseToTest.java new file mode 100644 index 0000000..8b0e244 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/number/IsCloseToTest.java @@ -0,0 +1,32 @@ +package org.hamcrest.number; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.number.IsCloseTo.closeTo; + +public class IsCloseToTest extends AbstractMatcherTest { + private final Matcher<Double> matcher = closeTo(1.0d, 0.5d); + + @Override + protected Matcher<?> createMatcher() { + final double irrelevant = 0.1; + return closeTo(irrelevant, irrelevant); + } + + public void test_matchesIfArgumentIsEqualToADoubleValueWithinSomeError() { + assertMatches("1.0", matcher, 1.0); + assertMatches("0.5d", matcher, 0.5d); + assertMatches("1.5d", matcher, 1.5d); + + assertDoesNotMatch("too large", matcher, 2.0); + assertMismatchDescription("<3.0> differed by <1.5> more than delta <0.5>", matcher, 3.0d); + assertDoesNotMatch("number too small", matcher, 0.0); + assertMismatchDescription("<0.1> differed by <0.4> more than delta <0.5>", matcher, 0.1); + } + + public void test_is_self_describing() { + assertDescription("a numeric value within <0.5> of <1.0>", matcher); + } + +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/number/IsNanTest.java b/hamcrest-library/src/test/java/org/hamcrest/number/IsNanTest.java new file mode 100644 index 0000000..c9b3956 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/number/IsNanTest.java @@ -0,0 +1,43 @@ +package org.hamcrest.number; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.number.IsNaN.notANumber; + +public final class IsNanTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<Double> matcher = notANumber(); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + matchesNaN() { + assertMatches(notANumber(), Double.NaN); + } + + @Test public void + doesNotMatchDoubleValue() { + assertDoesNotMatch(notANumber(), 1.25); + } + + @Test public void + doesNotMatchInfinity() { + assertDoesNotMatch(notANumber(), Double.POSITIVE_INFINITY); + } + + @Test public void + describesItself() { + assertDescription("a double value of NaN", notANumber()); + } + + @Test public void + describesAMismatch() { + assertMismatchDescription("was <1.25>", notANumber(), 1.25); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/number/OrderingComparisonTest.java b/hamcrest-library/src/test/java/org/hamcrest/number/OrderingComparisonTest.java new file mode 100644 index 0000000..5953bd0 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/number/OrderingComparisonTest.java @@ -0,0 +1,80 @@ +package org.hamcrest.number; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.math.BigDecimal; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.number.OrderingComparison.*; + +public class OrderingComparisonTest extends AbstractMatcherTest { + + @Override + protected Matcher<Integer> createMatcher() { + return greaterThan(1); + } + + public void testDescription() { + assertDescription("a value greater than <1>", greaterThan(1)); + assertDescription("a value equal to or greater than <1>", greaterThanOrEqualTo(1)); + assertDescription("a value equal to <1>", comparesEqualTo(1)); + assertDescription("a value less than or equal to <1>", lessThanOrEqualTo(1)); + assertDescription("a value less than <1>", lessThan(1)); + } + + public void testMismatchDescriptions() { + assertMismatchDescription("<0> was less than <1>", greaterThan(1), 0); + assertMismatchDescription("<1> was equal to <1>", greaterThan(1), 1); + assertMismatchDescription("<1> was greater than <0>", lessThan(0), 1); + assertMismatchDescription("<2> was equal to <2>", lessThan(2), 2); + } + + public void testComparesObjectsForGreaterThan() { + assertThat(2, greaterThan(1)); + assertThat(0, not(greaterThan(1))); + } + + public void testComparesObjectsForLessThan() { + assertThat(2, lessThan(3)); + assertThat(0, lessThan(1)); + } + + + public void testComparesObjectsForEquality() { + assertThat(3, comparesEqualTo(3)); + assertThat("aa", comparesEqualTo("aa")); + } + + public void testAllowsForInclusiveComparisons() { + assertThat("less", 1, lessThanOrEqualTo(1)); + assertThat("greater", 1, greaterThanOrEqualTo(1)); + } + + public void testSupportsDifferentTypesOfComparableObjects() { + assertThat(1.1, greaterThan(1.0)); + assertThat("cc", greaterThan("bb")); + } + + public void testComparesBigDecimalsWithDifferentScalesCorrectlyForIssue20() { + assertThat(new BigDecimal("10.0"), greaterThanOrEqualTo(new BigDecimal("10"))); + assertThat(new BigDecimal(10), greaterThanOrEqualTo(new BigDecimal("10.0"))); + assertThat(new BigDecimal("2"), comparesEqualTo(new BigDecimal("2.000"))); + } + + public void testComparesCustomTypesWhoseCompareToReturnsValuesGreaterThatOne() { + assertThat(new CustomInt(5), lessThan(new CustomInt(10))); + } + + private static final class CustomInt implements Comparable<CustomInt> { + private final int value; + public CustomInt(int value) { + this.value = value; + } + + public int compareTo(CustomInt other) { + return value - other.value; + } + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/object/HasToStringTest.java b/hamcrest-library/src/test/java/org/hamcrest/object/HasToStringTest.java new file mode 100644 index 0000000..5c75ae7 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/object/HasToStringTest.java @@ -0,0 +1,55 @@ +package org.hamcrest.object; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.object.HasToString.hasToString; + +public final class HasToStringTest { + private static final String TO_STRING_RESULT = "toString result"; + private static final Object TEST_OBJECT = new Object() { + @Override + public String toString() { + return TO_STRING_RESULT; + } + }; + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<Object> matcher = hasToString(equalTo("irrelevant")); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + matchesWhenUtilisingANestedMatcher() { + final Matcher<Object> matcher = hasToString(equalTo(TO_STRING_RESULT)); + + assertMatches(matcher, TEST_OBJECT); + assertDoesNotMatch(matcher, new Object()); + } + + @Test public void + matchesWhenUsingShortcutForHasToStringEqualTo() { + final Matcher<Object> matcher = hasToString(TO_STRING_RESULT); + + assertMatches(matcher, TEST_OBJECT); + assertDoesNotMatch(matcher, new Object()); + } + + @Test public void + describesItself() { + final Matcher<Object> matcher = hasToString(equalTo(TO_STRING_RESULT)); + assertDescription("with toString() \"toString result\"", matcher); + } + + @Test public void + describesAMismatch() { + final Matcher<Object> matcher = hasToString(equalTo(TO_STRING_RESULT)); + String expectedMismatchString = "toString() was \"Cheese\""; + assertMismatchDescription(expectedMismatchString, matcher, "Cheese"); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/object/IsCompatibleTypeTest.java b/hamcrest-library/src/test/java/org/hamcrest/object/IsCompatibleTypeTest.java new file mode 100644 index 0000000..8432fdb --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/object/IsCompatibleTypeTest.java @@ -0,0 +1,58 @@ +package org.hamcrest.object; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.object.IsCompatibleType.typeCompatibleWith; + +public class IsCompatibleTypeTest extends AbstractMatcherTest { + public static class BaseClass { + } + + public static class ExtendedClass extends BaseClass { + } + + public interface BaseInterface { + } + + public interface ExtendedInterface extends BaseInterface { + } + + public static class ClassImplementingBaseInterface implements BaseInterface { + } + + @Override + protected Matcher<?> createMatcher() { + return typeCompatibleWith(BaseClass.class); + } + + public void testMatchesSameClass() { + assertThat(BaseClass.class, typeCompatibleWith(BaseClass.class)); + } + + public void testMatchesSameInterface() { + assertThat(BaseInterface.class, typeCompatibleWith(BaseInterface.class)); + } + + public void testMatchesExtendedClass() { + assertThat(ExtendedClass.class, typeCompatibleWith(BaseClass.class)); + } + + public void testMatchesClassImplementingInterface() { + assertThat(ClassImplementingBaseInterface.class, typeCompatibleWith(BaseInterface.class)); + } + + public void testMatchesExtendedInterface() { + assertThat(ExtendedInterface.class, typeCompatibleWith(BaseInterface.class)); + } + +// public void testDoesNotMatchIncompatibleTypes() { +// assertThat(BaseClass.class, not(compatibleType(ExtendedClass.class))); +// assertThat(Integer.class, not(compatibleType(String.class))); +// } + + public void testHasReadableDescription() { + assertDescription("type < java.lang.Runnable", typeCompatibleWith(Runnable.class)); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/object/IsEventFromTest.java b/hamcrest-library/src/test/java/org/hamcrest/object/IsEventFromTest.java new file mode 100644 index 0000000..b3c4a3a --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/object/IsEventFromTest.java @@ -0,0 +1,52 @@ +package org.hamcrest.object; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import java.util.EventObject; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.object.IsEventFrom.eventFrom; + + +public class IsEventFromTest extends AbstractMatcherTest { + + @Override + protected Matcher<?> createMatcher() { + return eventFrom(null); + } + + public void testEvaluatesToTrueIfArgumentIsAnEventObjectFiredByASpecifiedSource() { + Object o = "Source"; + EventObject ev = new EventObject(o); + EventObject ev2 = new EventObject("source 2"); + + Matcher<EventObject> isEventMatcher = eventFrom(o); + + assertThat(ev, isEventMatcher); + assertMismatchDescription("source was \"source 2\"", isEventMatcher, ev2); + } + + private static class DerivedEvent extends EventObject { + private static final long serialVersionUID = 1L; + + public DerivedEvent(Object source) { + super(source); + } + } + + public void testCanTestForSpecificEventClasses() { + Object o = new Object(); + DerivedEvent goodEv = new DerivedEvent(o); + DerivedEvent wrongSource = new DerivedEvent("wrong source"); + EventObject wrongType = new EventObject(o); + EventObject wrongSourceAndType = new EventObject(new Object()); + + Matcher<EventObject> isEventMatcher = IsEventFrom.eventFrom(DerivedEvent.class, o); + + assertThat(goodEv, isEventMatcher); + assertMismatchDescription("source was \"wrong source\"", isEventMatcher, wrongSource); + assertMismatchDescription("item type was java.util.EventObject", isEventMatcher, wrongType); + assertMismatchDescription("item type was java.util.EventObject", isEventMatcher, wrongSourceAndType); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/object/MatchesPatternTest.java b/hamcrest-library/src/test/java/org/hamcrest/object/MatchesPatternTest.java new file mode 100644 index 0000000..3e2d911 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/object/MatchesPatternTest.java @@ -0,0 +1,59 @@ +package org.hamcrest.object; + +import org.hamcrest.Matcher; +import org.hamcrest.text.MatchesPattern; +import org.junit.Test; + +import java.util.regex.Pattern; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.junit.Assert.assertThat; + +public class MatchesPatternTest { + @Test + public void copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = new MatchesPattern(Pattern.compile(".")); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test + public void matchesExactString() { + assertThat("a", new MatchesPattern(Pattern.compile("a"))); + } + + @Test + public void doesNotMatchADifferentString() { + assertDoesNotMatch("A different string does not match", new MatchesPattern(Pattern.compile("a")), "b"); + } + + @Test + public void doesNotMatchSubstring() { + assertDoesNotMatch("A substring does not match", new MatchesPattern(Pattern.compile("a")), "ab"); + } + + @Test + public void hasAReadableDescription() { + Matcher<?> m = new MatchesPattern(Pattern.compile("a[bc](d|e)")); + assertDescription("a string matching the pattern 'a[bc](d|e)'", m ); + } + + @Test + public void describesAMismatch() { + final Matcher<String> matcher = new MatchesPattern(Pattern.compile("a")); + assertMismatchDescription("was \"Cheese\"", matcher, "Cheese"); + } + + @Test + public void factoryMethodAllowsCreationWithPattern() { + Matcher<?> m = MatchesPattern.matchesPattern(Pattern.compile("a[bc](d|e)")); + assertDescription("a string matching the pattern 'a[bc](d|e)'", m ); + } + + @Test + public void factoryMethodAllowsCreationWithString() { + Matcher<?> m = MatchesPattern.matchesPattern("a[bc](d|e)"); + assertDescription("a string matching the pattern 'a[bc](d|e)'", m ); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/IsBlankStringTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/IsBlankStringTest.java new file mode 100644 index 0000000..c5f35f1 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/text/IsBlankStringTest.java @@ -0,0 +1,55 @@ +package org.hamcrest.text; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.text.IsBlankString.blankOrNullString; +import static org.hamcrest.text.IsBlankString.blankString; + +public final class IsBlankStringTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = blankString(); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + matchesEmptyString() { + assertMatches(blankOrNullString(), ""); + assertMatches(blankString(), ""); + } + + @Test public void + matchesNullAppropriately() { + assertMatches(blankOrNullString(), null); + assertDoesNotMatch(blankString(), null); + } + + @Test public void + matchesBlankStringAppropriately() { + assertMatches(blankString(), " \t"); + assertMatches(blankOrNullString(), " \t"); + } + + @Test public void + doesNotMatchFilledString() { + assertDoesNotMatch(blankString(), "a"); + assertDoesNotMatch(blankOrNullString(), "a"); + } + + @Test public void + describesItself() { + assertDescription("a blank string", blankString()); + assertDescription("(null or a blank string)", blankOrNullString()); + } + + @Test public void + describesAMismatch() { + assertMismatchDescription("was \"a\"", blankString(), "a"); + assertMismatchDescription("was \"a\"", blankOrNullString(), "a"); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/IsEmptyStringTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/IsEmptyStringTest.java new file mode 100644 index 0000000..62e3053 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/text/IsEmptyStringTest.java @@ -0,0 +1,55 @@ +package org.hamcrest.text; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.text.IsEmptyString.emptyOrNullString; +import static org.hamcrest.text.IsEmptyString.emptyString; + +public final class IsEmptyStringTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = emptyString(); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + matchesEmptyString() { + assertMatches(emptyOrNullString(), ""); + assertMatches(emptyString(), ""); + } + + @Test public void + matchesNullAppropriately() { + assertMatches(emptyOrNullString(), null); + assertDoesNotMatch(emptyString(), null); + } + + @Test public void + matchesBlankStringAppropriately() { + assertDoesNotMatch(emptyString(), " "); + assertDoesNotMatch(emptyOrNullString(), " "); + } + + @Test public void + doesNotMatchFilledString() { + assertDoesNotMatch(emptyString(), "a"); + assertDoesNotMatch(emptyOrNullString(), "a"); + } + + @Test public void + describesItself() { + assertDescription("an empty string", emptyString()); + assertDescription("(null or an empty string)", emptyOrNullString()); + } + + @Test public void + describesAMismatch() { + assertMismatchDescription("was \"a\"", emptyString(), "a"); + assertMismatchDescription("was \"a\"", emptyOrNullString(), "a"); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringCaseTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringCaseTest.java new file mode 100644 index 0000000..4800f43 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringCaseTest.java @@ -0,0 +1,62 @@ +package org.hamcrest.text; + +import org.hamcrest.Matcher; +import org.junit.Test; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase; + +public final class IsEqualIgnoringCaseTest { + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<String> matcher = equalToIgnoringCase("irrelevant"); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + ignoresCaseOfCharsInString() { + final Matcher<String> matcher = equalToIgnoringCase("heLLo"); + + assertMatches(matcher, "HELLO"); + assertMatches(matcher, "hello"); + assertMatches(matcher, "HelLo"); + assertDoesNotMatch(matcher, "bye"); + } + + @Test public void + mismatchesIfAdditionalWhitespaceIsPresent() { + final Matcher<String> matcher = equalToIgnoringCase("heLLo"); + + assertDoesNotMatch(matcher, "hello "); + assertDoesNotMatch(matcher, " hello"); + } + + @Test public void + mismatchesNull() { + final Matcher<String> matcher = equalToIgnoringCase("heLLo"); + + assertDoesNotMatch(matcher, null); + } + + @Test(expected=IllegalArgumentException.class) public void + canOnlyBeConstructedAboutANonNullString() { + equalToIgnoringCase(null); + } + + + @Test public void + describesItself() { + final Matcher<String> matcher = equalToIgnoringCase("heLLo"); + assertDescription("equalToIgnoringCase(\"heLLo\")", matcher); + } + + @Test public void + describesAMismatch() { + final Matcher<String> matcher = equalToIgnoringCase("heLLo"); + String expectedMismatchString = "was \"Cheese\""; + assertMismatchDescription(expectedMismatchString, matcher, "Cheese"); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringWhiteSpaceTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringWhiteSpaceTest.java new file mode 100644 index 0000000..d5c7576 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/text/IsEqualIgnoringWhiteSpaceTest.java @@ -0,0 +1,51 @@ +package org.hamcrest.text; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.text.IsEqualIgnoringWhiteSpace.equalToIgnoringWhiteSpace; + +public class IsEqualIgnoringWhiteSpaceTest extends AbstractMatcherTest { + + private final Matcher<String> matcher = equalToIgnoringWhiteSpace("Hello World how\n are we? "); + + @Override + protected Matcher<?> createMatcher() { + return matcher; + } + + public void testPassesIfWordsAreSameButWhitespaceDiffers() { + assertThat("Hello World how are we?", matcher); + assertThat(" Hello World how are \n\n\twe?", matcher); + } + + public void testFailsIfTextOtherThanWhitespaceDiffers() { + assertThat("Hello PLANET how are we?", not(matcher)); + assertThat("Hello World how are we", not(matcher)); + } + + public void testFailsIfWhitespaceIsAddedOrRemovedInMidWord() { + assertThat("HelloWorld how are we?", not(matcher)); + assertThat("Hello Wo rld how are we?", not(matcher)); + } + + public void testFailsIfMatchingAgainstNull() { + assertThat(null, not(matcher)); + } + + public void testRequiresNonNullStringToBeConstructed() { + try { + new IsEqualIgnoringWhiteSpace(null); + fail("Expected exception"); + } catch (IllegalArgumentException goodException) { + // expected! + } + } + + public void testHasAReadableDescription() { + assertDescription("equalToIgnoringWhiteSpace(\"Hello World how\\n are we? \")", + matcher); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/text/StringContainsInOrderTest.java b/hamcrest-library/src/test/java/org/hamcrest/text/StringContainsInOrderTest.java new file mode 100644 index 0000000..8ffbc67 --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/text/StringContainsInOrderTest.java @@ -0,0 +1,30 @@ +package org.hamcrest.text; + +import org.hamcrest.AbstractMatcherTest; +import org.hamcrest.Matcher; + +import static java.util.Arrays.asList; + + +public class StringContainsInOrderTest extends AbstractMatcherTest { + StringContainsInOrder m = new StringContainsInOrder(asList("a", "b", "c")); + + @Override + protected Matcher<?> createMatcher() { + return m; + } + + public void testMatchesOnlyIfStringContainsGivenSubstringsInTheSameOrder() { + assertMatches("substrings in order", m, "abc"); + assertMatches("substrings separated", m, "1a2b3c4"); + + assertDoesNotMatch("substrings out of order", m, "cab"); + assertDoesNotMatch("no substrings in string", m, "xyz"); + assertDoesNotMatch("substring missing", m, "ac"); + assertDoesNotMatch("empty string", m, ""); + } + + public void testHasAReadableDescription() { + assertDescription("a string containing \"a\", \"b\", \"c\" in order", m); + } +} diff --git a/hamcrest-library/src/test/java/org/hamcrest/xml/HasXPathTest.java b/hamcrest-library/src/test/java/org/hamcrest/xml/HasXPathTest.java new file mode 100644 index 0000000..a66689d --- /dev/null +++ b/hamcrest-library/src/test/java/org/hamcrest/xml/HasXPathTest.java @@ -0,0 +1,147 @@ +package org.hamcrest.xml; + +import org.hamcrest.Matcher; +import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.ByteArrayInputStream; +import java.util.HashSet; +import java.util.Iterator; + +import static org.hamcrest.AbstractMatcherTest.*; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNot.not; +import static org.hamcrest.core.StringContains.containsString; +import static org.hamcrest.xml.HasXPath.hasXPath; +import static org.junit.Assert.fail; + +/** + * @author Joe Walnes + * @author Tom Denley + */ +public final class HasXPathTest { + + private final Document xml = parse("" + + "<root type='food'>\n" + + " <something id='a'><cheese>Edam</cheese></something>\n" + + " <something id='b'><cheese>Cheddar</cheese></something>\n" + + " <f:foreignSomething xmlns:f=\"http://cheese.com\" milk=\"camel\">Caravane</f:foreignSomething>\n" + + " <emptySomething />\n" + + " <f:emptySomething xmlns:f=\"http://cheese.com\" />" + + "</root>\n" + ); + + private final NamespaceContext ns = new NamespaceContext() { + @Override + public String getNamespaceURI(String prefix) { + return ("cheese".equals(prefix) ? "http://cheese.com" : null); + } + + @Override + public String getPrefix(String namespaceURI) { + return ("http://cheese.com".equals(namespaceURI) ? "cheese" : null); + } + + @Override + public Iterator<String> getPrefixes(String namespaceURI) { + HashSet<String> prefixes = new HashSet<String>(); + String prefix = getPrefix(namespaceURI); + if (prefix != null) { + prefixes.add(prefix); + } + return prefixes.iterator(); + } + }; + + @Test public void + copesWithNullsAndUnknownTypes() { + Matcher<Node> matcher = hasXPath("//irrelevant"); + + assertNullSafe(matcher); + assertUnknownTypeSafe(matcher); + } + + @Test public void + appliesMatcherToXPathInDocument() { + assertMatches(hasXPath("/root/something[2]/cheese", equalTo("Cheddar")), xml); + assertMatches(hasXPath("//something[1]/cheese", containsString("dam")), xml); + assertMatches(hasXPath("//something[2]/cheese", not(containsString("dam"))), xml); + assertMatches(hasXPath("/root/@type", equalTo("food")), xml); + assertMatches(hasXPath("//something[@id='b']/cheese", equalTo("Cheddar")), xml); + assertMatches(hasXPath("//something[@id='b']/cheese"), xml); + } + + @Test public void + matchesEmptyElement() { + assertMatches(hasXPath("//emptySomething"), xml); + } + + @Test public void + matchesEmptyElementInNamespace() { + assertMatches(hasXPath("//cheese:emptySomething", ns), xml); + } + + @Test public void + failsIfNodeIsMissing() { + assertDoesNotMatch(hasXPath("/root/something[3]/cheese", ns, equalTo("Cheddar")), xml); + assertDoesNotMatch(hasXPath("//something[@id='c']/cheese", ns), xml); + } + + @Test public void + failsIfNodeIsMissingInNamespace() { + assertDoesNotMatch(hasXPath("//cheese:foreignSomething", equalTo("Badger")), xml); + assertDoesNotMatch(hasXPath("//cheese:foreignSomething"), xml); + } + + @Test public void + matchesWithNamespace() { + assertMatches(hasXPath("//cheese:foreignSomething", ns), xml); + assertMatches(hasXPath("//cheese:foreignSomething/@milk", ns, equalTo("camel")), xml); + assertMatches(hasXPath("//cheese:foreignSomething/text()", ns, equalTo("Caravane")), xml); + } + + @Test public void + throwsIllegalArgumentExceptionIfGivenIllegalExpression() { + try { + hasXPath("\\g:dfgd::DSgf/root/something[2]/cheese", equalTo("blah")); + fail("Expected exception"); + } catch (IllegalArgumentException expectedException) { + // expected exception + } + } + + @Test public void + describesItself() { + assertDescription("an XML document with XPath /some/path \"Cheddar\"", + hasXPath("/some/path", equalTo("Cheddar"))); + + assertDescription("an XML document with XPath /some/path", + hasXPath("/some/path")); + } + + @Test public void + describesMissingNodeMismatch() { + assertMismatchDescription("xpath returned no results.", hasXPath("//honky"), xml); + } + + @Test public void + describesIncorrectNodeValueMismatch() { + assertMismatchDescription("was \"Edam\"", hasXPath("//something[1]/cheese", equalTo("parmesan")), xml); + } + + private static Document parse(String xml) { + try { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + return documentBuilder.parse(new ByteArrayInputStream(xml.getBytes())); + } + catch (Exception e) { + throw new IllegalStateException(e); + } + } +} |