diff --git a/pom.xml b/pom.xml index d864b2e4e6..fab78c65a0 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 4.1.0-SNAPSHOT + 4.1.0-archunit-dependency-tests-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index 1b2a1390e6..3f405e43be 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 4.1.0-SNAPSHOT + 4.1.0-archunit-dependency-tests-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 8db8d798fb..064351f06a 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -15,7 +15,7 @@ org.springframework.data spring-data-mongodb-parent - 4.1.0-SNAPSHOT + 4.1.0-archunit-dependency-tests-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 9a57f7eb52..6814d94000 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -13,7 +13,7 @@ org.springframework.data spring-data-mongodb-parent - 4.1.0-SNAPSHOT + 4.1.0-archunit-dependency-tests-SNAPSHOT ../pom.xml @@ -23,6 +23,7 @@ spring.data.mongodb ${basedir}/.. 1.01 + 1.0.1 @@ -250,9 +251,9 @@ - de.schauderhaft.degraph - degraph-check - 0.1.4 + com.tngtech.archunit + archunit + ${archunit.version} test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java index 00d5b63551..e9b53b178b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/DependencyTests.java @@ -15,12 +15,16 @@ */ package org.springframework.data.mongodb; -import static de.schauderhaft.degraph.check.JCheck.*; -import static org.hamcrest.MatcherAssert.*; - -import de.schauderhaft.degraph.configuration.NamedPattern; - -import org.junit.jupiter.api.Disabled; +import com.tngtech.archunit.base.DescribedPredicate; +import com.tngtech.archunit.core.domain.JavaClass; +import com.tngtech.archunit.core.domain.JavaClasses; +import com.tngtech.archunit.core.importer.ClassFileImporter; +import com.tngtech.archunit.core.importer.ImportOption; +import com.tngtech.archunit.lang.ArchRule; +import com.tngtech.archunit.library.dependencies.SliceAssignment; +import com.tngtech.archunit.library.dependencies.SliceIdentifier; +import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition; +import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; /** @@ -29,49 +33,138 @@ * @author Jens Schauder * @author Oliver Gierke */ -@Disabled("Needs to be tansitioned to ArchUnit") class DependencyTests { @Test - void noInternalPackageCycles() { - - assertThat(classpath() // - .noJars() // - .including("org.springframework.data.mongodb.**") // - .filterClasspath("*target/classes") // - .printOnFailure("degraph.graphml"), // - violationFree() // - ); + void cycleFree() { + + JavaClasses importedClasses = new ClassFileImporter() // + .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) // + .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_JARS) // we just analyze the code of this module. + .importPackages("org.springframework.data.mongodb").that( // + onlySpringData() // + ); + + ArchRule rule = SlicesRuleDefinition.slices() // + .matching("org.springframework.data.mongodb.(**)") // + .should() // + .beFreeOfCycles(); + + rule.check(importedClasses); + } + + @Test + void acrossModules() { + + JavaClasses importedClasses = new ClassFileImporter().withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) + .importPackages( // + "org.springframework.data.mongodb", // Spring Data Relational + "org.springframework.data" // Spring Data Commons + ).that(onlySpringData()); + + ArchRule rule = SlicesRuleDefinition.slices() // + .assignedFrom(subModuleSlicing()) // + .should().beFreeOfCycles(); + + rule.check(importedClasses); } @Test - void onlyConfigMayUseRepository() { - - assertThat(classpath() // - .including("org.springframework.data.**") // - .filterClasspath("*target/classes") // - .printOnFailure("onlyConfigMayUseRepository.graphml") // - .withSlicing("slices", // - "**.(config).**", // - new NamedPattern("**.cdi.**", "config"), // - "**.(repository).**", // - new NamedPattern("**", "other")) - .allow("config", "repository", "other"), // - violationFree() // - ); + // GH-1058 + void testGetFirstPackagePart() { + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(getFirstPackagePart("a.b.c")).isEqualTo("a"); + softly.assertThat(getFirstPackagePart("a")).isEqualTo("a"); + }); } @Test - void commonsInternaly() { - - assertThat(classpath() // - .noJars() // - .including("org.springframework.data.**") // - .excluding("org.springframework.data.mongodb.**") // - .filterClasspath("*target/classes") // - .printTo("commons.graphml"), // - violationFree() // - ); + // GH-1058 + void testSubModule() { + + SoftAssertions.assertSoftly(softly -> { + softly.assertThat(subModule("a.b", "a.b.c.d")).isEqualTo("c"); + softly.assertThat(subModule("a.b", "a.b.c")).isEqualTo("c"); + softly.assertThat(subModule("a.b", "a.b")).isEqualTo(""); + }); + } + + private DescribedPredicate onlySpringData() { + + return new DescribedPredicate<>("Spring Data Classes") { + @Override + public boolean test(JavaClass input) { + return input.getPackageName().startsWith("org.springframework.data"); + } + }; + } + + private DescribedPredicate ignore(Class type) { + + return new DescribedPredicate<>("ignored class " + type.getName()) { + @Override + public boolean test(JavaClass input) { + return !input.getFullName().startsWith(type.getName()); + } + }; + } + + private DescribedPredicate ignorePackage(String type) { + + return new DescribedPredicate<>("ignored class " + type) { + @Override + public boolean test(JavaClass input) { + return !input.getPackageName().equals(type); + } + }; + } + + private String getFirstPackagePart(String subpackage) { + + int index = subpackage.indexOf("."); + if (index < 0) { + return subpackage; + } + return subpackage.substring(0, index); + } + + private String subModule(String basePackage, String packageName) { + + if (packageName.startsWith(basePackage) && packageName.length() > basePackage.length()) { + + final int index = basePackage.length() + 1; + String subpackage = packageName.substring(index); + return getFirstPackagePart(subpackage); + } + return ""; } + private SliceAssignment subModuleSlicing() { + return new SliceAssignment() { + + @Override + public SliceIdentifier getIdentifierOf(JavaClass javaClass) { + + String packageName = javaClass.getPackageName(); + + String subModule = subModule("org.springframework.data.mongodb", packageName); + if (!subModule.isEmpty()) { + return SliceIdentifier.of(subModule); + } + + subModule = subModule("org.springframework.data", packageName); + if (!subModule.isEmpty()) { + return SliceIdentifier.of(subModule); + } + + return SliceIdentifier.ignore(); + } + + @Override + public String getDescription() { + return "Submodule"; + } + }; + } }