diff options
author | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2022-11-14 11:07:52 +0100 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2022-11-14 11:08:50 +0100 |
commit | 91ae1fb4acd2c61bf3effaa7af05a52eff4223ce (patch) | |
tree | 2da5cae63faec9811d61a08ad777f82ed5563917 | |
parent | 2e3d84ed44caa36214cff7ac0ff9c4b874643dcb (diff) |
Classify dependencies based on test vs non-test usage
6 files changed, 173 insertions, 82 deletions
diff --git a/maven-plugins/allowed-maven-dependencies.txt b/maven-plugins/allowed-maven-dependencies.txt index 11b8c23e9e0..b0f97265541 100644 --- a/maven-plugins/allowed-maven-dependencies.txt +++ b/maven-plugins/allowed-maven-dependencies.txt @@ -1,4 +1,7 @@ # Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#[non-test] +# Contains dependencies that are not used exclusively in 'test' scope aopalliance:aopalliance:1.0 com.fasterxml.jackson.core:jackson-annotations:2.14.0 com.fasterxml.jackson.core:jackson-core:2.14.0 @@ -14,9 +17,6 @@ javax.annotation:javax.annotation-api:1.2 javax.annotation:jsr250-api:1.0 javax.enterprise:cdi-api:1.0 javax.inject:javax.inject:1 -junit:junit:4.13.2 -net.bytebuddy:byte-buddy:1.11.19 -net.bytebuddy:byte-buddy-agent:1.11.19 org.apache.commons:commons-compress:1.21 org.apache.commons:commons-lang3:3.5 org.apache.commons:commons-lang3:3.8.1 @@ -54,7 +54,6 @@ org.apache.maven.shared:maven-dependency-tree:3.1.1 org.apache.maven.shared:maven-shared-utils:3.1.0 org.apache.maven.shared:maven-shared-utils:3.3.3 org.apache.maven.shared:maven-shared-utils:3.3.4 -org.apiguardian:apiguardian-api:1.1.2 org.codehaus.plexus:plexus-archiver:4.2.7 org.codehaus.plexus:plexus-cipher:2.0 org.codehaus.plexus:plexus-classworlds:2.5.2 @@ -73,9 +72,23 @@ org.eclipse.sisu:org.eclipse.sisu.inject:0.3.3 org.eclipse.sisu:org.eclipse.sisu.inject:0.3.5 org.eclipse.sisu:org.eclipse.sisu.plexus:0.3.3 org.eclipse.sisu:org.eclipse.sisu.plexus:0.3.5 +org.iq80.snappy:snappy:0.4 +org.ow2.asm:asm:9.3 +org.slf4j:slf4j-api:1.7.32 +org.slf4j:slf4j-simple:1.7.22 +org.sonatype.plexus:plexus-cipher:1.4 +org.sonatype.plexus:plexus-sec-dispatcher:1.4 +org.tukaani:xz:1.9 +org.twdata.maven:mojo-executor:2.3.0 + +#[test-only] +# Contains dependencies that are used exclusively in 'test' scope +junit:junit:4.13.2 +net.bytebuddy:byte-buddy:1.11.19 +net.bytebuddy:byte-buddy-agent:1.11.19 +org.apiguardian:apiguardian-api:1.1.2 org.hamcrest:hamcrest-all:1.3 org.hamcrest:hamcrest-core:1.3 -org.iq80.snappy:snappy:0.4 org.junit.jupiter:junit-jupiter:5.8.1 org.junit.jupiter:junit-jupiter-api:5.8.1 org.junit.jupiter:junit-jupiter-engine:5.8.1 @@ -85,10 +98,3 @@ org.junit.platform:junit-platform-engine:1.8.1 org.mockito:mockito-core:4.0.0 org.objenesis:objenesis:3.2 org.opentest4j:opentest4j:1.2.0 -org.ow2.asm:asm:9.3 -org.slf4j:slf4j-api:1.7.32 -org.slf4j:slf4j-simple:1.7.22 -org.sonatype.plexus:plexus-cipher:1.4 -org.sonatype.plexus:plexus-sec-dispatcher:1.4 -org.tukaani:xz:1.9 -org.twdata.maven:mojo-executor:2.3.0 diff --git a/vespa-dependencies-enforcer/allowed-maven-dependencies.txt b/vespa-dependencies-enforcer/allowed-maven-dependencies.txt index 114f75acc0b..459033e387e 100644 --- a/vespa-dependencies-enforcer/allowed-maven-dependencies.txt +++ b/vespa-dependencies-enforcer/allowed-maven-dependencies.txt @@ -1,4 +1,7 @@ # Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#[non-test] +# Contains dependencies that are not used exclusively in 'test' scope aopalliance:aopalliance:1.0 backport-util-concurrent:backport-util-concurrent:3.1 biz.aQute.bnd:biz.aQute.bnd.util:6.1.0 @@ -21,17 +24,13 @@ com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:2.14.0 com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.14.0 com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.14.0 com.github.spotbugs:spotbugs-annotations:3.1.9 -com.github.tomakehurst:wiremock-jre8-standalone:2.35.0 com.google.code.findbugs:jsr305:3.0.2 com.google.errorprone:error_prone_annotations:2.2.0 com.google.guava:failureaccess:1.0.1 com.google.guava:guava:27.1-jre -com.google.guava:guava-testlib:27.1-jre com.google.inject:guice:4.2.3 com.google.inject:guice:4.2.3:no_aop com.google.j2objc:j2objc-annotations:1.1 -com.google.jimfs:jimfs:1.1 -com.google.jimfs:jimfs:1.2 com.google.protobuf:protobuf-java:3.21.7 com.ibm.icu:icu4j:70.1 com.intellij:annotations:9.0.4 @@ -80,9 +79,6 @@ javax.ws.rs:javax.ws.rs-api:2.0 javax.ws.rs:javax.ws.rs-api:2.0.1 javax.xml.bind:jaxb-api:2.3.0 joda-time:joda-time:2.8.1 -junit:junit:4.13.2 -net.bytebuddy:byte-buddy:1.11.19 -net.bytebuddy:byte-buddy-agent:1.11.19 net.java.dev.jna:jna:5.11.0 org.antlr:antlr-runtime:3.5.2 org.antlr:antlr4-runtime:4.9.3 @@ -96,7 +92,6 @@ org.apache.commons:commons-math3:3.6.1 org.apache.curator:curator-client:5.3.0 org.apache.curator:curator-framework:5.3.0 org.apache.curator:curator-recipes:5.3.0 -org.apache.curator:curator-test:5.3.0 org.apache.felix:org.apache.felix.framework:7.0.1 org.apache.felix:org.apache.felix.log:1.0.1 org.apache.httpcomponents:httpclient:4.5.13 @@ -140,11 +135,9 @@ org.apache.yetus:audience-annotations:0.12.0 org.apache.zookeeper:zookeeper:3.8.0 org.apache.zookeeper:zookeeper-jute:3.8.0 org.apiguardian:apiguardian-api:1.1.2 -org.assertj:assertj-core:3.11.1 org.bouncycastle:bcpkix-jdk18on:1.72 org.bouncycastle:bcprov-jdk18on:1.72 org.bouncycastle:bcutil-jdk18on:1.72 -org.checkerframework:checker-qual:2.5.2 org.codehaus.plexus:plexus-archiver:4.2.1 org.codehaus.plexus:plexus-cipher:2.0 org.codehaus.plexus:plexus-classworlds:2.6.0 @@ -155,8 +148,6 @@ org.codehaus.plexus:plexus-interpolation:1.26 org.codehaus.plexus:plexus-io:3.2.0 org.codehaus.plexus:plexus-sec-dispatcher:2.0 org.codehaus.plexus:plexus-utils:3.3.0 -org.codehaus.plexus:plexus-utils:3.3.1 -org.cthul:cthul-matchers:1.0 org.eclipse.collections:eclipse-collections:11.0.0 org.eclipse.collections:eclipse-collections-api:11.0.0 org.eclipse.jetty:jetty-alpn-java-server:9.4.49.v20220914 @@ -195,28 +186,19 @@ org.glassfish.jersey.ext:jersey-entity-filtering:2.25 org.glassfish.jersey.ext:jersey-proxy-client:2.25 org.glassfish.jersey.media:jersey-media-json-jackson:2.25 org.glassfish.jersey.media:jersey-media-multipart:2.25 -org.hamcrest:hamcrest-all:1.3 -org.hamcrest:hamcrest-core:1.3 -org.hamcrest:hamcrest-library:1.3 org.hdrhistogram:HdrHistogram:2.1.12 org.iq80.snappy:snappy:0.4 org.javassist:javassist:3.20.0-GA org.json:json:20220320 -org.junit.jupiter:junit-jupiter:5.8.1 org.junit.jupiter:junit-jupiter-api:5.8.1 org.junit.jupiter:junit-jupiter-engine:5.8.1 -org.junit.jupiter:junit-jupiter-params:5.8.1 org.junit.platform:junit-platform-commons:1.8.1 org.junit.platform:junit-platform-engine:1.8.1 org.junit.platform:junit-platform-launcher:1.8.1 -org.junit.vintage:junit-vintage-engine:5.8.1 org.jvnet.mimepull:mimepull:1.9.6 org.jvnet.staxex:stax-ex:1.8.1 org.kohsuke:libpam4j:1.11 org.lz4:lz4-java:1.8.0 -org.mockito:mockito-core:4.0.0 -org.mockito:mockito-junit-jupiter:4.0.0 -org.objenesis:objenesis:3.2 org.opentest4j:opentest4j:1.2.0 org.osgi:org.osgi.compendium:4.1.0 org.osgi:org.osgi.core:4.1.0 @@ -240,4 +222,28 @@ org.xerial.snappy:snappy-java:1.1.7 software.amazon.ion:ion-java:1.0.2 xerces:xercesImpl:2.12.2 xml-apis:xml-apis:1.4.01 + +#[test-only] +# Contains dependencies that are used exclusively in 'test' scope +com.github.tomakehurst:wiremock-jre8-standalone:2.35.0 +com.google.guava:guava-testlib:27.1-jre +com.google.jimfs:jimfs:1.1 +com.google.jimfs:jimfs:1.2 +junit:junit:4.13.2 +net.bytebuddy:byte-buddy:1.11.19 +net.bytebuddy:byte-buddy-agent:1.11.19 +org.apache.curator:curator-test:5.3.0 +org.assertj:assertj-core:3.11.1 +org.checkerframework:checker-qual:2.5.2 +org.codehaus.plexus:plexus-utils:3.3.1 +org.cthul:cthul-matchers:1.0 +org.hamcrest:hamcrest-all:1.3 +org.hamcrest:hamcrest-core:1.3 +org.hamcrest:hamcrest-library:1.3 +org.junit.jupiter:junit-jupiter:5.8.1 +org.junit.jupiter:junit-jupiter-params:5.8.1 +org.junit.vintage:junit-vintage-engine:5.8.1 +org.mockito:mockito-core:4.0.0 +org.mockito:mockito-junit-jupiter:4.0.0 +org.objenesis:objenesis:3.2 xmlunit:xmlunit:1.5 diff --git a/vespa-dependencies-enforcer/pom.xml b/vespa-dependencies-enforcer/pom.xml index a4f73991a64..a0e6dc19ccb 100644 --- a/vespa-dependencies-enforcer/pom.xml +++ b/vespa-dependencies-enforcer/pom.xml @@ -46,6 +46,14 @@ <i>com.yahoo.vespa.bundle-plugin:*:*</i> <i>com.yahoo.vespa.jdisc_core:*:*</i> </ignored> + + <!-- Classifly all dependencies of below modules as 'test' --> + <testUtilProjects> + <!-- Misc --> + <i>com.yahoo.vespa:testutil</i> + <!-- Bundle plugin integration test --> + <i>com.yahoo.vespa.bundle-plugin:*</i> + </testUtilProjects> </enforceDependencies> </rules> <fail>true</fail> diff --git a/vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java b/vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java index 6a9d5c5e123..82c705c4611 100644 --- a/vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java +++ b/vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java @@ -37,21 +37,25 @@ import java.util.stream.Stream; public class EnforceDependenciesAllProjects implements EnforcerRule { private static final String WRITE_SPEC_PROP = "dependencyEnforcer.writeSpec"; + private static final String NON_TEST_HEADER = "#[non-test]"; + private static final String TEST_ONLY_HEADER = "#[test-only]"; private String specFile; - private List<String> ignored; + private List<String> ignored = List.of(); + private List<String> testUtilProjects = List.of(); @Override public void execute(EnforcerRuleHelper helper) throws EnforcerRuleException { Log log = helper.getLog(); - SortedSet<Dependency> dependencies = getDependenciesOfAllProjects(helper, ignored); - log.info("Found %d unique dependencies".formatted(dependencies.size())); + Dependencies deps = getDependenciesOfAllProjects(helper, ignored, testUtilProjects); + log.info("Found %d unique dependencies (%d non-test, %d test only)".formatted( + deps.nonTest().size() + deps.testOnly().size(), deps.nonTest().size(), deps.testOnly().size())); Path specFile = resolveSpecFile(helper, this.specFile); if (System.getProperties().containsKey(WRITE_SPEC_PROP)) { - writeDependencySpec(specFile, dependencies); + writeDependencySpec(specFile, deps); log.info("Updated spec file '%s'".formatted(specFile.toString())); } else { - validateDependencies(dependencies, specFile, aggregatorPomRoot(helper), projectName(helper)); + validateDependencies(deps, specFile, aggregatorPomRoot(helper), projectName(helper)); } log.info("The dependency enforcer completed successfully"); } @@ -61,6 +65,8 @@ public class EnforceDependenciesAllProjects implements EnforcerRule { @SuppressWarnings("unused") public String getSpecFile() { return specFile; } @SuppressWarnings("unused") public void setIgnored(List<String> l) { this.ignored = l; } @SuppressWarnings("unused") public List<String> getIgnored() { return ignored; } + @SuppressWarnings("unused") public void setTestUtilProjects(List<String> l) { this.testUtilProjects = l; } + @SuppressWarnings("unused") public List<String> getTestUtilProjects() { return testUtilProjects; } record Dependency(String groupId, String artifactId, String version, Optional<String> classifier) implements Comparable<Dependency> { @@ -88,24 +94,16 @@ public class EnforceDependenciesAllProjects implements EnforcerRule { @Override public int compareTo(Dependency o) { return COMPARATOR.compare(this, o); } } - static void validateDependencies(SortedSet<Dependency> dependencies, Path specFile, Path aggregatorPomRoot, + record Dependencies(SortedSet<Dependency> nonTest, SortedSet<Dependency> testOnly) {} + + static void validateDependencies(Dependencies dependencies, Path specFile, Path aggregatorPomRoot, String moduleName) throws EnforcerRuleException { - SortedSet<Dependency> allowedDependencies = loadDependencySpec(specFile); - SortedSet<Dependency> forbiddenDependencies = new TreeSet<>(dependencies); - forbiddenDependencies.removeAll(allowedDependencies); - SortedSet<Dependency> removeDependencies = new TreeSet<>(allowedDependencies); - removeDependencies.removeAll(dependencies); - if (!forbiddenDependencies.isEmpty() || !removeDependencies.isEmpty()) { + Dependencies allowedDependencies = loadDependencySpec(specFile); + if (!allowedDependencies.equals(dependencies)) { StringBuilder errorMsg = new StringBuilder("The dependency enforcer failed:\n"); - if (!forbiddenDependencies.isEmpty()) { - errorMsg.append("Forbidden dependencies:\n"); - forbiddenDependencies.forEach(d -> errorMsg.append(" - ").append(d.asString()).append('\n')); - } - if (!removeDependencies.isEmpty()) { - errorMsg.append("Removed dependencies:\n"); - removeDependencies.forEach(d -> errorMsg.append(" - ").append(d.asString()).append('\n')); - } + generateDiff(errorMsg, "non-test", dependencies.nonTest(), allowedDependencies.nonTest()); + generateDiff(errorMsg, "test-only", dependencies.testOnly(), allowedDependencies.testOnly()); throw new EnforcerRuleException( errorMsg.append("Maven dependency validation failed. ") .append("If this change was intentional, update the dependency spec by running:\n") @@ -114,14 +112,36 @@ public class EnforceDependenciesAllProjects implements EnforcerRule { } } - private static SortedSet<Dependency> getDependenciesOfAllProjects(EnforcerRuleHelper helper, List<String> ignored) + static void generateDiff( + StringBuilder errorMsg, String label, SortedSet<Dependency> actual, SortedSet<Dependency> expected) { + SortedSet<Dependency> forbidden = new TreeSet<>(actual); + forbidden.removeAll(expected); + SortedSet<Dependency> removed = new TreeSet<>(expected); + removed.removeAll(actual); + if (!forbidden.isEmpty()) { + errorMsg.append("Forbidden ").append(label).append(" dependencies:\n"); + forbidden.forEach(d -> errorMsg.append(" - ").append(d.asString()).append('\n')); + } + if (!removed.isEmpty()) { + errorMsg.append("Removed ").append(label).append(" dependencies:\n"); + removed.forEach(d -> errorMsg.append(" - ").append(d.asString()).append('\n')); + } + } + + private static Dependencies getDependenciesOfAllProjects(EnforcerRuleHelper helper, List<String> ignored, + List<String> testUtilProjects) throws EnforcerRuleException { try { - Pattern ignorePattern = Pattern.compile( + Pattern depIgnorePattern = Pattern.compile( ignored.stream() .map(s -> s.replace(".", "\\.").replace("*", ".*").replace(":", "\\:").replace('?', '.')) .collect(Collectors.joining(")|(", "^(", ")$"))); - SortedSet<Dependency> dependencies = new TreeSet<>(); + Pattern projectIgnorePattern = Pattern.compile( + testUtilProjects.stream() + .map(s -> s.replace(".", "\\.").replace("*", ".*").replace(":", "\\:").replace('?', '.')) + .collect(Collectors.joining(")|(", "^(", ")$"))); + SortedSet<Dependency> nonTestDeps = new TreeSet<>(); + SortedSet<Dependency> testDeps = new TreeSet<>(); MavenSession session = mavenSession(helper); var graphBuilder = helper.getComponent(DependencyGraphBuilder.class); List<MavenProject> projects = session.getAllProjects(); @@ -133,22 +153,33 @@ public class EnforceDependenciesAllProjects implements EnforcerRule { var req = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest()); req.setProject(project); DependencyNode root = graphBuilder.buildDependencyGraph(req, null); - addDependenciesRecursive(root, dependencies, ignorePattern); + String projectId = "%s:%s".formatted(project.getGroupId(), project.getArtifactId()); + boolean overrideToTest = projectIgnorePattern.matcher(projectId).matches(); + if (overrideToTest) helper.getLog().info("Treating dependencies of '%s' as 'test'".formatted(projectId)); + addDependenciesRecursive(root, nonTestDeps, testDeps, depIgnorePattern, overrideToTest); } - return dependencies; + testDeps.removeAll(nonTestDeps); + return new Dependencies(nonTestDeps, testDeps); } catch (DependencyGraphBuilderException | ComponentLookupException e) { throw new RuntimeException(e.getMessage(), e); } } - private static void addDependenciesRecursive(DependencyNode node, Set<Dependency> dependencies, Pattern ignored) { + private static void addDependenciesRecursive( + DependencyNode node, Set<Dependency> nonTestDeps, Set<Dependency> testDeps, Pattern ignored, + boolean overrideToTest) { if (node.getChildren() != null) { for (DependencyNode dep : node.getChildren()) { - Dependency dependency = Dependency.fromArtifact(dep.getArtifact()); + Artifact a = dep.getArtifact(); + Dependency dependency = Dependency.fromArtifact(a); if (!ignored.matcher(dependency.asString()).matches()) { - dependencies.add(dependency); + if (a.getScope().equals("test") || overrideToTest) { + testDeps.add(dependency); + } else { + nonTestDeps.add(dependency); + } } - addDependenciesRecursive(dep, dependencies, ignored); + addDependenciesRecursive(dep, nonTestDeps, testDeps, ignored, overrideToTest); } } } @@ -182,29 +213,43 @@ public class EnforceDependenciesAllProjects implements EnforcerRule { } } - static void writeDependencySpec(Path specFile, SortedSet<Dependency> dependencies) { + static void writeDependencySpec(Path specFile, Dependencies dependencies) { try (var out = Files.newBufferedWriter(specFile)) { - out.write("# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.\n"); - for (Dependency d : dependencies) { - out.write(d.asString()); - out.write('\n'); + out.write("# Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.\n\n"); + out.write(NON_TEST_HEADER); out.write('\n'); + out.write("# Contains dependencies that are not used exclusively in 'test' scope\n"); + for (Dependency d : dependencies.nonTest()) { + out.write(d.asString()); out.write('\n'); + } + out.write("\n"); out.write(TEST_ONLY_HEADER); out.write('\n'); + out.write("# Contains dependencies that are used exclusively in 'test' scope\n"); + for (Dependency d : dependencies.testOnly()) { + out.write(d.asString()); out.write('\n'); } } catch (IOException e) { throw new UncheckedIOException(e); } } - private static SortedSet<Dependency> loadDependencySpec(Path specFile) { + private static Dependencies loadDependencySpec(Path specFile) { try { + List<String> lines; try (Stream<String> s = Files.lines(specFile)) { - return s.map(String::trim).filter(l -> !l.isEmpty() && !l.startsWith("#")).map(Dependency::fromString) - .collect(Collectors.toCollection(TreeSet::new)); + lines = s.map(String::trim).filter(l -> !l.isEmpty()).toList(); } + SortedSet<Dependency> nonTest = parseDependencies(lines.stream().takeWhile(l -> !l.equals(TEST_ONLY_HEADER))); + SortedSet<Dependency> testOnly = parseDependencies(lines.stream().dropWhile(l -> !l.equals(TEST_ONLY_HEADER))); + return new Dependencies(nonTest, testOnly); } catch (IOException e) { throw new UncheckedIOException(e); } } + private static SortedSet<Dependency> parseDependencies(Stream<String> lines) { + return lines.filter(l -> !l.startsWith("#")).map(Dependency::fromString) + .collect(Collectors.toCollection(TreeSet::new)); + } + // Mark rule as not cachable @Override public boolean isCacheable() { return false; } @Override public boolean isResultValid(EnforcerRule r) { return false; } diff --git a/vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java b/vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java index 910d18b25cc..6e47aad0d06 100644 --- a/vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java +++ b/vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java @@ -1,6 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.maven.plugin.enforcer; +import com.yahoo.vespa.maven.plugin.enforcer.EnforceDependenciesAllProjects.Dependencies; import com.yahoo.vespa.maven.plugin.enforcer.EnforceDependenciesAllProjects.Dependency; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; import org.junit.jupiter.api.Test; @@ -29,26 +30,34 @@ class EnforceDependenciesAllProjectsTest { @Test void succeeds_dependencies_matches_spec() { - SortedSet<Dependency> dependencies = new TreeSet<>(Set.of( + SortedSet<Dependency> nonTest = new TreeSet<>(Set.of( Dependency.fromString("com.example:foo:1.2.3"), Dependency.fromString("com.example:bar:2.3.4"))); + SortedSet<Dependency> testOnly = new TreeSet<>(Set.of( + Dependency.fromString("com.example:testfoo:1.2.3"), + Dependency.fromString("com.example:testbar:2.3.4"))); Path specFile = Paths.get("src/test/resources/allowed-dependencies.txt"); - assertDoesNotThrow(() -> validateDependencies(dependencies, specFile, POM_FILE, "my-dep-enforcer")); + Dependencies deps = new Dependencies(nonTest, testOnly); + assertDoesNotThrow(() -> validateDependencies(deps, specFile, POM_FILE, "my-dep-enforcer")); } @Test void fails_on_forbidden_dependency() { - SortedSet<Dependency> dependencies = new TreeSet<>(Set.of( + SortedSet<Dependency> nonTest = new TreeSet<>(Set.of( Dependency.fromString("com.example:foo:1.2.3"), Dependency.fromString("com.example:bar:2.3.4"), Dependency.fromString("com.example:foobar:3.4.5"))); + SortedSet<Dependency> testOnly = new TreeSet<>(Set.of( + Dependency.fromString("com.example:testfoo:1.2.3"), + Dependency.fromString("com.example:testbar:2.3.4"))); Path specFile = Paths.get("src/test/resources/allowed-dependencies.txt"); + Dependencies deps = new Dependencies(nonTest, testOnly); var exception = assertThrows(EnforcerRuleException.class, - () -> validateDependencies(dependencies, specFile, POM_FILE, "my-dep-enforcer")); + () -> validateDependencies(deps, specFile, POM_FILE, "my-dep-enforcer")); String expectedErrorMessage = """ The dependency enforcer failed: - Forbidden dependencies: + Forbidden non-test dependencies: - com.example:foobar:3.4.5 Maven dependency validation failed. If this change was intentional, update the dependency spec by running: $ mvn validate -DdependencyEnforcer.writeSpec -pl my-dep-enforcer -f /vespa-src/pom.xml @@ -58,16 +67,21 @@ class EnforceDependenciesAllProjectsTest { @Test void fails_on_missing_dependency() { - SortedSet<Dependency> dependencies = new TreeSet<>(Set.of( - Dependency.fromString("com.example:foo:1.2.3"))); + SortedSet<Dependency> nonTest = new TreeSet<>(Set.of( + Dependency.fromString("com.example:bar:2.3.4"))); + SortedSet<Dependency> testOnly = new TreeSet<>(Set.of( + Dependency.fromString("com.example:testfoo:1.2.3"))); Path specFile = Paths.get("src/test/resources/allowed-dependencies.txt"); + Dependencies deps = new Dependencies(nonTest, testOnly); var exception = assertThrows(EnforcerRuleException.class, - () -> validateDependencies(dependencies, specFile, POM_FILE, "my-dep-enforcer")); + () -> validateDependencies(deps, specFile, POM_FILE, "my-dep-enforcer")); String expectedErrorMessage = """ The dependency enforcer failed: - Removed dependencies: - - com.example:bar:2.3.4 + Removed non-test dependencies: + - com.example:foo:1.2.3 + Removed test-only dependencies: + - com.example:testbar:2.3.4 Maven dependency validation failed. If this change was intentional, update the dependency spec by running: $ mvn validate -DdependencyEnforcer.writeSpec -pl my-dep-enforcer -f /vespa-src/pom.xml """; @@ -76,11 +90,15 @@ class EnforceDependenciesAllProjectsTest { @Test void writes_valid_spec_file(@TempDir Path tempDir) throws IOException { - SortedSet<Dependency> dependencies = new TreeSet<>(Set.of( + SortedSet<Dependency> nonTest = new TreeSet<>(Set.of( Dependency.fromString("com.example:foo:1.2.3"), Dependency.fromString("com.example:bar:2.3.4"))); + SortedSet<Dependency> testOnly = new TreeSet<>(Set.of( + Dependency.fromString("com.example:testfoo:1.2.3"), + Dependency.fromString("com.example:testbar:2.3.4"))); + Dependencies deps = new Dependencies(nonTest, testOnly); Path outputFile = tempDir.resolve("allowed-dependencies.txt"); - writeDependencySpec(outputFile, dependencies); + writeDependencySpec(outputFile, deps); assertEquals( Files.readString(Paths.get("src/test/resources/allowed-dependencies.txt")), Files.readString(outputFile)); diff --git a/vespa-enforcer-extensions/src/test/resources/allowed-dependencies.txt b/vespa-enforcer-extensions/src/test/resources/allowed-dependencies.txt index dc6ab2e9be0..2ef0f9e0c0c 100644 --- a/vespa-enforcer-extensions/src/test/resources/allowed-dependencies.txt +++ b/vespa-enforcer-extensions/src/test/resources/allowed-dependencies.txt @@ -1,3 +1,11 @@ # Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#[non-test] +# Contains dependencies that are not used exclusively in 'test' scope com.example:bar:2.3.4 com.example:foo:1.2.3 + +#[test-only] +# Contains dependencies that are used exclusively in 'test' scope +com.example:testbar:2.3.4 +com.example:testfoo:1.2.3 |