Skip to content

Commit

Permalink
Adding FAIL_FAST option (#785)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukas-krecan committed Jul 3, 2024
1 parent 5dff029 commit 3df62fd
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,10 @@ public enum Option {
* Ignores values but fails if value types are different.
* When using within {@link ConfigurationWhen#then(Option, Option...)}, path to the node with ignored value should be passed.
*/
IGNORING_VALUES
IGNORING_VALUES,

/**
* Stops comparison at the first difference. Can bring performance boots to use-cases that do not need the full list of all differences.
*/
FAIL_FAST
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@
import static java.lang.Math.min;
import static java.util.Collections.unmodifiableList;
import static java.util.stream.Collectors.toList;
import static net.javacrumbs.jsonunit.core.Configuration.dummyDifferenceListener;
import static net.javacrumbs.jsonunit.core.Option.FAIL_FAST;
import static net.javacrumbs.jsonunit.core.internal.Diff.DEFAULT_DIFFERENCE_STRING;
import static net.javacrumbs.jsonunit.core.internal.JsonUnitLogger.NULL_LOGGER;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import net.javacrumbs.jsonunit.core.Configuration;
import net.javacrumbs.jsonunit.core.listener.DifferenceListener;

/**
* Stores comparison result when comparing two arrays.
Expand Down Expand Up @@ -88,15 +89,12 @@ private static boolean isSimilar(Path path, Configuration configuration, Node ex
expected,
actual,
Path.create("", path.toElement(i).getFullPath()),
configuration.withDifferenceListener(failFastDifferenceListener),
configuration.withDifferenceListener(dummyDifferenceListener()).withOptions(FAIL_FAST),
NULL_LOGGER,
NULL_LOGGER,
DEFAULT_DIFFERENCE_STRING);
try {
return diff.similar();
} catch (DifferenceFoundException e) {
return false;
}

return diff.similar();
}

ComparisonMatrix compare() {
Expand Down Expand Up @@ -225,15 +223,4 @@ List<Integer> getMissing() {
List<Integer> getExtra() {
return extra;
}

private static final DifferenceListener failFastDifferenceListener = (difference, context) -> {
throw new DifferenceFoundException();
};

private static final class DifferenceFoundException extends RuntimeException {
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@
import net.javacrumbs.jsonunit.core.internal.ArrayComparison.ComparisonResult;
import net.javacrumbs.jsonunit.core.internal.ArrayComparison.NodeWithIndex;
import net.javacrumbs.jsonunit.core.listener.Difference;
import static java.util.Collections.emptySet;
import static net.javacrumbs.jsonunit.core.Option.FAIL_FAST;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_ARRAY_ITEMS;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_FIELDS;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_VALUES;
import static net.javacrumbs.jsonunit.core.Option.TREATING_NULL_AS_ABSENT;
import static net.javacrumbs.jsonunit.core.internal.ClassUtils.isClassPresent;
import static net.javacrumbs.jsonunit.core.internal.DifferenceContextImpl.differenceContext;
import static net.javacrumbs.jsonunit.core.internal.ExceptionUtils.createException;
import static net.javacrumbs.jsonunit.core.internal.ExceptionUtils.formatDifferences;
import static net.javacrumbs.jsonunit.core.internal.JsonUnitLogger.NULL_LOGGER;
import static net.javacrumbs.jsonunit.core.internal.JsonUtils.convertToJson;
import static net.javacrumbs.jsonunit.core.internal.JsonUtils.prettyPrint;
import static net.javacrumbs.jsonunit.core.internal.JsonUtils.quoteIfNeeded;
import static net.javacrumbs.jsonunit.core.internal.Node.KeyValue;
import static net.javacrumbs.jsonunit.core.internal.Node.NodeType;

import java.math.BigDecimal;
import java.util.ArrayList;
Expand Down Expand Up @@ -124,7 +141,11 @@ private void compare() {
if (part.isMissingNode()) {
structureDifferenceFound(context, "Missing node in path \"%s\".", startPath);
} else {
compareNodes(context);
try {
compareNodes(context);
} catch (FailedFastException e) {
// ignore, the difference is already in the `differences` list.
}
}
compared = true;

Expand Down Expand Up @@ -538,18 +559,27 @@ private List<Node> asList(Iterator<Node> elements) {

private void structureDifferenceFound(Context context, String message, Object... arguments) {
differences.add(new JsonDifference(context, message, arguments));
possiblyFailFast(context);
}

@SuppressWarnings("deprecation")
private void valueDifferenceFound(Context context, String message, Object... arguments) {
if (!hasOption(context.getActualPath(), COMPARING_ONLY_STRUCTURE)) {
differences.add(new JsonDifference(context, message, arguments));
}
possiblyFailFast(context);
}

private void reportValueDifference(Context context, String message, Object... arguments) {
reportDifference(DifferenceImpl.different(context));
valueDifferenceFound(context, message, arguments);
possiblyFailFast(context);
}

private void possiblyFailFast(Context context) {
if (hasOption(context.getActualPath(), FAIL_FAST)) {
throw new FailedFastException();
}
}

private Set<String> commonFields(Map<String, Node> expectedFields, Map<String, Node> actualFields) {
Expand Down Expand Up @@ -625,4 +655,14 @@ private static JsonUnitLogger createLogger(String name) {
return NULL_LOGGER;
}
}

/**
* Exception throw on the first difference when FAIL_FAST option is on.
*/
private static final class FailedFastException extends RuntimeException {
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import static net.javacrumbs.jsonunit.core.ConfigurationWhen.then;
import static net.javacrumbs.jsonunit.core.ConfigurationWhen.thenIgnore;
import static net.javacrumbs.jsonunit.core.ConfigurationWhen.thenNot;
import static net.javacrumbs.jsonunit.core.Option.FAIL_FAST;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_ARRAY_ITEMS;
import static net.javacrumbs.jsonunit.core.Option.IGNORING_EXTRA_FIELDS;
Expand Down Expand Up @@ -1980,6 +1981,14 @@ void shouldIgnoreMultiplePathsWrittenSeparately() {
.isEqualTo("{\"c\":3}");
}

@Test
void shouldFailFast() {
assertThatThrownBy(() -> assertThatJson("{\"a\":{\"a1\": 1},\"b\":{\"b1\": 1}}")
.withConfiguration(c -> c.withOptions(FAIL_FAST))
.isEqualTo("{\"a\":{\"a1\": 2},\"b\":{\"b1\": 2}}"))
.hasMessage("JSON documents are different:\nDifferent value found in node \"a.a1\", expected: <2> but was: <1>.\n");
}

private static final String json = "{\n" +
" \"store\": {\n" +
" \"book\": [\n" +
Expand Down

0 comments on commit 3df62fd

Please sign in to comment.