diff options
author | Paul Duffin <paulduffin@google.com> | 2017-01-20 15:04:28 +0000 |
---|---|---|
committer | Paul Duffin <paulduffin@google.com> | 2017-02-09 15:12:38 +0000 |
commit | c1dbb44e71e47410ad5685aba3ef3fccb095a2b4 (patch) | |
tree | 08f6e90ece87cf59e3c7c645a7519eaaf63c716e /hamcrest-core/src/main/java/org/hamcrest/core | |
parent | 21a7b5b68f0bdc465bf6270db8917b881cf04157 (diff) | |
download | hamcrest-c1dbb44e71e47410ad5685aba3ef3fccb095a2b4.tar.gz |
Upgrade to almost 2.0.0.0
See the README.android for the exact version used and an
explanation as to why it was chosen.
Bug: 30946317
Test: make checkbuild
Change-Id: Icae106f5e4a62d2a34f4cf03506fd63676814c07
Diffstat (limited to 'hamcrest-core/src/main/java/org/hamcrest/core')
18 files changed, 839 insertions, 251 deletions
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..06e999a 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,56 @@ 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; /** - * 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> { + + private final Iterable<Matcher<? super T>> matchers; - public AllOf(Iterable<Matcher<? extends 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(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..03cc210 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,46 @@ 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; /** - * 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> { - - private final Iterable<Matcher<? extends T>> matchers; +public class AnyOf<T> extends ShortcutCombination<T> { - 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(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); + +} |