Skip to content

Commit

Permalink
Recursive comparison breaking changes: use of the expected field as a…
Browse files Browse the repository at this point in the history
… reference for container type compatibility

- sorted vs non sorted are replaced ordered vs unordered semantics (ordered type are List, SortedSet and LinkedHashSet)
- actual ordered vs expected unordered is allowed but actual unordered vs expected ordered is not

Refactor RecursiveComparisonDifferenceCalculator:
- introduce ComparisonState
- remove quite a bit of code duplication

Improve error messages when group size differs or when trying to compare actual unordered vs expected ordered.

Split and add a bunch of tests.
  • Loading branch information
joel-costigliola committed May 5, 2019
1 parent e2b4828 commit f329748
Show file tree
Hide file tree
Showing 17 changed files with 1,482 additions and 540 deletions.
Expand Up @@ -14,19 +14,30 @@

import static java.lang.String.format;
import static java.util.Collections.unmodifiableList;
import static org.assertj.core.util.Arrays.array;
import static org.assertj.core.util.Arrays.isArray;
import static org.assertj.core.util.Strings.join;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.stream.Stream;

// logically immutable
final class DualValue {

static final Class<?>[] DEFAULT_ORDERED_COLLECTION_TYPES = array(List.class, SortedSet.class, LinkedHashSet.class);

final List<String> path;
final String concatenatedPath;
final Object actual;
final Object expected;
private final int hashCode;


DualValue(List<String> path, Object actual, Object expected) {
this.path = path;
this.concatenatedPath = join(path).with(".");
Expand Down Expand Up @@ -66,4 +77,60 @@ public boolean isJavaType() {
if (actual == null) return false;
return actual.getClass().getName().startsWith("java.");
}

public boolean isExpectedFieldAnArray() {
return isArray(expected);
}

public boolean isActualFieldAnArray() {
return isArray(actual);
}

public boolean hasIterableValues() {
return actual instanceof Iterable && expected instanceof Iterable;
}

public boolean isActualFieldAnOptional() {
return actual instanceof Optional;
}

public boolean isExpectedFieldAnOptional() {
return expected instanceof Optional;
}

public boolean isActualFieldAMap() {
return actual instanceof Map;
}

public boolean isExpectedFieldAMap() {
return expected instanceof Map;
}

public boolean isActualFieldASortedMap() {
return actual instanceof SortedMap;
}

public boolean isExpectedFieldASortedMap() {
return expected instanceof SortedMap;
}

public boolean isActualFieldAnOrderedCollection() {
return isAnOrderedCollection(actual);
}

public boolean isExpectedFieldAnOrderedCollection() {
return isAnOrderedCollection(expected);
}

public boolean isActualFieldAnIterable() {
return actual instanceof Iterable;
}

public boolean isExpectedFieldAnIterable() {
return expected instanceof Iterable;
}

private static boolean isAnOrderedCollection(Object value) {
return Stream.of(DEFAULT_ORDERED_COLLECTION_TYPES).anyMatch(type -> type.isInstance(value));
}
}
Expand Up @@ -290,11 +290,11 @@ private static String concatenatedPath(String parentPath, String name) {
return parentPath.isEmpty() ? name : format("%s.%s", parentPath, name);
}

boolean shouldIgnoreOverriddenEqualsOf(DualValue dualKey) {
if (dualKey.isJavaType()) return false; // we must compare basic types otherwise the recursive comparison loops infinitely!
boolean shouldIgnoreOverriddenEqualsOf(DualValue dualValue) {
if (dualValue.isJavaType()) return false; // we must compare basic types otherwise the recursive comparison loops infinitely!
return ignoreAllOverriddenEquals
|| matchesAnIgnoredOverriddenEqualsField(dualKey)
|| shouldIgnoreOverriddenEqualsOf(dualKey.actual.getClass());
|| matchesAnIgnoredOverriddenEqualsField(dualValue)
|| shouldIgnoreOverriddenEqualsOf(dualValue.actual.getClass());
}

@VisibleForTesting
Expand Down

0 comments on commit f329748

Please sign in to comment.