aboutsummaryrefslogtreecommitdiff
path: root/hamcrest-core
diff options
context:
space:
mode:
authorPaul Duffin <paulduffin@google.com>2017-02-24 13:38:19 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-02-24 13:38:19 +0000
commit2c2a845e1e8fdda704e4f2ccaa335d69d043ebf3 (patch)
tree873cd708d3c6fb36684c53bc506ff3940c3ec3f0 /hamcrest-core
parent9432ade17c16656f8c3ebbe2b7f3081a93c52d4d (diff)
parentc2e228b07b9dd8266a6eeabb34e27233733ef127 (diff)
downloadhamcrest-android-8.1.0_r51.tar.gz
Merge changes from topic 'upgrade-hamcrest-to-2.0' am: f324aac9e2 am: 0d446c0a6fandroid-wear-8.1.0_r1android-vts-8.1_r9android-vts-8.1_r8android-vts-8.1_r7android-vts-8.1_r6android-vts-8.1_r5android-vts-8.1_r4android-vts-8.1_r3android-vts-8.1_r14android-vts-8.1_r13android-vts-8.1_r12android-vts-8.1_r11android-vts-8.1_r10android-vts-8.0_r2android-vts-8.0_r1android-security-8.1.0_r93android-security-8.1.0_r92android-security-8.1.0_r91android-security-8.1.0_r90android-security-8.1.0_r89android-security-8.1.0_r88android-security-8.1.0_r87android-security-8.1.0_r86android-security-8.1.0_r85android-security-8.1.0_r84android-security-8.1.0_r83android-security-8.1.0_r82android-o-mr1-preview-2android-o-mr1-preview-1android-cts-8.1_r9android-cts-8.1_r8android-cts-8.1_r7android-cts-8.1_r6android-cts-8.1_r5android-cts-8.1_r4android-cts-8.1_r3android-cts-8.1_r25android-cts-8.1_r24android-cts-8.1_r23android-cts-8.1_r22android-cts-8.1_r21android-cts-8.1_r20android-cts-8.1_r2android-cts-8.1_r19android-cts-8.1_r18android-cts-8.1_r17android-cts-8.1_r16android-cts-8.1_r15android-cts-8.1_r14android-cts-8.1_r13android-cts-8.1_r12android-cts-8.1_r11android-cts-8.1_r10android-cts-8.1_r1android-8.1.0_r9android-8.1.0_r81android-8.1.0_r80android-8.1.0_r8android-8.1.0_r79android-8.1.0_r78android-8.1.0_r77android-8.1.0_r76android-8.1.0_r75android-8.1.0_r74android-8.1.0_r73android-8.1.0_r72android-8.1.0_r71android-8.1.0_r70android-8.1.0_r7android-8.1.0_r69android-8.1.0_r68android-8.1.0_r67android-8.1.0_r66android-8.1.0_r65android-8.1.0_r64android-8.1.0_r63android-8.1.0_r62android-8.1.0_r61android-8.1.0_r60android-8.1.0_r6android-8.1.0_r53android-8.1.0_r52android-8.1.0_r51android-8.1.0_r50android-8.1.0_r5android-8.1.0_r48android-8.1.0_r47android-8.1.0_r46android-8.1.0_r45android-8.1.0_r43android-8.1.0_r42android-8.1.0_r41android-8.1.0_r40android-8.1.0_r4android-8.1.0_r39android-8.1.0_r38android-8.1.0_r37android-8.1.0_r36android-8.1.0_r35android-8.1.0_r33android-8.1.0_r32android-8.1.0_r31android-8.1.0_r30android-8.1.0_r3android-8.1.0_r29android-8.1.0_r28android-8.1.0_r27android-8.1.0_r26android-8.1.0_r25android-8.1.0_r23android-8.1.0_r22android-8.1.0_r21android-8.1.0_r20android-8.1.0_r2android-8.1.0_r19android-8.1.0_r18android-8.1.0_r17android-8.1.0_r16android-8.1.0_r15android-8.1.0_r14android-8.1.0_r13android-8.1.0_r12android-8.1.0_r11android-8.1.0_r10android-8.1.0_r1android-8.0.0_r34android-8.0.0_r33android-8.0.0_r27android-8.0.0_r26android-8.0.0_r25android-8.0.0_r24android-8.0.0_r23android-8.0.0_r22android-8.0.0_r21security-oc-mr1-releaseoreo-mr1-wear-releaseoreo-mr1-vts-releaseoreo-mr1-security-releaseoreo-mr1-s1-releaseoreo-mr1-releaseoreo-mr1-devoreo-mr1-cuttlefish-testingoreo-mr1-cts-releaseoreo-m8-releaseoreo-m7-releaseoreo-m6-s4-releaseoreo-m6-s3-releaseoreo-m6-s2-releaseoreo-m5-releaseoreo-m4-s9-releaseoreo-m4-s8-releaseoreo-m4-s7-releaseoreo-m4-s6-releaseoreo-m4-s5-releaseoreo-m4-s4-releaseoreo-m4-s3-releaseoreo-m4-s2-releaseoreo-m4-s12-releaseoreo-m4-s11-releaseoreo-m4-s10-releaseoreo-m4-s1-releaseoreo-m3-releaseoreo-m2-s5-releaseoreo-m2-s4-releaseoreo-m2-s3-releaseoreo-m2-s2-releaseoreo-m2-s1-releaseoreo-m2-releaseoreo-dr3-releaseoreo-dr2-releaseoreo-dr1-releaseoreo-dr1-devoreo-dev
am: c2e228b07b Change-Id: I737b987a8b22811c7ea058bcd9898b58694b58ce
Diffstat (limited to 'hamcrest-core')
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/BaseDescription.java271
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java9
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/Condition.java69
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/CoreMatchers.java419
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/CustomMatcher.java37
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/CustomTypeSafeMatcher.java39
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/Description.java133
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/DiagnosingMatcher.java21
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/Factory.java9
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/FeatureMatcher.java54
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/Matcher.java34
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java51
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/SelfDescribing.java2
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/StringDescription.java123
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/TypeSafeDiagnosingMatcher.java69
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/TypeSafeMatcher.java81
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java50
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/AnyOf.java50
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/CombinableMatcher.java82
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/DescribedAs.java124
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/Every.java44
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/Is.java64
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java41
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/IsCollectionContaining.java133
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/IsEqual.java82
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/IsInstanceOf.java81
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/IsNot.java36
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/IsNull.java61
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/IsSame.java39
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/ShortcutCombination.java33
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/StringContains.java46
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/StringEndsWith.java42
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/StringStartsWith.java40
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/core/SubstringMatcher.java44
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/internal/ArrayIterator.java43
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/internal/NullSafety.java18
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/internal/ReflectiveTypeFinder.java70
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValue.java1
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/internal/SelfDescribingValueIterator.java7
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/internal/package.html5
-rw-r--r--hamcrest-core/src/main/java/org/hamcrest/package.html9
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/AbstractMatcherTest.java77
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/BaseDescriptionTest.java78
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/BaseMatcherTest.java26
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/CustomMatcherTest.java20
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/CustomTypeSafeMatcherTest.java41
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/FeatureMatcherTest.java68
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/MatcherAssertTest.java96
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/NullDescriptionTest.java18
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/TypeSafeMatcherTest.java40
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/AllOfTest.java63
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/AnyOfTest.java56
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/CombinableTest.java68
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/DescribedAsTest.java49
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/EveryTest.java43
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/IsAnythingTest.java35
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/IsCollectionContainingTest.java107
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/IsEqualTest.java143
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/IsInstanceOfTest.java69
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/IsNotTest.java42
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/IsNullTest.java43
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/IsSameTest.java48
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/IsTest.java51
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/SampleBaseClass.java24
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/SampleSubClass.java9
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/StringContainsTest.java43
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/StringEndsWithTest.java45
-rw-r--r--hamcrest-core/src/test/java/org/hamcrest/core/StringStartsWithTest.java46
68 files changed, 3466 insertions, 648 deletions
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&lt;String&gt; aNonEmptyString = new CustomMatcher&lt;String&gt;("a non empty string") {
+ * public boolean matches(Object object) {
+ * return ((object instanceof String) &amp;&amp; !((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&lt;String&gt; aNonEmptyString = new CustomTypeSafeMatcher&lt;String&gt;("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 &lt;T&gt; 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 &lt;T&gt; 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 &lt;T&gt; 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 &lt;T&gt; 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&lt;T&gt;</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&lt;String&gt;</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(&lt;T&gt;, 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");
+ }
+
+}