Skip to content

Commit

Permalink
Do not treat Path as Iterable to avoid infinite recursion.
Browse files Browse the repository at this point in the history
Fixes #1855
  • Loading branch information
joel-costigliola committed May 2, 2020
1 parent d66da9f commit c5de891
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.assertj.core.util.Lists.newArrayList;
import static org.assertj.core.util.Strings.join;

import java.nio.file.Path;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -166,11 +167,16 @@ public boolean isExpectedFieldAnOrderedCollection() {
}

public boolean isActualFieldAnIterable() {
return actual instanceof Iterable;
// ignore Path to be consistent with isExpectedFieldAnIterable
return actual instanceof Iterable && !(actual instanceof Path);
}

public boolean isExpectedFieldAnIterable() {
return expected instanceof Iterable;
// Don't consider Path as an Iterable as recursively comparing them leads to a stack overflow, here's why:
// Iterable are compared element by element recursively
// Ex: /tmp/foo.txt path has /tmp as its first element
// so /tmp is going to be compared recursively but /tmp first element is itself leading to an infinite recursion
return expected instanceof Iterable && !(expected instanceof Path);
}

private static boolean isAnOrderedCollection(Object value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.assertj.core.util.Sets.newLinkedHashSet;
import static org.assertj.core.util.Sets.newTreeSet;

import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Stream;

Expand Down Expand Up @@ -130,7 +131,8 @@ public void isExpectedFieldAnIterable_should_return_false_when_expected_is_not_a
}

static Stream<Object> nonIterables() {
return Stream.of(123, "abc", array("a", "b"));
// even though Path is an iterable, it must not be considered as such
return Stream.of(123, "abc", array("a", "b"), Paths.get("/tmp"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@
import static org.assertj.core.error.ShouldNotBeNull.shouldNotBeNull;
import static org.assertj.core.test.AlwaysEqualComparator.ALWAY_EQUALS_STRING;
import static org.assertj.core.util.Lists.list;
import static org.junit.jupiter.api.condition.OS.WINDOWS;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.Mockito.verify;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.util.Date;
import java.util.stream.Stream;
Expand All @@ -36,6 +39,7 @@
import org.assertj.core.internal.objects.data.Person;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
Expand Down Expand Up @@ -335,7 +339,30 @@ static class LightString {
public LightString(String value) {
this.color = value;
}
}

@Test
@DisabledOnOs(WINDOWS)
public void should_not_treat_Path_as_Iterable_to_avoid_infinite_recursion() {
final Container container1 = new Container("/tmp/example");
final Container container2 = new Container("/tmp/example");

assertThat(container1).usingRecursiveComparison()
.isEqualTo(container2)
.ignoringAllOverriddenEquals()
.isEqualTo(container2);
}

public static class Container {
private Path path;

public Container(String path) {
this.path = Paths.get(path);
}

public Path getPath() {
return path;
}
}

}

0 comments on commit c5de891

Please sign in to comment.