Skip to content

Commit 06e2472

Browse files
committed
MNG-1378: make test-jar dependencies transitive
Treat the direct test-scoped dependencies of a test-jar producer as part of that test artifact's dependency contract when resolving under Maven 4 semantics. Keep ordinary test-scope behavior unchanged, preserve Maven 3 personality compatibility, and add an integration fixture that proves the test-jar consumer receives the producer's test dependency while a regular JAR consumer does not.
1 parent 1991811 commit 06e2472

8 files changed

Lines changed: 441 additions & 4 deletions

File tree

impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/MavenSessionBuilderSupplier.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,13 @@ public DependencyManager getDependencyManager(boolean transitive) {
100100
}
101101

102102
public DependencySelector getDependencySelector() {
103+
DependencySelector scopeSelector = ScopeDependencySelector.legacy(
104+
null, Arrays.asList(DependencyScope.TEST.id(), DependencyScope.PROVIDED.id()));
105+
if (!mavenMaven3Personality) {
106+
scopeSelector = new TestJarDependencySelector(scopeSelector);
107+
}
103108
return new AndDependencySelector(
104-
ScopeDependencySelector.legacy(
105-
null, Arrays.asList(DependencyScope.TEST.id(), DependencyScope.PROVIDED.id())),
106-
OptionalDependencySelector.fromDirect(),
107-
new ExclusionDependencySelector());
109+
scopeSelector, OptionalDependencySelector.fromDirect(), new ExclusionDependencySelector());
108110
}
109111

