From 781fe68c5316033d18167a6b18d23a13cece61f4 Mon Sep 17 00:00:00 2001 From: Nicolas Dos Santos Date: Fri, 16 Apr 2021 09:56:24 +0200 Subject: [PATCH 1/2] Support for verifying a package and all sub-packages --- .../ConfiguredEqualsVerifier.java | 16 +++- .../jqno/equalsverifier/EqualsVerifier.java | 16 +++- .../internal/reflection/PackageScanner.java | 19 ++-- .../MultipleTypeEqualsVerifierTest.java | 89 +++++++++++++++++++ .../reflection/PackageScannerTest.java | 46 ++++++++-- .../packages/correct/subpackage/A.java | 31 +++++++ .../packages/correct/subpackage/B.java | 31 +++++++ .../correct/subpackage/subpackage/A.java | 31 +++++++ .../correct/subpackage/subpackage/B.java | 31 +++++++ .../correct/subpackage/subpackage/D.java | 31 +++++++ .../twoincorrect/subpackage/IncorrectO.java | 31 +++++++ .../twoincorrect/subpackage/IncorrectP.java | 31 +++++++ 12 files changed, 390 insertions(+), 13 deletions(-) create mode 100644 src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/A.java create mode 100644 src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/B.java create mode 100644 src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/A.java create mode 100644 src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/B.java create mode 100644 src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/D.java create mode 100644 src/test/java/nl/jqno/equalsverifier/testhelpers/packages/twoincorrect/subpackage/IncorrectO.java create mode 100644 src/test/java/nl/jqno/equalsverifier/testhelpers/packages/twoincorrect/subpackage/IncorrectP.java diff --git a/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java b/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java index 82fd39a60..e44195b80 100644 --- a/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java +++ b/src/main/java/nl/jqno/equalsverifier/ConfiguredEqualsVerifier.java @@ -146,7 +146,21 @@ public MultipleTypeEqualsVerifierApi forClasses( * @return A fluent API for EqualsVerifier. */ public MultipleTypeEqualsVerifierApi forPackage(String packageName) { - List> classes = PackageScanner.getClassesIn(packageName); + return forPackage(packageName, false); + } + + /** + * Factory method. For general use. + * + *

Note that this operation may be slow. If the test is too slow, use {@link + * #forClasses(Class, Class, Class...)} instead. + * + * @param packageName A package for which each class's {@code equals} should be tested. + * @param scanRecursively true to scan all sub-packages + * @return A fluent API for EqualsVerifier. + */ + public MultipleTypeEqualsVerifierApi forPackage(String packageName, boolean scanRecursively) { + List> classes = PackageScanner.getClassesIn(packageName, scanRecursively); Validations.validatePackageContainsClasses(packageName, classes); return new MultipleTypeEqualsVerifierApi(classes, new ConfiguredEqualsVerifier()); } diff --git a/src/main/java/nl/jqno/equalsverifier/EqualsVerifier.java b/src/main/java/nl/jqno/equalsverifier/EqualsVerifier.java index cc9602e8a..9bd156dfb 100644 --- a/src/main/java/nl/jqno/equalsverifier/EqualsVerifier.java +++ b/src/main/java/nl/jqno/equalsverifier/EqualsVerifier.java @@ -113,7 +113,21 @@ public static MultipleTypeEqualsVerifierApi forClasses( * @return A fluent API for EqualsVerifier. */ public static MultipleTypeEqualsVerifierApi forPackage(String packageName) { - List> classes = PackageScanner.getClassesIn(packageName); + return forPackage(packageName, false); + } + + /** + * Factory method. For general use. + * + *

Note that this operation may be slow. If the test is too slow, use {@link + * #forClasses(Class, Class, Class...)} instead. + * + * @param packageName A package for which each class's {@code equals} should be tested. + * @param scanRecursively true to scan all sub-packages + * @return A fluent API for EqualsVerifier. + */ + public static MultipleTypeEqualsVerifierApi forPackage(String packageName, boolean scanRecursively) { + List> classes = PackageScanner.getClassesIn(packageName, scanRecursively); Validations.validatePackageContainsClasses(packageName, classes); return new MultipleTypeEqualsVerifierApi(classes, new ConfiguredEqualsVerifier()); } diff --git a/src/main/java/nl/jqno/equalsverifier/internal/reflection/PackageScanner.java b/src/main/java/nl/jqno/equalsverifier/internal/reflection/PackageScanner.java index 6c1480264..09b5169a9 100644 --- a/src/main/java/nl/jqno/equalsverifier/internal/reflection/PackageScanner.java +++ b/src/main/java/nl/jqno/equalsverifier/internal/reflection/PackageScanner.java @@ -18,12 +18,13 @@ private PackageScanner() {} * Scans the given package for classes. * * @param packageName The package to scan. + * @param scanRecursively true to scan all sub-packages * @return the classes contained in the given package. */ - public static List> getClassesIn(String packageName) { + public static List> getClassesIn(String packageName, boolean scanRecursively) { return getDirs(packageName) .stream() - .flatMap(d -> getClassesInDir(packageName, d).stream()) + .flatMap(d -> getClassesInDir(packageName, d, scanRecursively).stream()) .collect(Collectors.toList()); } @@ -41,14 +42,22 @@ private static List getDirs(String packageName) { ); } - private static List> getClassesInDir(String packageName, File dir) { + private static List> getClassesInDir(String packageName, File dir, boolean scanRecursively) { if (!dir.exists()) { return Collections.emptyList(); } return Arrays .stream(dir.listFiles()) - .filter(f -> f.getName().endsWith(".class")) - .map(f -> fileToClass(packageName, f)) + .filter(f -> (scanRecursively && f.isDirectory()) || f.getName().endsWith(".class")) + .flatMap(f -> { + List> classes; + if(f.isDirectory()) { + classes = getClassesInDir(packageName + "." + f.getName(), f, scanRecursively); + } else { + classes = Collections.singletonList(fileToClass(packageName, f)); + } + return classes.stream(); + }) .filter(c -> !c.getName().endsWith("Test")) .collect(Collectors.toList()); } diff --git a/src/test/java/nl/jqno/equalsverifier/integration/operational/MultipleTypeEqualsVerifierTest.java b/src/test/java/nl/jqno/equalsverifier/integration/operational/MultipleTypeEqualsVerifierTest.java index 20f360f24..f240cf93d 100644 --- a/src/test/java/nl/jqno/equalsverifier/integration/operational/MultipleTypeEqualsVerifierTest.java +++ b/src/test/java/nl/jqno/equalsverifier/integration/operational/MultipleTypeEqualsVerifierTest.java @@ -16,6 +16,8 @@ import nl.jqno.equalsverifier.testhelpers.packages.correct.C; import nl.jqno.equalsverifier.testhelpers.packages.twoincorrect.IncorrectM; import nl.jqno.equalsverifier.testhelpers.packages.twoincorrect.IncorrectN; +import nl.jqno.equalsverifier.testhelpers.packages.twoincorrect.subpackage.IncorrectO; +import nl.jqno.equalsverifier.testhelpers.packages.twoincorrect.subpackage.IncorrectP; import org.junit.jupiter.api.Test; public class MultipleTypeEqualsVerifierTest { @@ -26,6 +28,8 @@ public class MultipleTypeEqualsVerifierTest { "nl.jqno.equalsverifier.testhelpers.packages.twoincorrect"; private static final String INCORRECT_M = INCORRECT_PACKAGE + ".IncorrectM"; private static final String INCORRECT_N = INCORRECT_PACKAGE + ".IncorrectN"; + private static final String INCORRECT_O = INCORRECT_PACKAGE + ".subpackage.IncorrectO"; + private static final String INCORRECT_P = INCORRECT_PACKAGE + ".subpackage.IncorrectP"; @Test public void succeed_whenVerifyingSeveralCorrectClasses_givenIterableOverload() { @@ -43,6 +47,11 @@ public void succeed_whenVerifyingACorrectPackage() { EqualsVerifier.forPackage(CORRECT_PACKAGE).verify(); } + @Test + public void succeed_whenVerifyingACorrectPackageRecursively() { + EqualsVerifier.forPackage(CORRECT_PACKAGE, true).verify(); + } + @Test public void fail_whenVerifyingOneIncorrectClass() { ExpectedException @@ -88,6 +97,22 @@ public void fail_whenVerifyingAPackageWithTwoIncorrectClasses() { ); } + @Test + public void fail_whenVerifyingAPackageRecursivelyWithFourIncorrectClasses() { + ExpectedException + .when(() -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).verify()) + .assertFailure() + .assertMessageContains( + "EqualsVerifier found a problem in 4 classes.", + "* " + INCORRECT_M, + "* " + INCORRECT_N, + "* " + INCORRECT_O, + "* " + INCORRECT_P, + "Subclass: equals is not final.", + "Reflexivity: object does not equal itself:" + ); + } + @Test public void fail_whenCallingForPackage_givenTwoClassesInPackageAreIncorrect() { ExpectedException @@ -102,6 +127,22 @@ public void fail_whenCallingForPackage_givenTwoClassesInPackageAreIncorrect() { ); } + @Test + public void fail_whenCallingForPackageRecursively_givenFourClassesInPackageAreIncorrect() { + ExpectedException + .when(() -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).verify()) + .assertFailure() + .assertMessageContains( + "EqualsVerifier found a problem in 4 classes.", + "IncorrectM", + "IncorrectN", + "IncorrectO", + "IncorrectP", + "Subclass: equals is not final.", + "Reflexivity: object does not equal itself:" + ); + } + @Test public void fail_whenCallingForPackage_whenPackageHasNoClasses() { ExpectedException @@ -113,6 +154,17 @@ public void fail_whenCallingForPackage_whenPackageHasNoClasses() { ); } + @Test + public void fail_whenCallingForPackageRecursively_whenPackageHasNoClasses() { + ExpectedException + .when(() -> EqualsVerifier.forPackage("nl.jqno.equalsverifier.doesnotexist", true)) + .assertThrows(IllegalStateException.class) + .assertMessageContains( + "nl.jqno.equalsverifier.doesnotexist", + "doesn't contain any (non-Test) types" + ); + } + @Test public void succeed_whenCallingForPackageOnAPackageContainingFailingClasses_givenFailingClassesAreExcepted() { EqualsVerifier @@ -121,6 +173,14 @@ public void succeed_whenCallingForPackageOnAPackageContainingFailingClasses_give .verify(); } + @Test + public void succeed_whenCallingForPackageRecursivelyOnAPackageContainingFailingClasses_givenFailingClassesAreExcepted() { + EqualsVerifier + .forPackage(INCORRECT_PACKAGE, true) + .except(IncorrectM.class, IncorrectN.class, IncorrectO.class, IncorrectP.class) + .verify(); + } + @Test public void fail_whenExceptingAClassThatDoesntExistInThePackage() { ExpectedException @@ -129,6 +189,14 @@ public void fail_whenExceptingAClassThatDoesntExistInThePackage() { .assertMessageContains("Unknown class(es) found", "IncorrectM"); } + @Test + public void fail_whenExceptingAClassThatDoesntExistInThePackageAndSubPackages() { + ExpectedException + .when(() -> EqualsVerifier.forPackage(CORRECT_PACKAGE, true).except(IncorrectM.class)) + .assertThrows(IllegalStateException.class) + .assertMessageContains("Unknown class(es) found", "IncorrectM"); + } + @Test public void succeed_whenCallingForPackageOnAPackageContainingFailingClasses_givenFailingClassesAreExceptedByPredicate() { EqualsVerifier @@ -137,6 +205,14 @@ public void succeed_whenCallingForPackageOnAPackageContainingFailingClasses_give .verify(); } + @Test + public void succeed_whenCallingForPackageRecursivelyOnAPackageContainingFailingClasses_givenFailingClassesAreExceptedByPredicate() { + EqualsVerifier + .forPackage(INCORRECT_PACKAGE, true) + .except(c -> c.getSimpleName().contains("Incorrect")) + .verify(); + } + @Test public void fail_whenCallingForPackageOnAPackageContainingFailingClasses_givenFailingClassesAreNotExceptedByPredicate() { ExpectedException @@ -145,11 +221,24 @@ public void fail_whenCallingForPackageOnAPackageContainingFailingClasses_givenFa .assertMessageContains("EqualsVerifier found a problem in 2 classes"); } + @Test + public void fail_whenCallingForPackageRecursivelyOnAPackageContainingFailingClasses_givenFailingClassesAreNotExceptedByPredicate() { + ExpectedException + .when(() -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).except(c -> false).verify()) + .assertFailure() + .assertMessageContains("EqualsVerifier found a problem in 4 classes"); + } + @Test public void succeed_whenCallingForPackageOnAPackageContainingFailingClasses_givenAllClassesAreExceptedByPredicate() { EqualsVerifier.forPackage(INCORRECT_PACKAGE).except(c -> true).verify(); } + @Test + public void succeed_whenCallingForPackageRecursivelyOnAPackageContainingFailingClasses_givenAllClassesAreExceptedByPredicate() { + EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).except(c -> true).verify(); + } + @Test public void succeed_whenReportingOnSeveralCorrectClasses() { List reports = EqualsVerifier diff --git a/src/test/java/nl/jqno/equalsverifier/internal/reflection/PackageScannerTest.java b/src/test/java/nl/jqno/equalsverifier/internal/reflection/PackageScannerTest.java index 4daff9b62..25a75ae12 100644 --- a/src/test/java/nl/jqno/equalsverifier/internal/reflection/PackageScannerTest.java +++ b/src/test/java/nl/jqno/equalsverifier/internal/reflection/PackageScannerTest.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; import nl.jqno.equalsverifier.testhelpers.packages.correct.*; @@ -21,17 +22,32 @@ public void coverTheConstructor() { @Test public void happyPath() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.testhelpers.packages.correct" - ); + "nl.jqno.equalsverifier.testhelpers.packages.correct", false); classes.sort((a, b) -> a.getName().compareTo(b.getName())); assertEquals(Arrays.asList(A.class, B.class, C.class), classes); } + @Test + public void happyPathRecursively() { + List> classes = PackageScanner.getClassesIn( + "nl.jqno.equalsverifier.testhelpers.packages.correct", true); + classes.sort(Comparator.comparing(Class::getName)); + assertEquals(Arrays.asList( + A.class, + B.class, + C.class, + nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.A.class, + nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.B.class, + nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage.A.class, + nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage.B.class, + nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage.D.class + ), classes); + } + @Test public void filterOutTestClasses() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.internal.reflection" - ); + "nl.jqno.equalsverifier.internal.reflection", false); List> testClasses = classes .stream() .filter(c -> c.getName().endsWith("Test")) @@ -40,11 +56,29 @@ public void filterOutTestClasses() { assertTrue(classes.size() - testClasses.size() > 0); } + @Test + public void filterOutTestClassesRecursively() { + List> classes = PackageScanner.getClassesIn( + "nl.jqno.equalsverifier.internal.reflection", true); + List> testClasses = classes + .stream() + .filter(c -> c.getName().endsWith("Test")) + .collect(Collectors.toList()); + assertEquals(Collections.emptyList(), testClasses); + assertTrue(classes.size() - testClasses.size() > 0); + } + @Test public void nonexistentPackage() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.nonexistentpackage" - ); + "nl.jqno.equalsverifier.nonexistentpackage", false); + assertEquals(Collections.emptyList(), classes); + } + + @Test + public void nonexistentPackageAndSubPackage() { + List> classes = PackageScanner.getClassesIn( + "nl.jqno.equalsverifier.nonexistentpackage", true); assertEquals(Collections.emptyList(), classes); } } diff --git a/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/A.java b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/A.java new file mode 100644 index 000000000..fd432b262 --- /dev/null +++ b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/A.java @@ -0,0 +1,31 @@ +package nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage; + +public final class A { + + private final int x; + private final int y; + + public A(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof A)) { + return false; + } + A p = (A) obj; + return p.x == x && p.y == y; + } + + @Override + public int hashCode() { + return x + (31 * y); + } + + @Override + public String toString() { + return getClass().getSimpleName() + ":" + x + "," + y; + } +} diff --git a/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/B.java b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/B.java new file mode 100644 index 000000000..6b5090a84 --- /dev/null +++ b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/B.java @@ -0,0 +1,31 @@ +package nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage; + +public final class B { + + private final int x; + private final int y; + + public B(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof B)) { + return false; + } + B p = (B) obj; + return p.x == x && p.y == y; + } + + @Override + public int hashCode() { + return x + (31 * y); + } + + @Override + public String toString() { + return getClass().getSimpleName() + ":" + x + "," + y; + } +} diff --git a/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/A.java b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/A.java new file mode 100644 index 000000000..995b7c6c4 --- /dev/null +++ b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/A.java @@ -0,0 +1,31 @@ +package nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage; + +public final class A { + + private final int x; + private final int y; + + public A(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof A)) { + return false; + } + A p = (A) obj; + return p.x == x && p.y == y; + } + + @Override + public int hashCode() { + return x + (31 * y); + } + + @Override + public String toString() { + return getClass().getSimpleName() + ":" + x + "," + y; + } +} diff --git a/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/B.java b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/B.java new file mode 100644 index 000000000..c05943907 --- /dev/null +++ b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/B.java @@ -0,0 +1,31 @@ +package nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage; + +public final class B { + + private final int x; + private final int y; + + public B(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof B)) { + return false; + } + B p = (B) obj; + return p.x == x && p.y == y; + } + + @Override + public int hashCode() { + return x + (31 * y); + } + + @Override + public String toString() { + return getClass().getSimpleName() + ":" + x + "," + y; + } +} diff --git a/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/D.java b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/D.java new file mode 100644 index 000000000..3b7d05b72 --- /dev/null +++ b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/correct/subpackage/subpackage/D.java @@ -0,0 +1,31 @@ +package nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage; + +public final class D { + + private final int x; + private final int y; + + public D(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof D)) { + return false; + } + D p = (D) obj; + return p.x == x && p.y == y; + } + + @Override + public int hashCode() { + return x + (31 * y); + } + + @Override + public String toString() { + return getClass().getSimpleName() + ":" + x + "," + y; + } +} diff --git a/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/twoincorrect/subpackage/IncorrectO.java b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/twoincorrect/subpackage/IncorrectO.java new file mode 100644 index 000000000..220d56432 --- /dev/null +++ b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/twoincorrect/subpackage/IncorrectO.java @@ -0,0 +1,31 @@ +package nl.jqno.equalsverifier.testhelpers.packages.twoincorrect.subpackage; + +public class IncorrectO { + + private final int x; + private final int y; + + public IncorrectO(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IncorrectO)) { + return false; + } + IncorrectO p = (IncorrectO) obj; + return p.x == x && p.y == y; + } + + @Override + public int hashCode() { + return x + (31 * y); + } + + @Override + public String toString() { + return getClass().getSimpleName() + ":" + x + "," + y; + } +} diff --git a/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/twoincorrect/subpackage/IncorrectP.java b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/twoincorrect/subpackage/IncorrectP.java new file mode 100644 index 000000000..fc9ef21f0 --- /dev/null +++ b/src/test/java/nl/jqno/equalsverifier/testhelpers/packages/twoincorrect/subpackage/IncorrectP.java @@ -0,0 +1,31 @@ +package nl.jqno.equalsverifier.testhelpers.packages.twoincorrect.subpackage; + +public final class IncorrectP { + + private final int x; + private final int y; + + public IncorrectP(int x, int y) { + this.x = x; + this.y = y; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IncorrectP)) { + return false; + } + IncorrectP p = (IncorrectP) obj; + return p.x == x && p.y != y; + } + + @Override + public int hashCode() { + return x + (31 * y); + } + + @Override + public String toString() { + return getClass().getSimpleName() + ":" + x + "," + y; + } +} From ad425e4cdddd259658861f0f85a0d819a5191622 Mon Sep 17 00:00:00 2001 From: Nicolas Dos Santos Date: Sun, 18 Apr 2021 14:53:45 +0200 Subject: [PATCH 2/2] fix formatting with 'mvn spotless:apply' --- .../jqno/equalsverifier/EqualsVerifier.java | 5 +- .../internal/reflection/PackageScanner.java | 25 ++++-- .../MultipleTypeEqualsVerifierTest.java | 82 ++++++++++--------- .../reflection/PackageScannerTest.java | 37 ++++++--- 4 files changed, 88 insertions(+), 61 deletions(-) diff --git a/src/main/java/nl/jqno/equalsverifier/EqualsVerifier.java b/src/main/java/nl/jqno/equalsverifier/EqualsVerifier.java index 9bd156dfb..9c61161bc 100644 --- a/src/main/java/nl/jqno/equalsverifier/EqualsVerifier.java +++ b/src/main/java/nl/jqno/equalsverifier/EqualsVerifier.java @@ -126,7 +126,10 @@ public static MultipleTypeEqualsVerifierApi forPackage(String packageName) { * @param scanRecursively true to scan all sub-packages * @return A fluent API for EqualsVerifier. */ - public static MultipleTypeEqualsVerifierApi forPackage(String packageName, boolean scanRecursively) { + public static MultipleTypeEqualsVerifierApi forPackage( + String packageName, + boolean scanRecursively + ) { List> classes = PackageScanner.getClassesIn(packageName, scanRecursively); Validations.validatePackageContainsClasses(packageName, classes); return new MultipleTypeEqualsVerifierApi(classes, new ConfiguredEqualsVerifier()); diff --git a/src/main/java/nl/jqno/equalsverifier/internal/reflection/PackageScanner.java b/src/main/java/nl/jqno/equalsverifier/internal/reflection/PackageScanner.java index 09b5169a9..6c6481e90 100644 --- a/src/main/java/nl/jqno/equalsverifier/internal/reflection/PackageScanner.java +++ b/src/main/java/nl/jqno/equalsverifier/internal/reflection/PackageScanner.java @@ -42,22 +42,29 @@ private static List getDirs(String packageName) { ); } - private static List> getClassesInDir(String packageName, File dir, boolean scanRecursively) { + private static List> getClassesInDir( + String packageName, + File dir, + boolean scanRecursively + ) { if (!dir.exists()) { return Collections.emptyList(); } return Arrays .stream(dir.listFiles()) .filter(f -> (scanRecursively && f.isDirectory()) || f.getName().endsWith(".class")) - .flatMap(f -> { - List> classes; - if(f.isDirectory()) { - classes = getClassesInDir(packageName + "." + f.getName(), f, scanRecursively); - } else { - classes = Collections.singletonList(fileToClass(packageName, f)); + .flatMap( + f -> { + List> classes; + if (f.isDirectory()) { + classes = + getClassesInDir(packageName + "." + f.getName(), f, scanRecursively); + } else { + classes = Collections.singletonList(fileToClass(packageName, f)); + } + return classes.stream(); } - return classes.stream(); - }) + ) .filter(c -> !c.getName().endsWith("Test")) .collect(Collectors.toList()); } diff --git a/src/test/java/nl/jqno/equalsverifier/integration/operational/MultipleTypeEqualsVerifierTest.java b/src/test/java/nl/jqno/equalsverifier/integration/operational/MultipleTypeEqualsVerifierTest.java index f240cf93d..1316155cb 100644 --- a/src/test/java/nl/jqno/equalsverifier/integration/operational/MultipleTypeEqualsVerifierTest.java +++ b/src/test/java/nl/jqno/equalsverifier/integration/operational/MultipleTypeEqualsVerifierTest.java @@ -100,17 +100,17 @@ public void fail_whenVerifyingAPackageWithTwoIncorrectClasses() { @Test public void fail_whenVerifyingAPackageRecursivelyWithFourIncorrectClasses() { ExpectedException - .when(() -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).verify()) - .assertFailure() - .assertMessageContains( - "EqualsVerifier found a problem in 4 classes.", - "* " + INCORRECT_M, - "* " + INCORRECT_N, - "* " + INCORRECT_O, - "* " + INCORRECT_P, - "Subclass: equals is not final.", - "Reflexivity: object does not equal itself:" - ); + .when(() -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).verify()) + .assertFailure() + .assertMessageContains( + "EqualsVerifier found a problem in 4 classes.", + "* " + INCORRECT_M, + "* " + INCORRECT_N, + "* " + INCORRECT_O, + "* " + INCORRECT_P, + "Subclass: equals is not final.", + "Reflexivity: object does not equal itself:" + ); } @Test @@ -130,17 +130,17 @@ public void fail_whenCallingForPackage_givenTwoClassesInPackageAreIncorrect() { @Test public void fail_whenCallingForPackageRecursively_givenFourClassesInPackageAreIncorrect() { ExpectedException - .when(() -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).verify()) - .assertFailure() - .assertMessageContains( - "EqualsVerifier found a problem in 4 classes.", - "IncorrectM", - "IncorrectN", - "IncorrectO", - "IncorrectP", - "Subclass: equals is not final.", - "Reflexivity: object does not equal itself:" - ); + .when(() -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).verify()) + .assertFailure() + .assertMessageContains( + "EqualsVerifier found a problem in 4 classes.", + "IncorrectM", + "IncorrectN", + "IncorrectO", + "IncorrectP", + "Subclass: equals is not final.", + "Reflexivity: object does not equal itself:" + ); } @Test @@ -157,12 +157,12 @@ public void fail_whenCallingForPackage_whenPackageHasNoClasses() { @Test public void fail_whenCallingForPackageRecursively_whenPackageHasNoClasses() { ExpectedException - .when(() -> EqualsVerifier.forPackage("nl.jqno.equalsverifier.doesnotexist", true)) - .assertThrows(IllegalStateException.class) - .assertMessageContains( - "nl.jqno.equalsverifier.doesnotexist", - "doesn't contain any (non-Test) types" - ); + .when(() -> EqualsVerifier.forPackage("nl.jqno.equalsverifier.doesnotexist", true)) + .assertThrows(IllegalStateException.class) + .assertMessageContains( + "nl.jqno.equalsverifier.doesnotexist", + "doesn't contain any (non-Test) types" + ); } @Test @@ -176,9 +176,9 @@ public void succeed_whenCallingForPackageOnAPackageContainingFailingClasses_give @Test public void succeed_whenCallingForPackageRecursivelyOnAPackageContainingFailingClasses_givenFailingClassesAreExcepted() { EqualsVerifier - .forPackage(INCORRECT_PACKAGE, true) - .except(IncorrectM.class, IncorrectN.class, IncorrectO.class, IncorrectP.class) - .verify(); + .forPackage(INCORRECT_PACKAGE, true) + .except(IncorrectM.class, IncorrectN.class, IncorrectO.class, IncorrectP.class) + .verify(); } @Test @@ -192,9 +192,9 @@ public void fail_whenExceptingAClassThatDoesntExistInThePackage() { @Test public void fail_whenExceptingAClassThatDoesntExistInThePackageAndSubPackages() { ExpectedException - .when(() -> EqualsVerifier.forPackage(CORRECT_PACKAGE, true).except(IncorrectM.class)) - .assertThrows(IllegalStateException.class) - .assertMessageContains("Unknown class(es) found", "IncorrectM"); + .when(() -> EqualsVerifier.forPackage(CORRECT_PACKAGE, true).except(IncorrectM.class)) + .assertThrows(IllegalStateException.class) + .assertMessageContains("Unknown class(es) found", "IncorrectM"); } @Test @@ -208,9 +208,9 @@ public void succeed_whenCallingForPackageOnAPackageContainingFailingClasses_give @Test public void succeed_whenCallingForPackageRecursivelyOnAPackageContainingFailingClasses_givenFailingClassesAreExceptedByPredicate() { EqualsVerifier - .forPackage(INCORRECT_PACKAGE, true) - .except(c -> c.getSimpleName().contains("Incorrect")) - .verify(); + .forPackage(INCORRECT_PACKAGE, true) + .except(c -> c.getSimpleName().contains("Incorrect")) + .verify(); } @Test @@ -224,9 +224,11 @@ public void fail_whenCallingForPackageOnAPackageContainingFailingClasses_givenFa @Test public void fail_whenCallingForPackageRecursivelyOnAPackageContainingFailingClasses_givenFailingClassesAreNotExceptedByPredicate() { ExpectedException - .when(() -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).except(c -> false).verify()) - .assertFailure() - .assertMessageContains("EqualsVerifier found a problem in 4 classes"); + .when( + () -> EqualsVerifier.forPackage(INCORRECT_PACKAGE, true).except(c -> false).verify() + ) + .assertFailure() + .assertMessageContains("EqualsVerifier found a problem in 4 classes"); } @Test diff --git a/src/test/java/nl/jqno/equalsverifier/internal/reflection/PackageScannerTest.java b/src/test/java/nl/jqno/equalsverifier/internal/reflection/PackageScannerTest.java index 25a75ae12..b175a18a9 100644 --- a/src/test/java/nl/jqno/equalsverifier/internal/reflection/PackageScannerTest.java +++ b/src/test/java/nl/jqno/equalsverifier/internal/reflection/PackageScannerTest.java @@ -22,7 +22,9 @@ public void coverTheConstructor() { @Test public void happyPath() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.testhelpers.packages.correct", false); + "nl.jqno.equalsverifier.testhelpers.packages.correct", + false + ); classes.sort((a, b) -> a.getName().compareTo(b.getName())); assertEquals(Arrays.asList(A.class, B.class, C.class), classes); } @@ -30,9 +32,12 @@ public void happyPath() { @Test public void happyPathRecursively() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.testhelpers.packages.correct", true); + "nl.jqno.equalsverifier.testhelpers.packages.correct", + true + ); classes.sort(Comparator.comparing(Class::getName)); - assertEquals(Arrays.asList( + assertEquals( + Arrays.asList( A.class, B.class, C.class, @@ -41,13 +46,17 @@ public void happyPathRecursively() { nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage.A.class, nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage.B.class, nl.jqno.equalsverifier.testhelpers.packages.correct.subpackage.subpackage.D.class - ), classes); + ), + classes + ); } @Test public void filterOutTestClasses() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.internal.reflection", false); + "nl.jqno.equalsverifier.internal.reflection", + false + ); List> testClasses = classes .stream() .filter(c -> c.getName().endsWith("Test")) @@ -59,11 +68,13 @@ public void filterOutTestClasses() { @Test public void filterOutTestClassesRecursively() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.internal.reflection", true); + "nl.jqno.equalsverifier.internal.reflection", + true + ); List> testClasses = classes - .stream() - .filter(c -> c.getName().endsWith("Test")) - .collect(Collectors.toList()); + .stream() + .filter(c -> c.getName().endsWith("Test")) + .collect(Collectors.toList()); assertEquals(Collections.emptyList(), testClasses); assertTrue(classes.size() - testClasses.size() > 0); } @@ -71,14 +82,18 @@ public void filterOutTestClassesRecursively() { @Test public void nonexistentPackage() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.nonexistentpackage", false); + "nl.jqno.equalsverifier.nonexistentpackage", + false + ); assertEquals(Collections.emptyList(), classes); } @Test public void nonexistentPackageAndSubPackage() { List> classes = PackageScanner.getClassesIn( - "nl.jqno.equalsverifier.nonexistentpackage", true); + "nl.jqno.equalsverifier.nonexistentpackage", + true + ); assertEquals(Collections.emptyList(), classes); } }