Skip to content

Commit

Permalink
Fixes #444 : containsOnly error should not display elements not found…
Browse files Browse the repository at this point in the history
… if there are none
  • Loading branch information
joel-costigliola committed Aug 28, 2015
1 parent aeda12d commit ad14304
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 169 deletions.
92 changes: 37 additions & 55 deletions src/main/java/org/assertj/core/error/ShouldContainOnly.java
Expand Up @@ -12,6 +12,8 @@
*/
package org.assertj.core.error;

import static org.assertj.core.error.ShouldContainOnly.ErrorType.NOT_EXPECTED;
import static org.assertj.core.error.ShouldContainOnly.ErrorType.NOT_FOUND;
import static org.assertj.core.util.IterableUtil.isNullOrEmpty;

import org.assertj.core.internal.ComparisonStrategy;
Expand All @@ -38,25 +40,12 @@ public class ShouldContainOnly extends BasicErrorMessageFactory {
* @param comparisonStrategy the {@link ComparisonStrategy} used to evaluate assertion.
* @return the created {@code ErrorMessageFactory}.
*/
public static ErrorMessageFactory shouldContainOnly(Object actual, Object expected, Object notFound,
Object notExpected,
ComparisonStrategy comparisonStrategy) {
return new ShouldContainOnly(actual, expected, notFound, notExpected, comparisonStrategy);
}

/**
* Creates a new </code>{@link ShouldContainOnly}</code>.
*
* @param actual the actual value in the failed assertion.
* @param expected values expected to be contained in {@code actual}.
* @param notFound values in {@code expected} not found in {@code actual}.
* @param notExpected values in {@code actual} that were not in {@code expected}.
* @param comparisonStrategy the {@link ComparisonStrategy} used to evaluate assertion.
* @return the created {@code ErrorMessageFactory}.
*/
public static ErrorMessageFactory shouldContainOnly(Object actual, Object expected, Object notFound,
Iterable<?> notExpected, ComparisonStrategy comparisonStrategy) {
if (isNullOrEmpty(notExpected)) return new ShouldContainOnly(actual, expected, notFound, comparisonStrategy);
public static ErrorMessageFactory shouldContainOnly(Object actual, Object expected, Iterable<?> notFound,
Iterable<?> notExpected, ComparisonStrategy comparisonStrategy) {
if (isNullOrEmpty(notExpected))
return new ShouldContainOnly(actual, expected, notFound, NOT_FOUND, comparisonStrategy);
if (isNullOrEmpty(notFound))
return new ShouldContainOnly(actual, expected, notExpected, NOT_EXPECTED, comparisonStrategy);
return new ShouldContainOnly(actual, expected, notFound, notExpected, comparisonStrategy);
}

Expand All @@ -69,48 +58,41 @@ public static ErrorMessageFactory shouldContainOnly(Object actual, Object expect
* @param notExpected values in {@code actual} that were not in {@code expected}.
* @return the created {@code ErrorMessageFactory}.
*/
public static ErrorMessageFactory shouldContainOnly(Object actual, Object expected, Object notFound,
Object notExpected) {
return shouldContainOnly(actual, expected, notFound, notExpected, StandardComparisonStrategy.instance());
public static ErrorMessageFactory shouldContainOnly(Object actual, Object expected, Iterable<?> notFound,
Iterable<?> notExpected) {
return shouldContainOnly(actual, expected, notFound, notExpected, StandardComparisonStrategy.instance());
}

/**
* Creates a new </code>{@link ShouldContainOnly}</code>.
*
* @param actual the actual value in the failed assertion.
* @param expected values expected to be contained in {@code actual}.
* @param notFound values in {@code expected} not found in {@code actual}.
* @param notExpected values in {@code actual} that were not in {@code expected}.
* @return the created {@code ErrorMessageFactory}.
*/
public static ErrorMessageFactory shouldContainOnly(Object actual, Object expected, Object notFound,
Iterable<?> notExpected) {
return shouldContainOnly(actual, expected, notFound, notExpected, StandardComparisonStrategy.instance());
private ShouldContainOnly(Object actual, Object expected, Iterable<?> notFound, Iterable<?> notExpected,
ComparisonStrategy comparisonStrategy) {
super("%n" +
"Expecting:%n" +
" <%s>%n" +
"to contain only:%n" +
" <%s>%n" +
"elements not found:%n" +
" <%s>%n" +
"and elements not expected:%n" +
" <%s>%n%s", actual,
expected, notFound, notExpected, comparisonStrategy);
}

private ShouldContainOnly(Object actual, Object expected, Object notFound, Object notExpected,
ComparisonStrategy comparisonStrategy) {
super("%n" +
"Expecting:%n" +
" <%s>%n" +
"to contain only:%n" +
" <%s>%n" +
"elements not found:%n" +
" <%s>%n" +
"and elements not expected:%n" +
" <%s>%n%s", actual,
expected, notFound, notExpected, comparisonStrategy);
private ShouldContainOnly(Object actual, Object expected, Iterable<?> notFoundOrNotExpected, ErrorType errorType,
ComparisonStrategy comparisonStrategy) {
// @format:off
super("%n" +
"Expecting:%n" +
" <%s>%n" +
"to contain only:%n" +
" <%s>%n" + (errorType == NOT_FOUND ?
"but could not find the following elements:%n" : "but the following elements were unexpected:%n") +
" <%s>%n%s",
actual, expected, notFoundOrNotExpected, comparisonStrategy);
// @format:on
}

private ShouldContainOnly(Object actual, Object expected, Object notFound, ComparisonStrategy comparisonStrategy) {
super("%n" +
"Expecting:%n" +
" <%s>%n" +
"to contain only:%n" +
" <%s>%n" +
"but could not find the following elements:%n" +
" <%s>%n%s",
actual, expected, notFound, comparisonStrategy);
public enum ErrorType {
NOT_FOUND, NOT_EXPECTED
}

}
74 changes: 22 additions & 52 deletions src/main/java/org/assertj/core/internal/Iterables.java
Expand Up @@ -259,9 +259,8 @@ public void assertContainsOnly(AssertionInfo info, Iterable<?> actual, Object[]
// check for elements in values that are missing in actual.
List<Object> notExpected = asListWithoutDuplicatesAccordingToComparisonStrategy(actual);
List<Object> notFound = containsOnly(notExpected, values);
if (!notExpected.isEmpty() || !notFound.isEmpty()) {
if (!notExpected.isEmpty() || !notFound.isEmpty())
throw failures.failure(info, shouldContainOnly(actual, values, notFound, notExpected, comparisonStrategy));
}
}

private List<Object> containsOnly(Collection<Object> actual, Object[] values) {
Expand All @@ -287,9 +286,7 @@ private List<Object> listWithoutDuplicates(Object... elements) {
* @return a Set without duplicates <b>according to given comparison strategy</b>
*/
private List<Object> asListWithoutDuplicatesAccordingToComparisonStrategy(Iterable<?> iterable) {
if (iterable == null) {
return null;
}
if (iterable == null) return null;
List<Object> list = new ArrayList<>();
for (Object e : iterable) {
// only add is not already there
Expand All @@ -313,8 +310,7 @@ private List<Object> asListWithoutDuplicatesAccordingToComparisonStrategy(Iterab
* {@code Iterable} contains values that are not in the given array.
*/
public void assertContainsOnlyOnce(AssertionInfo info, Iterable<?> actual, Object[] values) {
if (commonCheckThatIterableAssertionSucceeds(info, actual, values))
return;
if (commonCheckThatIterableAssertionSucceeds(info, actual, values)) return;
// check for elements in values that are missing in actual.
Set<Object> notFound = new LinkedHashSet<>();
Set<Object> notOnlyOnce = new LinkedHashSet<>();
Expand All @@ -326,9 +322,8 @@ public void assertContainsOnlyOnce(AssertionInfo info, Iterable<?> actual, Objec
notOnlyOnce.add(expectedOnlyOnce);
}
}
if (!notFound.isEmpty() || !notOnlyOnce.isEmpty()) {
if (!notFound.isEmpty() || !notOnlyOnce.isEmpty())
throw failures.failure(info, shouldContainsOnlyOnce(actual, values, notFound, notOnlyOnce, comparisonStrategy));
}
// assertion succeeded
}

Expand Down Expand Up @@ -371,25 +366,17 @@ public void assertContainsSequence(AssertionInfo info, Iterable<?> actual, Objec
* @throws AssertionError if the given {@code Iterable} does not contain the given subsequence of objects.
*/
public void assertContainsSubsequence(AssertionInfo info, Iterable<?> actual, Object[] subsequence) {
if (commonCheckThatIterableAssertionSucceeds(info, actual, subsequence)) {
return;
}
if (commonCheckThatIterableAssertionSucceeds(info, actual, subsequence)) return;

Iterator<?> actualIterator = actual.iterator();
int subsequenceIndex = 0;

while (actualIterator.hasNext() && subsequenceIndex < subsequence.length) {
Object actualNext = actualIterator.next();
Object subsequenceNext = subsequence[subsequenceIndex];

if (areEqual(actualNext, subsequenceNext)) {
subsequenceIndex++;
}
if (areEqual(actualNext, subsequenceNext)) subsequenceIndex++;
}

if (subsequenceIndex < subsequence.length) {
throw actualDoesNotContainSubsequence(info, actual, subsequence);
}
if (subsequenceIndex < subsequence.length) throw actualDoesNotContainSubsequence(info, actual, subsequence);
}

/**
Expand All @@ -412,9 +399,7 @@ public void assertIsSubsetOf(AssertionInfo info, Iterable<?> actual, Iterable<?>
extra.add(actualElement);
}
}
if (extra.size() > 0) {
throw failures.failure(info, shouldBeSubsetOf(actual, values, extra, comparisonStrategy));
}
if (extra.size() > 0) throw failures.failure(info, shouldBeSubsetOf(actual, values, extra, comparisonStrategy));
}

/**
Expand All @@ -429,9 +414,7 @@ private boolean containsSequenceAtGivenIndex(List<?> actualAsList, Object[] sequ
// check that, starting from given index, actualAsList has enough remaining elements to contain sequence
if (actualAsList.size() - startingIndex < sequence.length) return false;
for (int i = 0; i < sequence.length; i++) {
if (!areEqual(actualAsList.get(startingIndex + i), sequence[i])) {
return false;
}
if (!areEqual(actualAsList.get(startingIndex + i), sequence[i])) return false;
}
return true;
}
Expand Down Expand Up @@ -467,9 +450,7 @@ public void assertDoesNotContain(AssertionInfo info, Iterable<?> actual, Object[
assertNotNull(info, actual);
Set<Object> found = new LinkedHashSet<>();
for (Object o : values) {
if (iterableContains(actual, o)) {
found.add(o);
}
if (iterableContains(actual, o)) found.add(o);
}
if (!found.isEmpty()) throw failures.failure(info, shouldNotContain(actual, values, found, comparisonStrategy));
}
Expand Down Expand Up @@ -505,9 +486,8 @@ public <T> void assertDoesNotContainAnyElementsOf(AssertionInfo info, Iterable<?
public void assertDoesNotHaveDuplicates(AssertionInfo info, Iterable<?> actual) {
assertNotNull(info, actual);
Iterable<?> duplicates = comparisonStrategy.duplicatesFrom(actual);
if (!isNullOrEmpty(duplicates)) {
if (!isNullOrEmpty(duplicates))
throw failures.failure(info, shouldNotHaveDuplicates(actual, duplicates, comparisonStrategy));
}
}

/**
Expand All @@ -524,14 +504,11 @@ public void assertDoesNotHaveDuplicates(AssertionInfo info, Iterable<?> actual)
* @throws AssertionError if the given {@code Iterable} does not start with the given sequence of objects.
*/
public void assertStartsWith(AssertionInfo info, Iterable<?> actual, Object[] sequence) {
if (commonCheckThatIterableAssertionSucceeds(info, actual, sequence))
return;
if (commonCheckThatIterableAssertionSucceeds(info, actual, sequence)) return;
int i = 0;
for (Object actualCurrentElement : actual) {
if (i >= sequence.length)
break;
if (areEqual(actualCurrentElement, sequence[i++]))
continue;
if (i >= sequence.length) break;
if (areEqual(actualCurrentElement, sequence[i++])) continue;
throw actualDoesNotStartWithSequence(info, actual, sequence);
}
if (sequence.length > i) {
Expand All @@ -558,19 +535,16 @@ private AssertionError actualDoesNotStartWithSequence(AssertionInfo info, Iterab
* @throws AssertionError if the given {@code Iterable} does not end with the given sequence of objects.
*/
public void assertEndsWith(AssertionInfo info, Iterable<?> actual, Object[] sequence) {
if (commonCheckThatIterableAssertionSucceeds(info, actual, sequence))
return;
if (commonCheckThatIterableAssertionSucceeds(info, actual, sequence)) return;

int sizeOfActual = sizeOf(actual);
if (sizeOfActual < sequence.length) {
throw actualDoesNotEndWithSequence(info, actual, sequence);
}
if (sizeOfActual < sequence.length) throw actualDoesNotEndWithSequence(info, actual, sequence);

int start = sizeOfActual - sequence.length;
int sequenceIndex = 0, indexOfActual = 0;
for (Object actualElement : actual) {
if (indexOfActual++ < start)
continue;
if (areEqual(actualElement, sequence[sequenceIndex++]))
continue;
if (indexOfActual++ < start) continue;
if (areEqual(actualElement, sequence[sequenceIndex++])) continue;
throw actualDoesNotEndWithSequence(info, actual, sequence);
}
}
Expand Down Expand Up @@ -898,19 +872,15 @@ private AssertionError actualDoesNotEndWithSequence(AssertionInfo info, Iterable
private <E> List<E> notSatisfiesCondition(Iterable<? extends E> actual, Condition<? super E> condition) {
List<E> notSatisfiesCondition = new LinkedList<>();
for (E o : actual) {
if (!condition.matches(o)) {
notSatisfiesCondition.add(o);
}
if (!condition.matches(o)) notSatisfiesCondition.add(o);
}
return notSatisfiesCondition;
}

private <E> List<E> satisfiesCondition(Iterable<? extends E> actual, Condition<? super E> condition) {
List<E> satisfiesCondition = new LinkedList<>();
for (E o : actual) {
if (condition.matches(o)) {
satisfiesCondition.add(o);
}
if (condition.matches(o)) satisfiesCondition.add(o);
}
return satisfiesCondition;
}
Expand Down

0 comments on commit ad14304

Please sign in to comment.