110112
public DependencyGraphTransformer getDependencyGraphTransformer() {
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.impl.resolver;
20+
21+
import java.util.Objects;
22+
23+
import org.apache.maven.api.DependencyScope;
24+
import org.apache.maven.api.Type;
25+
import org.eclipse.aether.artifact.ArtifactProperties;
26+
import org.eclipse.aether.collection.DependencyCollectionContext;
27+
import org.eclipse.aether.collection.DependencySelector;
28+
import org.eclipse.aether.graph.Dependency;
29+
30+
import static java.util.Objects.requireNonNull;
31+
32+
/**
33+
* Preserves Maven's normal non-transitive test-scope semantics while allowing the direct test-scoped dependencies of
34+
* a test JAR to participate in dependency collection. Those dependencies are part of the test artifact's classpath
35+
* contract, not the producer's main artifact contract.
36+
*/
37+
final class TestJarDependencySelector implements DependencySelector {
38+
private final DependencySelector delegate;
39+
private final boolean testJarParent;
40+
41+
TestJarDependencySelector(DependencySelector delegate) {
42+
this(delegate, false);
43+
}
44+
45+
private TestJarDependencySelector(DependencySelector delegate, boolean testJarParent) {
46+
this.delegate = requireNonNull(delegate, "delegate cannot be null");
47+
this.testJarParent = testJarParent;
48+
}
49+
50+
@Override
51+
public boolean selectDependency(Dependency dependency) {
52+
requireNonNull(dependency, "dependency cannot be null");
53+
if (testJarParent && DependencyScope.TEST.id().equals(dependency.getScope())) {
54+
return true;
55+
}
56+
return delegate.selectDependency(dependency);
57+
}
58+
59+
@Override
60+
public DependencySelector deriveChildSelector(DependencyCollectionContext context) {
61+
requireNonNull(context, "context cannot be null");
62+
63+
DependencySelector childDelegate = delegate.deriveChildSelector(context);
64+
Dependency parent = context.getDependency();
65+
boolean childOfTestJar = parent != null
66+
&& Type.TEST_JAR.equals(parent.getArtifact().getProperty(ArtifactProperties.TYPE, ""));
67+
68+
if (childDelegate == delegate && childOfTestJar == testJarParent) {
69+
return this;
70+
}
71+
return new TestJarDependencySelector(childDelegate, childOfTestJar);
72+
}
73+
74+
@Override
75+
public boolean equals(Object obj) {
76+
if (this == obj) {
77+
return true;
78+
}
79+
if (!(obj instanceof TestJarDependencySelector that)) {
80+
return false;
81+
}
82+
return testJarParent == that.testJarParent && delegate.equals(that.delegate);
83+
}
84+
85+
@Override
86+
public int hashCode() {
87+
return Objects.hash(delegate, testJarParent);
88+
}
89+
90+
@Override
91+
public String toString() {
92+
return getClass().getSimpleName() + "[delegate=" + delegate + ", testJarParent=" + testJarParent + ']';
93+
}
94+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.maven.it;
20+
21+
import java.nio.file.Path;
22+
import java.util.List;
23+
24+
import org.junit.jupiter.api.Test;
25+
26+
import static org.junit.jupiter.api.Assertions.assertFalse;
27+
import static org.junit.jupiter.api.Assertions.assertTrue;
28+
29+
/**
30+
* Integration test for <a href="https://issues.apache.org/jira/browse/MNG-1378">MNG-1378</a>.
31+
*/
32+
public class MavenITmng1378TestJarTransitiveDependenciesTest extends AbstractMavenIntegrationTestCase {
33+
34+
@Test
35+
public void testTestJarCarriesProducerTestDependencies() throws Exception {
36+
Path testDir = extractResources("mng-1378");
37+
38+
Verifier producer = newVerifier(testDir);
39+
producer.setAutoclean(false);
40+
producer.deleteArtifacts("org.apache.maven.its.mng1378");
41+
producer.addCliArgument("-pl");
42+
producer.addCliArgument("support,test-jar");
43+
producer.addCliArgument("validate");
44+
producer.execute();
45+
producer.verifyErrorFreeLog();
46+
47+
Verifier consumer = newVerifier(testDir.resolve("consumer"));
48+
consumer.setAutoclean(false);
49+
consumer.addCliArgument("validate");
50+
consumer.execute();
51+
consumer.verifyErrorFreeLog();
52+
53+
List<String> testClasspath = consumer.loadLines("target/test.txt");
54+
assertTrue(testClasspath.contains("test-jar-1.0-tests.jar"), testClasspath.toString());
55+
assertTrue(testClasspath.contains("support-1.0.jar"), testClasspath.toString());
56+
57+
Verifier regularConsumer = newVerifier(testDir.resolve("regular-consumer"));
58+
regularConsumer.setAutoclean(false);
59+
regularConsumer.addCliArgument("validate");
60+
regularConsumer.execute();
61+
regularConsumer.verifyErrorFreeLog();
62+
63+
List<String> regularTestClasspath = regularConsumer.loadLines("target/test.txt");
64+
assertTrue(regularTestClasspath.contains("test-jar-1.0.jar"), regularTestClasspath.toString());
65+
assertFalse(regularTestClasspath.contains("support-1.0.jar"), regularTestClasspath.toString());
66+
}
67+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing,
14+
software distributed under the License is distributed on an
15+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
KIND, either express or implied. See the License for the
17+
specific language governing permissions and limitations
18+
under the License.
19+
-->
20+
<project xmlns="http://maven.apache.org/POM/4.0.0">
21+
<modelVersion>4.0.0</modelVersion>
22+
23+
<groupId>org.apache.maven.its.mng1378</groupId>
24+
<artifactId>consumer</artifactId>
25+
<version>1.0</version>
26+
27+
<name>Maven Integration Test :: MNG-1378 :: Test JAR Consumer</name>
28+
29+
<dependencies>
30+
<dependency>
31+
<groupId>org.apache.maven.its.mng1378</groupId>
32+
<artifactId>test-jar</artifactId>
33+
<version>1.0</version>
34+
<type>test-jar</type>
35+
<scope>test</scope>
36+
</dependency>
37+
</dependencies>
38+
39+
<build>
40+
<plugins>
41+
<plugin>
42+
<groupId>org.apache.maven.its.plugins</groupId>
43+
<artifactId>maven-it-plugin-dependency-resolution</artifactId>
44+
<version>2.1-SNAPSHOT</version>
45+
<executions>
46+
<execution>
47+
<id>test</id>
48+
<goals>
49+
<goal>test</goal>
50+
</goals>
51+
<phase>validate</phase>
52+
<configuration>
53+
<testClassPath>target/test.txt</testClassPath>
54+
<significantPathLevels>1</significantPathLevels>
55+
</configuration>
56+
</execution>
57+
</executions>
58+
</plugin>
59+
</plugins>
60+
</build>
61+
</project>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing,
14+
software distributed under the License is distributed on an
15+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
KIND, either express or implied. See the License for the
17+
specific language governing permissions and limitations
18+
under the License.
19+
-->
20+
<project xmlns="http://maven.apache.org/POM/4.0.0">
21+
<modelVersion>4.0.0</modelVersion>
22+
23+
<groupId>org.apache.maven.its.mng1378</groupId>
24+
<artifactId>parent</artifactId>
25+
<version>1.0</version>
26+
<packaging>pom</packaging>
27+
28+
<name>Maven Integration Test :: MNG-1378</name>
29+
<description>Verify that dependencies required by a producer's test JAR are transitively available to test-JAR consumers.</description>
30+
31+
<modules>
32+
<module>support</module>
33+
<module>test-jar</module>
34+
<module>consumer</module>
35+
<module>regular-consumer</module>
36+
</modules>
37+
</project>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing,
14+
software distributed under the License is distributed on an
15+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
KIND, either express or implied. See the License for the
17+
specific language governing permissions and limitations
18+
under the License.
19+
-->
20+
<project xmlns="http://maven.apache.org/POM/4.0.0">
21+
<modelVersion>4.0.0</modelVersion>
22+
23+
<groupId>org.apache.maven.its.mng1378</groupId>
24+
<artifactId>regular-consumer</artifactId>
25+
<version>1.0</version>
26+
27+
<name>Maven Integration Test :: MNG-1378 :: Regular JAR Consumer</name>
28+
29+
<dependencies>
30+
<dependency>
31+
<groupId>org.apache.maven.its.mng1378</groupId>
32+
<artifactId>test-jar</artifactId>
33+
<version>1.0</version>
34+
<scope>test</scope>
35+
</dependency>
36+
</dependencies>
37+
38+
<build>
39+
<plugins>
40+
<plugin>
41+
<groupId>org.apache.maven.its.plugins</groupId>
42+
<artifactId>maven-it-plugin-dependency-resolution</artifactId>
43+
<version>2.1-SNAPSHOT</version>
44+
<executions>
45+
<execution>
46+
<id>test</id>
47+
<goals>
48+
<goal>test</goal>
49+
</goals>
50+
<phase>validate</phase>
51+
<configuration>
52+
<testClassPath>target/test.txt</testClassPath>
53+
<significantPathLevels>1</significantPathLevels>
54+
</configuration>
55+
</execution>
56+
</executions>
57+
</plugin>
58+
</plugins>
59+
</build>
60+
</project>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing,
14+
software distributed under the License is distributed on an
15+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
KIND, either express or implied. See the License for the
17+
specific language governing permissions and limitations
18+
under the License.
19+
-->
20+
<project xmlns="http://maven.apache.org/POM/4.0.0">
21+
<modelVersion>4.0.0</modelVersion>
22+
23+
<groupId>org.apache.maven.its.mng1378</groupId>
24+
<artifactId>support</artifactId>
25+
<version>1.0</version>
26+
27+
<name>Maven Integration Test :: MNG-1378 :: Test Support</name>
28+
29+
<build>
30+
<plugins>
31+
<plugin>
32+
<groupId>org.apache.maven.its.plugins</groupId>
33+
<artifactId>maven-it-plugin-artifact</artifactId>
34+
<version>2.1-SNAPSHOT</version>
35+
<configuration>
36+
<mainFile>pom.xml</mainFile>
37+
</configuration>
38+
<executions>
39+
<execution>
40+
<id>install</id>
41+
<goals>
42+
<goal>set</goal>
43+
<goal>install</goal>
44+
</goals>
45+
<phase>validate</phase>
46+
</execution>
47+
</executions>
48+
</plugin>
49+
</plugins>
50+
</build>
51+
</project>

0 commit comments

Comments
 (0)