summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@yahooinc.com>2022-11-14 11:07:52 +0100
committerBjørn Christian Seime <bjorncs@yahooinc.com>2022-11-14 11:08:50 +0100
commit91ae1fb4acd2c61bf3effaa7af05a52eff4223ce (patch)
tree2da5cae63faec9811d61a08ad777f82ed5563917
parent2e3d84ed44caa36214cff7ac0ff9c4b874643dcb (diff)
Classify dependencies based on test vs non-test usage
-rw-r--r--maven-plugins/allowed-maven-dependencies.txt30
-rw-r--r--vespa-dependencies-enforcer/allowed-maven-dependencies.txt48
-rw-r--r--vespa-dependencies-enforcer/pom.xml8
-rw-r--r--vespa-enforcer-extensions/src/main/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjects.java119
-rw-r--r--vespa-enforcer-extensions/src/test/java/com/yahoo/vespa/maven/plugin/enforcer/EnforceDependenciesAllProjectsTest.java42
-rw-r--r--vespa-enforcer-extensions/src/test/resources/allowed-dependencies.txt8
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