| /* |
| * 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()); |
| } |
| } |
| } |