diff options
author | Paul Duffin <paulduffin@google.com> | 2017-02-24 13:28:28 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-02-24 13:28:28 +0000 |
commit | f324aac9e2d9c977fcf8e0033a6a7846a62db4df (patch) | |
tree | 873cd708d3c6fb36684c53bc506ff3940c3ec3f0 | |
parent | 21a7b5b68f0bdc465bf6270db8917b881cf04157 (diff) | |
parent | 9599ee2623bb76c0c7f840ba8bfd92a6ecf74390 (diff) | |
download | hamcrest-f324aac9e2d9c977fcf8e0033a6a7846a62db4df.tar.gz |
Merge changes from topic 'upgrade-hamcrest-to-2.0'android-o-preview-1android-n-mr2-preview-2o-preview
* changes:
Temporarily add void is(Class) to cause compile time errors
Make it compile in error prone
Replace org.hamcrest.Factory for backwards compatibility
Remove org.hamcrest.beans and update Matchers
Upgrade to almost 2.0.0.0
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); + } + } +} |