blob: ff3ac75751acf200cb6b0ee9d71b32e591b1574b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.repository.legacy.resolver;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.metadata.ResolutionGroup;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.CyclicDependencyException;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.repository.legacy.metadata.MetadataResolutionRequest;
import org.codehaus.plexus.testing.PlexusTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test the default artifact collector.
*
*/
@PlexusTest
class DefaultArtifactCollectorTest {
@Inject
private LegacyArtifactCollector artifactCollector;
@Inject
private ArtifactFactory artifactFactory;
private ArtifactSpec projectArtifact;
private Source source;
private static final String GROUP_ID = "test";
@BeforeEach
void setUp() throws Exception {
source = new Source();
projectArtifact = createArtifactSpec("project", "1.0", null);
}
@Test
@Disabled("works, but we don't fail on cycles presently")
void testCircularDependencyNotIncludingCurrentProject()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
b.addDependency("a", "1.0");
assertThrows(
CyclicDependencyException.class,
() -> collect(a),
"Should have failed on cyclic dependency not involving project");
}
@Test
@Disabled("works, but we don't fail on cycles presently")
void testCircularDependencyIncludingCurrentProject()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
b.addDependency("project", "1.0");
assertThrows(
CyclicDependencyException.class,
() -> collect(a),
"Should have failed on cyclic dependency not involving project");
}
@Test
void testResolveWithFilter() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
ArtifactSpec c = a.addDependency("c", "3.0");
b.addDependency("c", "2.0");
ArtifactSpec d = b.addDependency("d", "4.0");
ArtifactResolutionResult res = collect(a);
assertEquals(
createSet(new Object[] {a.artifact, b.artifact, c.artifact, d.artifact}),
res.getArtifacts(),
"Check artifact list");
ArtifactFilter filter = new ExclusionSetFilter(new String[] {"b"});
res = collect(a, filter);
assertEquals(createSet(new Object[] {a.artifact, c.artifact}), res.getArtifacts(), "Check artifact list");
}
@Test
void testResolveCorrectDependenciesWhenDifferentDependenciesOnNearest()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
ArtifactSpec c2 = b.addDependency("c", "2.0");
c2.addDependency("d", "1.0");
ArtifactSpec e = createArtifactSpec("e", "1.0");
ArtifactSpec c1 = e.addDependency("c", "1.0");
ArtifactSpec f = c1.addDependency("f", "1.0");
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, e.artifact}));
assertEquals(
createSet(new Object[] {a.artifact, b.artifact, e.artifact, c1.artifact, f.artifact}),
res.getArtifacts(),
"Check artifact list");
assertEquals("1.0", getArtifact("c", res.getArtifacts()).getVersion(), "Check version");
}
@Test
@Disabled
void testResolveCorrectDependenciesWhenDifferentDependenciesOnNewest()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
// TODO use newest conflict resolver
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
ArtifactSpec c2 = b.addDependency("c", "2.0");
ArtifactSpec d = c2.addDependency("d", "1.0");
ArtifactSpec e = createArtifactSpec("e", "1.0");
ArtifactSpec c1 = e.addDependency("c", "1.0");
c1.addDependency("f", "1.0");
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, e.artifact}));
assertEquals(
createSet(new Object[] {a.artifact, b.artifact, e.artifact, c2.artifact, d.artifact}),
res.getArtifacts(),
"Check artifact list");
assertEquals("2.0", getArtifact("c", res.getArtifacts()).getVersion(), "Check version");
}
@Test
@Disabled
void testResolveCorrectDependenciesWhenDifferentDependenciesOnNewestVersionReplaced()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
// TODO use newest conflict resolver
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b1 = a.addDependency("b", "1.0");
ArtifactSpec c = a.addDependency("c", "1.0");
ArtifactSpec d2 = b1.addDependency("d", "2.0");
d2.addDependency("h", "1.0");
ArtifactSpec d1 = c.addDependency("d", "1.0");
ArtifactSpec b2 = c.addDependency("b", "2.0");
ArtifactSpec e = b2.addDependency("e", "1.0");
ArtifactSpec g = d1.addDependency("g", "1.0");
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact}));
Object[] artifacts = new Object[] {a.artifact, c.artifact, d1.artifact, b2.artifact, e.artifact, g.artifact};
assertEquals(createSet(artifacts), res.getArtifacts(), "Check artifact list");
assertEquals("1.0", getArtifact("d", res.getArtifacts()).getVersion(), "Check version");
assertEquals("2.0", getArtifact("b", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testResolveNearestNewestIsNearest() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
ArtifactSpec c = a.addDependency("c", "3.0");
b.addDependency("c", "2.0");
ArtifactResolutionResult res = collect(a);
assertEquals(
createSet(new Object[] {a.artifact, b.artifact, c.artifact}),
res.getArtifacts(),
"Check artifact list");
assertEquals("3.0", getArtifact("c", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testResolveNearestOldestIsNearest() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
ArtifactSpec c = a.addDependency("c", "2.0");
b.addDependency("c", "3.0");
ArtifactResolutionResult res = collect(a);
assertEquals(
createSet(new Object[] {a.artifact, b.artifact, c.artifact}),
res.getArtifacts(),
"Check artifact list");
assertEquals("2.0", getArtifact("c", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testResolveLocalNewestIsLocal() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
a.addDependency("b", "2.0");
ArtifactSpec b = createArtifactSpec("b", "3.0");
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts(), "Check artifact list");
assertEquals("3.0", getArtifact("b", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testResolveLocalOldestIsLocal() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
a.addDependency("b", "3.0");
ArtifactSpec b = createArtifactSpec("b", "2.0");
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts(), "Check artifact list");
assertEquals("2.0", getArtifact("b", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testResolveLocalWithNewerVersionButLesserScope()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("commons-logging", "1.0");
a.addDependency("junit", "3.7");
ArtifactSpec b = createArtifactSpec("junit", "3.8.1", Artifact.SCOPE_TEST);
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts(), "Check artifact list");
assertEquals("3.8.1", getArtifact("junit", res.getArtifacts()).getVersion(), "Check version");
assertEquals(
Artifact.SCOPE_TEST, getArtifact("junit", res.getArtifacts()).getScope(), "Check artifactScope");
}
@Test
void testResolveLocalWithNewerVersionButLesserScopeResolvedFirst()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec b = createArtifactSpec("junit", "3.8.1", Artifact.SCOPE_TEST);
ArtifactSpec a = createArtifactSpec("commons-logging", "1.0");
a.addDependency("junit", "3.7");
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts(), "Check artifact list");
assertEquals("3.8.1", getArtifact("junit", res.getArtifacts()).getVersion(), "Check version");
assertEquals(
Artifact.SCOPE_TEST, getArtifact("junit", res.getArtifacts()).getScope(), "Check artifactScope");
}
@Test
void testResolveNearestWithRanges() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
ArtifactSpec c = a.addDependency("c", "2.0");
b.addDependency("c", "[1.0,3.0]");
ArtifactResolutionResult res = collect(a);
assertEquals(
createSet(new Object[] {a.artifact, b.artifact, c.artifact}),
res.getArtifacts(),
"Check artifact list");
assertEquals("2.0", getArtifact("c", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testResolveRangeWithManagedVersion() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "[1.0,3.0]");
ArtifactSpec managedB = createArtifactSpec("b", "5.0");
ArtifactResolutionResult res = collect(a, managedB.artifact);
assertEquals(
createSet(new Object[] {a.artifact, managedB.artifact}), res.getArtifacts(), "Check artifact list");
assertEquals("5.0", getArtifact("b", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testCompatibleRanges() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
a.addDependency("c", "[2.0,2.5]");
b.addDependency("c", "[1.0,3.0]");
ArtifactSpec c = createArtifactSpec("c", "2.5");
ArtifactResolutionResult res = collect(a);
assertEquals(
createSet(new Object[] {a.artifact, b.artifact, c.artifact}),
res.getArtifacts(),
"Check artifact list");
assertEquals("2.5", getArtifact("c", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testIncompatibleRanges() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
a.addDependency("c", "[2.4,3.0]");
b.addDependency("c", "[1.0,2.0]");
ArtifactResolutionResult res = collect(a);
assertTrue(res.hasVersionRangeViolations());
}
@Test
void testUnboundedRangeWhenVersionUnavailable()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = a.addDependency("b", "1.0");
a.addDependency("c", "[2.0,]");
b.addDependency("c", "[1.0,]");
ArtifactResolutionResult res = collect(a);
assertTrue(res.hasVersionRangeViolations());
}
@Test
void testUnboundedRangeBelowLastRelease() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
createArtifactSpec("c", "1.5");
ArtifactSpec c = createArtifactSpec("c", "2.0");
createArtifactSpec("c", "1.1");
a.addDependency("c", "[1.0,)");
ArtifactResolutionResult res = collect(a);
assertEquals(createSet(new Object[] {a.artifact, c.artifact}), res.getArtifacts(), "Check artifact list");
assertEquals("2.0", getArtifact("c", res.getArtifacts()).getVersion(), "Check version");
}
@Test
void testUnboundedRangeAboveLastRelease() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
createArtifactSpec("c", "2.0");
a.addDependency("c", "[10.0,)");
ArtifactResolutionResult res = collect(a);
assertTrue(res.hasVersionRangeViolations());
}
@Test
void testResolveManagedVersion() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
a.addDependency("b", "3.0", Artifact.SCOPE_RUNTIME);
Artifact managedVersion = createArtifactSpec("b", "5.0").artifact;
Artifact modifiedB = createArtifactSpec("b", "5.0", Artifact.SCOPE_RUNTIME).artifact;
ArtifactResolutionResult res = collect(a, managedVersion);
assertEquals(createSet(new Object[] {a.artifact, modifiedB}), res.getArtifacts(), "Check artifact list");
}
@Test
void testCollectChangesVersionOfOriginatingArtifactIfInDependencyManagementHasDifferentVersion()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
Artifact artifact = projectArtifact.artifact;
Artifact managedVersion = createArtifactSpec(artifact.getArtifactId(), "2.0").artifact;
ArtifactResolutionResult result = collect(a, managedVersion);
assertEquals("1.0", artifact.getVersion(), "collect has modified version in originating artifact");
Artifact resolvedArtifact = result.getArtifacts().iterator().next();
assertEquals("1.0", resolvedArtifact.getVersion(), "Resolved version don't match original artifact version");
}
@Test
void testResolveCompileScopeOverTestScope()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec c = createArtifactSpec("c", "3.0", Artifact.SCOPE_TEST);
a.addDependency("c", "2.0", Artifact.SCOPE_COMPILE);
Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_COMPILE).artifact;
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, c.artifact}));
assertEquals(createSet(new Object[] {a.artifact, modifiedC}), res.getArtifacts(), "Check artifact list");
Artifact artifact = getArtifact("c", res.getArtifacts());
// local wins now, and irrelevant if not local as test/provided aren't transitive
// assertEquals( Artifact.SCOPE_COMPILE, artifact.getArtifactScope(), "Check artifactScope" );
assertEquals(Artifact.SCOPE_TEST, artifact.getScope(), "Check artifactScope");
}
@Test
void testResolveRuntimeScopeOverTestScope()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec c = createArtifactSpec("c", "3.0", Artifact.SCOPE_TEST);
a.addDependency("c", "2.0", Artifact.SCOPE_RUNTIME);
Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_RUNTIME).artifact;
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, c.artifact}));
assertEquals(createSet(new Object[] {a.artifact, modifiedC}), res.getArtifacts(), "Check artifact list");
Artifact artifact = getArtifact("c", res.getArtifacts());
// local wins now, and irrelevant if not local as test/provided aren't transitive
// assertEquals( Artifact.SCOPE_RUNTIME, artifact.getArtifactScope(), "Check artifactScope" );
assertEquals(Artifact.SCOPE_TEST, artifact.getScope(), "Check artifactScope");
}
@Test
void testResolveCompileScopeOverRuntimeScope()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec root = createArtifactSpec("root", "1.0");
ArtifactSpec a = root.addDependency("a", "1.0");
root.addDependency("c", "3.0", Artifact.SCOPE_RUNTIME);
a.addDependency("c", "2.0", Artifact.SCOPE_COMPILE);
Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_COMPILE).artifact;
ArtifactResolutionResult res = collect(createSet(new Object[] {root.artifact}));
assertEquals(
createSet(new Object[] {a.artifact, root.artifact, modifiedC}),
res.getArtifacts(),
"Check artifact list");
Artifact artifact = getArtifact("c", res.getArtifacts());
assertEquals(Artifact.SCOPE_COMPILE, artifact.getScope(), "Check artifactScope");
}
@Test
void testResolveCompileScopeOverProvidedScope()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec c = createArtifactSpec("c", "3.0", Artifact.SCOPE_PROVIDED);
a.addDependency("c", "2.0", Artifact.SCOPE_COMPILE);
Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_COMPILE).artifact;
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, c.artifact}));
assertEquals(createSet(new Object[] {a.artifact, modifiedC}), res.getArtifacts(), "Check artifact list");
Artifact artifact = getArtifact("c", res.getArtifacts());
// local wins now, and irrelevant if not local as test/provided aren't transitive
// assertEquals( Artifact.SCOPE_COMPILE, artifact.getArtifactScope(), "Check artifactScope" );
assertEquals(Artifact.SCOPE_PROVIDED, artifact.getScope(), "Check artifactScope");
}
@Test
void testResolveRuntimeScopeOverProvidedScope()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec c = createArtifactSpec("c", "3.0", Artifact.SCOPE_PROVIDED);
a.addDependency("c", "2.0", Artifact.SCOPE_RUNTIME);
Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_RUNTIME).artifact;
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, c.artifact}));
assertEquals(createSet(new Object[] {a.artifact, modifiedC}), res.getArtifacts(), "Check artifact list");
Artifact artifact = getArtifact("c", res.getArtifacts());
// local wins now, and irrelevant if not local as test/provided aren't transitive
// assertEquals( Artifact.SCOPE_RUNTIME, artifact.getArtifactScope(), "Check artifactScope" );
assertEquals(Artifact.SCOPE_PROVIDED, artifact.getScope(), "Check artifactScope");
}
@Test
void testProvidedScopeNotTransitive() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0", Artifact.SCOPE_PROVIDED);
ArtifactSpec b = createArtifactSpec("b", "1.0");
b.addDependency("c", "3.0", Artifact.SCOPE_PROVIDED);
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts(), "Check artifact list");
}
@Test
void testOptionalNotTransitive() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = createArtifactSpec("b", "1.0");
b.addDependency("c", "3.0", true);
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts(), "Check artifact list");
}
@Test
void testOptionalIncludedAtRoot() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = createArtifactSpec("b", "1.0", true);
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts(), "Check artifact list");
}
@Test
void testScopeUpdate() throws InvalidVersionSpecificationException, ArtifactResolutionException {
/* farthest = compile */
checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_COMPILE);
checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_COMPILE);
checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_COMPILE);
checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_COMPILE);
/* farthest = provided */
checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED);
checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME);
checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM);
checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST);
/* farthest = runtime */
checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_RUNTIME);
checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME);
checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM);
checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_TEST, Artifact.SCOPE_RUNTIME);
/* farthest = system */
checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED);
checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME);
checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM);
checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST);
/* farthest = test */
checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED);
checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME);
checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM);
checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST);
}
private void checkScopeUpdate(String farthestScope, String nearestScope, String expectedScope)
throws ArtifactResolutionException, InvalidVersionSpecificationException {
checkScopeUpdateDirect(farthestScope, nearestScope, expectedScope);
checkScopeUpdateTransitively(farthestScope, nearestScope, expectedScope);
}
private void checkScopeUpdateTransitively(String farthestScope, String nearestScope, String expectedScope)
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = createArtifactSpec("b", "1.0", nearestScope);
ArtifactSpec c = createArtifactSpec("c", "1.0");
a.addDependency(c);
ArtifactSpec dNearest = createArtifactSpec("d", "2.0");
b.addDependency(dNearest);
ArtifactSpec dFarthest = createArtifactSpec("d", "3.0", farthestScope);
c.addDependency(dFarthest);
/* system and provided dependencies are not transitive */
if (!Artifact.SCOPE_SYSTEM.equals(nearestScope) && !Artifact.SCOPE_PROVIDED.equals(nearestScope)) {
checkScopeUpdate(a, b, expectedScope, "2.0");
}
}
private void checkScopeUpdateDirect(String farthestScope, String nearestScope, String expectedScope)
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = createArtifactSpec("b", "1.0");
ArtifactSpec c = createArtifactSpec("c", "1.0");
a.addDependency(c);
ArtifactSpec dNearest = createArtifactSpec("d", "2.0", nearestScope);
b.addDependency(dNearest);
ArtifactSpec dFarthest = createArtifactSpec("d", "3.0", farthestScope);
c.addDependency(dFarthest);
checkScopeUpdate(a, b, expectedScope, "2.0");
}
private void checkScopeUpdate(ArtifactSpec a, ArtifactSpec b, String expectedScope, String expectedVersion)
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ScopeArtifactFilter filter;
if (Artifact.SCOPE_PROVIDED.equals(expectedScope)) {
filter = new ScopeArtifactFilter(Artifact.SCOPE_COMPILE);
} else if (Artifact.SCOPE_SYSTEM.equals(expectedScope)) {
filter = new ScopeArtifactFilter(Artifact.SCOPE_COMPILE);
} else {
filter = new ScopeArtifactFilter(expectedScope);
}
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}), filter);
Artifact artifact = getArtifact("d", res.getArtifacts());
assertNotNull(artifact, "MNG-1895 Dependency was not added to resolution");
assertEquals(expectedScope, artifact.getScope(), "Check artifactScope");
assertEquals(expectedVersion, artifact.getVersion(), "Check version");
ArtifactSpec d = createArtifactSpec("d", "1.0");
res = collect(createSet(new Object[] {a.artifact, b.artifact, d.artifact}), filter);
artifact = getArtifact("d", res.getArtifacts());
assertNotNull(artifact, "MNG-1895 Dependency was not added to resolution");
assertEquals(d.artifact.getScope(), artifact.getScope(), "Check artifactScope");
assertEquals("1.0", artifact.getVersion(), "Check version");
}
@Test
@Disabled
void testOptionalNotTransitiveButVersionIsInfluential()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
ArtifactSpec b = createArtifactSpec("b", "1.0");
b.addDependency("c", "3.0", true);
ArtifactSpec d = a.addDependency("d", "1.0");
ArtifactSpec e = d.addDependency("e", "1.0");
e.addDependency("c", "2.0");
ArtifactSpec c = createArtifactSpec("c", "3.0");
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(
createSet(new Object[] {a.artifact, b.artifact, c.artifact, d.artifact, e.artifact}),
res.getArtifacts(),
"Check artifact list");
Artifact artifact = getArtifact("c", res.getArtifacts());
assertEquals("3.0", artifact.getVersion(), "Check version");
}
@Test
void testTestScopeNotTransitive() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0", Artifact.SCOPE_TEST);
ArtifactSpec b = createArtifactSpec("b", "1.0");
b.addDependency("c", "3.0", Artifact.SCOPE_TEST);
ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
assertEquals(createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts(), "Check artifact list");
}
@Test
void testSnapshotNotIncluded() throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
a.addDependency("b", "[1.0,)");
createArtifactSpec("b", "1.0-SNAPSHOT");
ArtifactResolutionResult res = collect(a);
assertTrue(res.hasVersionRangeViolations());
/*
* try { ArtifactResolutionResult res = collect( a ); fail( "Expected b not to resolve: " + res ); } catch (
* OverConstrainedVersionException e ) { assertTrue( e.getMessage().indexOf( "[1.0-SNAPSHOT]" ) <
* e.getMessage().indexOf( "[1.0,)" ) ); }
*/
}
@Test
@Disabled("that one does not work")
void testOverConstrainedVersionException()
throws ArtifactResolutionException, InvalidVersionSpecificationException {
ArtifactSpec a = createArtifactSpec("a", "1.0");
a.addDependency("b", "[1.0, 2.0)");
a.addDependency("c", "[3.3.0,4.0.0)");
ArtifactSpec b = createArtifactSpec("b", "1.0.0");
b.addDependency("c", "3.3.0-v3346");
ArtifactSpec c = createArtifactSpec("c", "3.2.1-v3235e");
OverConstrainedVersionException e = assertThrows(
OverConstrainedVersionException.class, () -> collect(createSet(new Object[] {a.artifact})));
assertTrue(e.getMessage().contains("[3.2.1-v3235e, 3.3.0-v3346]"), "Versions unordered");
assertTrue(e.getMessage().contains("Path to dependency:"), "DependencyTrail unresolved");
}
private Artifact getArtifact(String id, Set artifacts) {
for (Object artifact : artifacts) {
Artifact a = (Artifact) artifact;
if (a.getArtifactId().equals(id) && a.getGroupId().equals(GROUP_ID)) {
return a;
}
}
return null;
}
private ArtifactResolutionResult collect(Set<Artifact> artifacts) throws ArtifactResolutionException {
return collect(artifacts, null);
}
private ArtifactResolutionResult collect(Set<Artifact> artifacts, ArtifactFilter filter)
throws ArtifactResolutionException {
return artifactCollector.collect(
artifacts, projectArtifact.artifact, null, null, null, source, filter, Collections.emptyList(), null);
}
private ArtifactResolutionResult collect(ArtifactSpec a) throws ArtifactResolutionException {
return artifactCollector.collect(
Collections.singleton(a.artifact),
projectArtifact.artifact,
null,
null,
null,
source,
null,
Collections.emptyList(),
null);
}
private ArtifactResolutionResult collect(ArtifactSpec a, ArtifactFilter filter) throws ArtifactResolutionException {
return artifactCollector.collect(
Collections.singleton(a.artifact),
projectArtifact.artifact,
null,
null,
null,
source,
filter,
Collections.emptyList(),
null);
}
private ArtifactResolutionResult collect(ArtifactSpec a, Artifact managedVersion)
throws ArtifactResolutionException {
Map<String, Artifact> managedVersions =
Collections.singletonMap(managedVersion.getDependencyConflictId(), managedVersion);
return artifactCollector.collect(
Collections.singleton(a.artifact),
projectArtifact.artifact,
managedVersions,
null,
null,
source,
null,
Collections.emptyList(),
null);
}
private ArtifactSpec createArtifactSpec(String id, String version) throws InvalidVersionSpecificationException {
return createArtifactSpec(id, version, Artifact.SCOPE_COMPILE);
}
private ArtifactSpec createArtifactSpec(String id, String version, boolean optional)
throws InvalidVersionSpecificationException {
return createArtifactSpec(id, version, Artifact.SCOPE_COMPILE, null, optional);
}
private ArtifactSpec createArtifactSpec(String id, String version, String scope)
throws InvalidVersionSpecificationException {
return createArtifactSpec(id, version, scope, null, false);
}
private ArtifactSpec createArtifactSpec(
String id, String version, String scope, String inheritedScope, boolean optional)
throws InvalidVersionSpecificationException {
VersionRange versionRange = VersionRange.createFromVersionSpec(version);
Artifact artifact = artifactFactory.createDependencyArtifact(
GROUP_ID, id, versionRange, "jar", null, scope, inheritedScope, optional);
ArtifactSpec spec = null;
if (artifact != null) {
spec = new ArtifactSpec();
spec.artifact = artifact;
source.addArtifact(spec);
}
return spec;
}
@SuppressWarnings("unchecked")
private static Set<Artifact> createSet(Object[] x) {
return new LinkedHashSet(Arrays.asList(x));
}
private class ArtifactSpec {
private Artifact artifact;
private Set<Artifact> dependencies = new HashSet<>();
public ArtifactSpec addDependency(String id, String version) throws InvalidVersionSpecificationException {
return addDependency(id, version, Artifact.SCOPE_COMPILE);
}
public ArtifactSpec addDependency(String id, String version, String scope)
throws InvalidVersionSpecificationException {
return addDependency(id, version, scope, false);
}
private ArtifactSpec addDependency(ArtifactSpec dep) throws InvalidVersionSpecificationException {
if (dep != null) {
dependencies.add(dep.artifact);
}
return dep;
}
private ArtifactSpec addDependency(String id, String version, String scope, boolean optional)
throws InvalidVersionSpecificationException {
ArtifactSpec dep = createArtifactSpec(id, version, scope, artifact.getScope(), optional);
return addDependency(dep);
}
public ArtifactSpec addDependency(String id, String version, boolean optional)
throws InvalidVersionSpecificationException {
return addDependency(id, version, Artifact.SCOPE_COMPILE, optional);
}
}
private class Source implements ArtifactMetadataSource {
private Map<String, ArtifactSpec> artifacts = new HashMap<>();
private Map<String, List<ArtifactVersion>> versions = new HashMap<>();
public ResolutionGroup retrieve(
Artifact artifact, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories)
throws ArtifactMetadataRetrievalException {
String key = getKey(artifact);
ArtifactSpec a = (ArtifactSpec) artifacts.get(key);
try {
return new ResolutionGroup(
artifact,
createArtifacts(
artifactFactory, a.dependencies, artifact.getScope(), artifact.getDependencyFilter()),
Collections.emptyList());
} catch (InvalidVersionSpecificationException e) {
throw new ArtifactMetadataRetrievalException("Invalid version creating artifacts", e, artifact);
}
}
private String getKey(Artifact artifact) {
return artifact.getDependencyConflictId();
}
private Set<Artifact> createArtifacts(
ArtifactFactory artifactFactory,
Set<Artifact> dependencies,
String inheritedScope,
ArtifactFilter dependencyFilter)
throws InvalidVersionSpecificationException {
Set<Artifact> projectArtifacts = new HashSet<>();
for (Artifact d : dependencies) {
VersionRange versionRange;
if (d.getVersionRange() != null) {
versionRange = d.getVersionRange();
} else {
versionRange = VersionRange.createFromVersionSpec(d.getVersion());
}
Artifact artifact;
if (d.getScope().equals(Artifact.SCOPE_TEST) || d.getScope().equals(Artifact.SCOPE_PROVIDED)) {
/* don't call createDependencyArtifact as it'll ignore test and provided scopes */
artifact = artifactFactory.createArtifact(
d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getScope(), d.getType());
} else {
artifact = artifactFactory.createDependencyArtifact(
d.getGroupId(),
d.getArtifactId(),
versionRange,
d.getType(),
d.getClassifier(),
d.getScope(),
inheritedScope,
d.isOptional());
}
if (artifact != null && (dependencyFilter == null || dependencyFilter.include(artifact))) {
artifact.setDependencyFilter(dependencyFilter);
projectArtifacts.add(artifact);
}
}
return projectArtifacts;
}
public void addArtifact(ArtifactSpec spec) {
artifacts.put(getKey(spec.artifact), spec);
String key = spec.artifact.getDependencyConflictId();
List<ArtifactVersion> artifactVersions = versions.computeIfAbsent(key, k -> new ArrayList<>());
if (spec.artifact.getVersion() != null) {
artifactVersions.add(new DefaultArtifactVersion(spec.artifact.getVersion()));
}
}
public List<ArtifactVersion> retrieveAvailableVersions(
Artifact artifact, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories)
throws ArtifactMetadataRetrievalException {
return retrieveAvailableVersions(artifact);
}
public List<ArtifactVersion> retrieveAvailableVersionsFromDeploymentRepository(
Artifact artifact, ArtifactRepository localRepository, ArtifactRepository remoteRepository)
throws ArtifactMetadataRetrievalException {
return retrieveAvailableVersions(artifact);
}
private List<ArtifactVersion> retrieveAvailableVersions(Artifact artifact) {
List<ArtifactVersion> artifactVersions = versions.get(artifact.getDependencyConflictId());
if (artifactVersions == null) {
artifactVersions = Collections.emptyList();
}
return artifactVersions;
}
public ResolutionGroup retrieve(MetadataResolutionRequest request) throws ArtifactMetadataRetrievalException {
return retrieve(request.getArtifact(), request.getLocalRepository(), request.getRemoteRepositories());
}
public List<ArtifactVersion> retrieveAvailableVersions(MetadataResolutionRequest request)
throws ArtifactMetadataRetrievalException {
return retrieveAvailableVersions(
request.getArtifact(), request.getLocalRepository(), request.getRemoteRepositories());
}
}
}