View Javadoc
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.repository.legacy.resolver;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.LinkedHashSet;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Set;
30  
31  import org.apache.maven.artifact.Artifact;
32  import org.apache.maven.artifact.factory.ArtifactFactory;
33  import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
34  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
35  import org.apache.maven.artifact.metadata.ResolutionGroup;
36  import org.apache.maven.artifact.repository.ArtifactRepository;
37  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
38  import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
39  import org.apache.maven.artifact.resolver.CyclicDependencyException;
40  import org.apache.maven.artifact.resolver.ResolutionListener;
41  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
42  import org.apache.maven.artifact.resolver.filter.ExclusionSetFilter;
43  import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
44  import org.apache.maven.artifact.versioning.ArtifactVersion;
45  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
46  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
47  import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
48  import org.apache.maven.artifact.versioning.VersionRange;
49  import org.apache.maven.repository.legacy.metadata.MetadataResolutionRequest;
50  import org.codehaus.plexus.PlexusTestCase;
51  
52  /**
53   * Test the default artifact collector.
54   *
55   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
56   */
57  public class DefaultArtifactCollectorTest extends PlexusTestCase {
58      private LegacyArtifactCollector artifactCollector;
59  
60      private ArtifactFactory artifactFactory;
61  
62      private ArtifactSpec projectArtifact;
63  
64      private Source source;
65  
66      private static final String GROUP_ID = "test";
67  
68      @Override
69      protected void setUp() throws Exception {
70          super.setUp();
71  
72          source = new Source();
73          artifactFactory = (ArtifactFactory) lookup(ArtifactFactory.ROLE);
74          artifactCollector = lookup(LegacyArtifactCollector.class);
75  
76          projectArtifact = createArtifactSpec("project", "1.0", null);
77      }
78  
79      @Override
80      protected void tearDown() throws Exception {
81          artifactCollector = null;
82          artifactFactory = null;
83          super.tearDown();
84      }
85  
86      // works, but we don't fail on cycles presently
87      public void disabledtestCircularDependencyNotIncludingCurrentProject()
88              throws ArtifactResolutionException, InvalidVersionSpecificationException {
89          ArtifactSpec a = createArtifactSpec("a", "1.0");
90          ArtifactSpec b = a.addDependency("b", "1.0");
91          b.addDependency("a", "1.0");
92          try {
93              collect(a);
94              fail("Should have failed on cyclic dependency not involving project");
95          } catch (CyclicDependencyException expected) {
96              assertTrue(true);
97          }
98      }
99  
100     // works, but we don't fail on cycles presently
101     public void disabledtestCircularDependencyIncludingCurrentProject()
102             throws ArtifactResolutionException, InvalidVersionSpecificationException {
103         ArtifactSpec a = createArtifactSpec("a", "1.0");
104         ArtifactSpec b = a.addDependency("b", "1.0");
105         b.addDependency("project", "1.0");
106         try {
107             collect(a);
108             fail("Should have failed on cyclic dependency involving project");
109         } catch (CyclicDependencyException expected) {
110             assertTrue(true);
111         }
112     }
113 
114     public void testResolveWithFilter() throws ArtifactResolutionException, InvalidVersionSpecificationException {
115         ArtifactSpec a = createArtifactSpec("a", "1.0");
116         ArtifactSpec b = a.addDependency("b", "1.0");
117         ArtifactSpec c = a.addDependency("c", "3.0");
118 
119         b.addDependency("c", "2.0");
120         ArtifactSpec d = b.addDependency("d", "4.0");
121 
122         ArtifactResolutionResult res = collect(a);
123         assertEquals(
124                 "Check artifact list",
125                 createSet(new Object[] {a.artifact, b.artifact, c.artifact, d.artifact}),
126                 res.getArtifacts());
127 
128         ArtifactFilter filter = new ExclusionSetFilter(new String[] {"b"});
129         res = collect(a, filter);
130         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, c.artifact}), res.getArtifacts());
131     }
132 
133     public void testResolveCorrectDependenciesWhenDifferentDependenciesOnNearest()
134             throws ArtifactResolutionException, InvalidVersionSpecificationException {
135         ArtifactSpec a = createArtifactSpec("a", "1.0");
136         ArtifactSpec b = a.addDependency("b", "1.0");
137         ArtifactSpec c2 = b.addDependency("c", "2.0");
138         c2.addDependency("d", "1.0");
139 
140         ArtifactSpec e = createArtifactSpec("e", "1.0");
141         ArtifactSpec c1 = e.addDependency("c", "1.0");
142         ArtifactSpec f = c1.addDependency("f", "1.0");
143 
144         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, e.artifact}));
145         assertEquals(
146                 "Check artifact list",
147                 createSet(new Object[] {a.artifact, b.artifact, e.artifact, c1.artifact, f.artifact}),
148                 res.getArtifacts());
149         assertEquals(
150                 "Check version", "1.0", getArtifact("c", res.getArtifacts()).getVersion());
151     }
152 
153     public void disabledtestResolveCorrectDependenciesWhenDifferentDependenciesOnNewest()
154             throws ArtifactResolutionException, InvalidVersionSpecificationException {
155         // TODO use newest conflict resolver
156         ArtifactSpec a = createArtifactSpec("a", "1.0");
157         ArtifactSpec b = a.addDependency("b", "1.0");
158         ArtifactSpec c2 = b.addDependency("c", "2.0");
159         ArtifactSpec d = c2.addDependency("d", "1.0");
160 
161         ArtifactSpec e = createArtifactSpec("e", "1.0");
162         ArtifactSpec c1 = e.addDependency("c", "1.0");
163         c1.addDependency("f", "1.0");
164 
165         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, e.artifact}));
166         assertEquals(
167                 "Check artifact list",
168                 createSet(new Object[] {a.artifact, b.artifact, e.artifact, c2.artifact, d.artifact}),
169                 res.getArtifacts());
170         assertEquals(
171                 "Check version", "2.0", getArtifact("c", res.getArtifacts()).getVersion());
172     }
173 
174     public void disabledtestResolveCorrectDependenciesWhenDifferentDependenciesOnNewestVersionReplaced()
175             throws ArtifactResolutionException, InvalidVersionSpecificationException {
176         // TODO use newest conflict resolver
177         ArtifactSpec a = createArtifactSpec("a", "1.0");
178         ArtifactSpec b1 = a.addDependency("b", "1.0");
179         ArtifactSpec c = a.addDependency("c", "1.0");
180         ArtifactSpec d2 = b1.addDependency("d", "2.0");
181         d2.addDependency("h", "1.0");
182         ArtifactSpec d1 = c.addDependency("d", "1.0");
183         ArtifactSpec b2 = c.addDependency("b", "2.0");
184         ArtifactSpec e = b2.addDependency("e", "1.0");
185         ArtifactSpec g = d1.addDependency("g", "1.0");
186 
187         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact}));
188         Object[] artifacts = new Object[] {a.artifact, c.artifact, d1.artifact, b2.artifact, e.artifact, g.artifact};
189         assertEquals("Check artifact list", createSet(artifacts), res.getArtifacts());
190         assertEquals(
191                 "Check version", "1.0", getArtifact("d", res.getArtifacts()).getVersion());
192         assertEquals(
193                 "Check version", "2.0", getArtifact("b", res.getArtifacts()).getVersion());
194     }
195 
196     public void testResolveNearestNewestIsNearest()
197             throws ArtifactResolutionException, InvalidVersionSpecificationException {
198         ArtifactSpec a = createArtifactSpec("a", "1.0");
199         ArtifactSpec b = a.addDependency("b", "1.0");
200         ArtifactSpec c = a.addDependency("c", "3.0");
201 
202         b.addDependency("c", "2.0");
203 
204         ArtifactResolutionResult res = collect(a);
205         assertEquals(
206                 "Check artifact list",
207                 createSet(new Object[] {a.artifact, b.artifact, c.artifact}),
208                 res.getArtifacts());
209         assertEquals(
210                 "Check version", "3.0", getArtifact("c", res.getArtifacts()).getVersion());
211     }
212 
213     public void testResolveNearestOldestIsNearest()
214             throws ArtifactResolutionException, InvalidVersionSpecificationException {
215         ArtifactSpec a = createArtifactSpec("a", "1.0");
216         ArtifactSpec b = a.addDependency("b", "1.0");
217         ArtifactSpec c = a.addDependency("c", "2.0");
218 
219         b.addDependency("c", "3.0");
220 
221         ArtifactResolutionResult res = collect(a);
222         assertEquals(
223                 "Check artifact list",
224                 createSet(new Object[] {a.artifact, b.artifact, c.artifact}),
225                 res.getArtifacts());
226         assertEquals(
227                 "Check version", "2.0", getArtifact("c", res.getArtifacts()).getVersion());
228     }
229 
230     public void testResolveLocalNewestIsLocal()
231             throws ArtifactResolutionException, InvalidVersionSpecificationException {
232         ArtifactSpec a = createArtifactSpec("a", "1.0");
233         a.addDependency("b", "2.0");
234         ArtifactSpec b = createArtifactSpec("b", "3.0");
235 
236         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
237         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts());
238         assertEquals(
239                 "Check version", "3.0", getArtifact("b", res.getArtifacts()).getVersion());
240     }
241 
242     public void testResolveLocalOldestIsLocal()
243             throws ArtifactResolutionException, InvalidVersionSpecificationException {
244         ArtifactSpec a = createArtifactSpec("a", "1.0");
245         a.addDependency("b", "3.0");
246         ArtifactSpec b = createArtifactSpec("b", "2.0");
247 
248         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
249         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts());
250         assertEquals(
251                 "Check version", "2.0", getArtifact("b", res.getArtifacts()).getVersion());
252     }
253 
254     public void testResolveLocalWithNewerVersionButLesserScope()
255             throws ArtifactResolutionException, InvalidVersionSpecificationException {
256         ArtifactSpec a = createArtifactSpec("commons-logging", "1.0");
257         a.addDependency("junit", "3.7");
258         ArtifactSpec b = createArtifactSpec("junit", "3.8.1", Artifact.SCOPE_TEST);
259 
260         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
261         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts());
262         assertEquals(
263                 "Check version",
264                 "3.8.1",
265                 getArtifact("junit", res.getArtifacts()).getVersion());
266         assertEquals(
267                 "Check artifactScope",
268                 Artifact.SCOPE_TEST,
269                 getArtifact("junit", res.getArtifacts()).getScope());
270     }
271 
272     public void testResolveLocalWithNewerVersionButLesserScopeResolvedFirst()
273             throws ArtifactResolutionException, InvalidVersionSpecificationException {
274         ArtifactSpec b = createArtifactSpec("junit", "3.8.1", Artifact.SCOPE_TEST);
275         ArtifactSpec a = createArtifactSpec("commons-logging", "1.0");
276         a.addDependency("junit", "3.7");
277 
278         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
279         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts());
280         assertEquals(
281                 "Check version",
282                 "3.8.1",
283                 getArtifact("junit", res.getArtifacts()).getVersion());
284         assertEquals(
285                 "Check artifactScope",
286                 Artifact.SCOPE_TEST,
287                 getArtifact("junit", res.getArtifacts()).getScope());
288     }
289 
290     public void testResolveNearestWithRanges()
291             throws ArtifactResolutionException, InvalidVersionSpecificationException {
292         ArtifactSpec a = createArtifactSpec("a", "1.0");
293         ArtifactSpec b = a.addDependency("b", "1.0");
294         ArtifactSpec c = a.addDependency("c", "2.0");
295 
296         b.addDependency("c", "[1.0,3.0]");
297 
298         ArtifactResolutionResult res = collect(a);
299         assertEquals(
300                 "Check artifact list",
301                 createSet(new Object[] {a.artifact, b.artifact, c.artifact}),
302                 res.getArtifacts());
303         assertEquals(
304                 "Check version", "2.0", getArtifact("c", res.getArtifacts()).getVersion());
305     }
306 
307     public void testResolveRangeWithManagedVersion()
308             throws ArtifactResolutionException, InvalidVersionSpecificationException {
309         ArtifactSpec a = createArtifactSpec("a", "1.0");
310         ArtifactSpec b = a.addDependency("b", "[1.0,3.0]");
311 
312         ArtifactSpec managedB = createArtifactSpec("b", "5.0");
313 
314         ArtifactResolutionResult res = collect(a, managedB.artifact);
315         assertEquals(
316                 "Check artifact list", createSet(new Object[] {a.artifact, managedB.artifact}), res.getArtifacts());
317         assertEquals(
318                 "Check version", "5.0", getArtifact("b", res.getArtifacts()).getVersion());
319     }
320 
321     public void testCompatibleRanges() throws ArtifactResolutionException, InvalidVersionSpecificationException {
322         ArtifactSpec a = createArtifactSpec("a", "1.0");
323         ArtifactSpec b = a.addDependency("b", "1.0");
324         a.addDependency("c", "[2.0,2.5]");
325         b.addDependency("c", "[1.0,3.0]");
326         ArtifactSpec c = createArtifactSpec("c", "2.5");
327 
328         ArtifactResolutionResult res = collect(a);
329 
330         assertEquals(
331                 "Check artifact list",
332                 createSet(new Object[] {a.artifact, b.artifact, c.artifact}),
333                 res.getArtifacts());
334         assertEquals(
335                 "Check version", "2.5", getArtifact("c", res.getArtifacts()).getVersion());
336     }
337 
338     public void testIncompatibleRanges() throws ArtifactResolutionException, InvalidVersionSpecificationException {
339         ArtifactSpec a = createArtifactSpec("a", "1.0");
340         ArtifactSpec b = a.addDependency("b", "1.0");
341         a.addDependency("c", "[2.4,3.0]");
342 
343         b.addDependency("c", "[1.0,2.0]");
344 
345         ArtifactResolutionResult res = collect(a);
346 
347         assertTrue(res.hasVersionRangeViolations());
348     }
349 
350     public void testUnboundedRangeWhenVersionUnavailable()
351             throws ArtifactResolutionException, InvalidVersionSpecificationException {
352         ArtifactSpec a = createArtifactSpec("a", "1.0");
353         ArtifactSpec b = a.addDependency("b", "1.0");
354         a.addDependency("c", "[2.0,]");
355         b.addDependency("c", "[1.0,]");
356 
357         ArtifactResolutionResult res = collect(a);
358 
359         assertTrue(res.hasVersionRangeViolations());
360     }
361 
362     public void testUnboundedRangeBelowLastRelease()
363             throws ArtifactResolutionException, InvalidVersionSpecificationException {
364         ArtifactSpec a = createArtifactSpec("a", "1.0");
365         createArtifactSpec("c", "1.5");
366         ArtifactSpec c = createArtifactSpec("c", "2.0");
367         createArtifactSpec("c", "1.1");
368         a.addDependency("c", "[1.0,)");
369 
370         ArtifactResolutionResult res = collect(a);
371 
372         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, c.artifact}), res.getArtifacts());
373         assertEquals(
374                 "Check version", "2.0", getArtifact("c", res.getArtifacts()).getVersion());
375     }
376 
377     public void testUnboundedRangeAboveLastRelease()
378             throws ArtifactResolutionException, InvalidVersionSpecificationException {
379         ArtifactSpec a = createArtifactSpec("a", "1.0");
380         createArtifactSpec("c", "2.0");
381         a.addDependency("c", "[10.0,)");
382 
383         ArtifactResolutionResult res = collect(a);
384 
385         assertTrue(res.hasVersionRangeViolations());
386     }
387 
388     public void testResolveManagedVersion() throws ArtifactResolutionException, InvalidVersionSpecificationException {
389         ArtifactSpec a = createArtifactSpec("a", "1.0");
390         a.addDependency("b", "3.0", Artifact.SCOPE_RUNTIME);
391 
392         Artifact managedVersion = createArtifactSpec("b", "5.0").artifact;
393         Artifact modifiedB = createArtifactSpec("b", "5.0", Artifact.SCOPE_RUNTIME).artifact;
394 
395         ArtifactResolutionResult res = collect(a, managedVersion);
396         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, modifiedB}), res.getArtifacts());
397     }
398 
399     public void testCollectChangesVersionOfOriginatingArtifactIfInDependencyManagementHasDifferentVersion()
400             throws ArtifactResolutionException, InvalidVersionSpecificationException {
401         ArtifactSpec a = createArtifactSpec("a", "1.0");
402 
403         Artifact artifact = projectArtifact.artifact;
404         Artifact managedVersion = createArtifactSpec(artifact.getArtifactId(), "2.0").artifact;
405 
406         ArtifactResolutionResult result = collect(a, managedVersion);
407 
408         assertEquals("collect has modified version in originating artifact", "1.0", artifact.getVersion());
409 
410         Artifact resolvedArtifact = result.getArtifacts().iterator().next();
411 
412         assertEquals("Resolved version don't match original artifact version", "1.0", resolvedArtifact.getVersion());
413     }
414 
415     public void testResolveCompileScopeOverTestScope()
416             throws ArtifactResolutionException, InvalidVersionSpecificationException {
417         ArtifactSpec a = createArtifactSpec("a", "1.0");
418         ArtifactSpec c = createArtifactSpec("c", "3.0", Artifact.SCOPE_TEST);
419 
420         a.addDependency("c", "2.0", Artifact.SCOPE_COMPILE);
421 
422         Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_COMPILE).artifact;
423 
424         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, c.artifact}));
425         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, modifiedC}), res.getArtifacts());
426         Artifact artifact = getArtifact("c", res.getArtifacts());
427         // local wins now, and irrelevant if not local as test/provided aren't transitive
428         // assertEquals( "Check artifactScope", Artifact.SCOPE_COMPILE, artifact.getArtifactScope() );
429         assertEquals("Check artifactScope", Artifact.SCOPE_TEST, artifact.getScope());
430     }
431 
432     public void testResolveRuntimeScopeOverTestScope()
433             throws ArtifactResolutionException, InvalidVersionSpecificationException {
434         ArtifactSpec a = createArtifactSpec("a", "1.0");
435         ArtifactSpec c = createArtifactSpec("c", "3.0", Artifact.SCOPE_TEST);
436 
437         a.addDependency("c", "2.0", Artifact.SCOPE_RUNTIME);
438 
439         Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_RUNTIME).artifact;
440 
441         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, c.artifact}));
442         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, modifiedC}), res.getArtifacts());
443         Artifact artifact = getArtifact("c", res.getArtifacts());
444         // local wins now, and irrelevant if not local as test/provided aren't transitive
445         // assertEquals( "Check artifactScope", Artifact.SCOPE_RUNTIME, artifact.getArtifactScope() );
446         assertEquals("Check artifactScope", Artifact.SCOPE_TEST, artifact.getScope());
447     }
448 
449     public void testResolveCompileScopeOverRuntimeScope()
450             throws ArtifactResolutionException, InvalidVersionSpecificationException {
451         ArtifactSpec root = createArtifactSpec("root", "1.0");
452         ArtifactSpec a = root.addDependency("a", "1.0");
453         root.addDependency("c", "3.0", Artifact.SCOPE_RUNTIME);
454 
455         a.addDependency("c", "2.0", Artifact.SCOPE_COMPILE);
456 
457         Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_COMPILE).artifact;
458 
459         ArtifactResolutionResult res = collect(createSet(new Object[] {root.artifact}));
460         assertEquals(
461                 "Check artifact list",
462                 createSet(new Object[] {a.artifact, root.artifact, modifiedC}),
463                 res.getArtifacts());
464         Artifact artifact = getArtifact("c", res.getArtifacts());
465         assertEquals("Check artifactScope", Artifact.SCOPE_COMPILE, artifact.getScope());
466     }
467 
468     public void testResolveCompileScopeOverProvidedScope()
469             throws ArtifactResolutionException, InvalidVersionSpecificationException {
470         ArtifactSpec a = createArtifactSpec("a", "1.0");
471         ArtifactSpec c = createArtifactSpec("c", "3.0", Artifact.SCOPE_PROVIDED);
472 
473         a.addDependency("c", "2.0", Artifact.SCOPE_COMPILE);
474 
475         Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_COMPILE).artifact;
476 
477         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, c.artifact}));
478         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, modifiedC}), res.getArtifacts());
479         Artifact artifact = getArtifact("c", res.getArtifacts());
480         // local wins now, and irrelevant if not local as test/provided aren't transitive
481         // assertEquals( "Check artifactScope", Artifact.SCOPE_COMPILE, artifact.getArtifactScope() );
482         assertEquals("Check artifactScope", Artifact.SCOPE_PROVIDED, artifact.getScope());
483     }
484 
485     public void testResolveRuntimeScopeOverProvidedScope()
486             throws ArtifactResolutionException, InvalidVersionSpecificationException {
487         ArtifactSpec a = createArtifactSpec("a", "1.0");
488         ArtifactSpec c = createArtifactSpec("c", "3.0", Artifact.SCOPE_PROVIDED);
489 
490         a.addDependency("c", "2.0", Artifact.SCOPE_RUNTIME);
491 
492         Artifact modifiedC = createArtifactSpec("c", "3.0", Artifact.SCOPE_RUNTIME).artifact;
493 
494         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, c.artifact}));
495         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, modifiedC}), res.getArtifacts());
496         Artifact artifact = getArtifact("c", res.getArtifacts());
497         // local wins now, and irrelevant if not local as test/provided aren't transitive
498         // assertEquals( "Check artifactScope", Artifact.SCOPE_RUNTIME, artifact.getArtifactScope() );
499         assertEquals("Check artifactScope", Artifact.SCOPE_PROVIDED, artifact.getScope());
500     }
501 
502     public void testProvidedScopeNotTransitive()
503             throws ArtifactResolutionException, InvalidVersionSpecificationException {
504         ArtifactSpec a = createArtifactSpec("a", "1.0", Artifact.SCOPE_PROVIDED);
505         ArtifactSpec b = createArtifactSpec("b", "1.0");
506         b.addDependency("c", "3.0", Artifact.SCOPE_PROVIDED);
507 
508         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
509         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts());
510     }
511 
512     public void testOptionalNotTransitive() throws ArtifactResolutionException, InvalidVersionSpecificationException {
513         ArtifactSpec a = createArtifactSpec("a", "1.0");
514         ArtifactSpec b = createArtifactSpec("b", "1.0");
515         b.addDependency("c", "3.0", true);
516 
517         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
518         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts());
519     }
520 
521     public void testOptionalIncludedAtRoot() throws ArtifactResolutionException, InvalidVersionSpecificationException {
522         ArtifactSpec a = createArtifactSpec("a", "1.0");
523 
524         ArtifactSpec b = createArtifactSpec("b", "1.0", true);
525 
526         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
527         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts());
528     }
529 
530     public void testScopeUpdate() throws InvalidVersionSpecificationException, ArtifactResolutionException {
531         /* farthest = compile */
532         checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
533         checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_COMPILE);
534         checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_COMPILE);
535         checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_COMPILE);
536         checkScopeUpdate(Artifact.SCOPE_COMPILE, Artifact.SCOPE_TEST, Artifact.SCOPE_COMPILE);
537 
538         /* farthest = provided */
539         checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
540         checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED);
541         checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME);
542         checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM);
543         checkScopeUpdate(Artifact.SCOPE_PROVIDED, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST);
544 
545         /* farthest = runtime */
546         checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
547         checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_RUNTIME);
548         checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME);
549         checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM);
550         checkScopeUpdate(Artifact.SCOPE_RUNTIME, Artifact.SCOPE_TEST, Artifact.SCOPE_RUNTIME);
551 
552         /* farthest = system */
553         checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
554         checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED);
555         checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME);
556         checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM);
557         checkScopeUpdate(Artifact.SCOPE_SYSTEM, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST);
558 
559         /* farthest = test */
560         checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_COMPILE, Artifact.SCOPE_COMPILE);
561         checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_PROVIDED, Artifact.SCOPE_PROVIDED);
562         checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_RUNTIME);
563         checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_SYSTEM, Artifact.SCOPE_SYSTEM);
564         checkScopeUpdate(Artifact.SCOPE_TEST, Artifact.SCOPE_TEST, Artifact.SCOPE_TEST);
565     }
566 
567     private void checkScopeUpdate(String farthestScope, String nearestScope, String expectedScope)
568             throws ArtifactResolutionException, InvalidVersionSpecificationException {
569         checkScopeUpdateDirect(farthestScope, nearestScope, expectedScope);
570         checkScopeUpdateTransitively(farthestScope, nearestScope, expectedScope);
571     }
572 
573     private void checkScopeUpdateTransitively(String farthestScope, String nearestScope, String expectedScope)
574             throws ArtifactResolutionException, InvalidVersionSpecificationException {
575         ArtifactSpec a = createArtifactSpec("a", "1.0");
576         ArtifactSpec b = createArtifactSpec("b", "1.0", nearestScope);
577         ArtifactSpec c = createArtifactSpec("c", "1.0");
578         a.addDependency(c);
579         ArtifactSpec dNearest = createArtifactSpec("d", "2.0");
580         b.addDependency(dNearest);
581         ArtifactSpec dFarthest = createArtifactSpec("d", "3.0", farthestScope);
582         c.addDependency(dFarthest);
583 
584         /* system and provided dependencies are not transitive */
585         if (!Artifact.SCOPE_SYSTEM.equals(nearestScope) && !Artifact.SCOPE_PROVIDED.equals(nearestScope)) {
586             checkScopeUpdate(a, b, expectedScope, "2.0");
587         }
588     }
589 
590     private void checkScopeUpdateDirect(String farthestScope, String nearestScope, String expectedScope)
591             throws ArtifactResolutionException, InvalidVersionSpecificationException {
592         ArtifactSpec a = createArtifactSpec("a", "1.0");
593         ArtifactSpec b = createArtifactSpec("b", "1.0");
594         ArtifactSpec c = createArtifactSpec("c", "1.0");
595         a.addDependency(c);
596         ArtifactSpec dNearest = createArtifactSpec("d", "2.0", nearestScope);
597         b.addDependency(dNearest);
598         ArtifactSpec dFarthest = createArtifactSpec("d", "3.0", farthestScope);
599         c.addDependency(dFarthest);
600 
601         checkScopeUpdate(a, b, expectedScope, "2.0");
602     }
603 
604     private void checkScopeUpdate(ArtifactSpec a, ArtifactSpec b, String expectedScope, String expectedVersion)
605             throws ArtifactResolutionException, InvalidVersionSpecificationException {
606         ScopeArtifactFilter filter;
607         if (Artifact.SCOPE_PROVIDED.equals(expectedScope)) {
608             filter = new ScopeArtifactFilter(Artifact.SCOPE_COMPILE);
609         } else if (Artifact.SCOPE_SYSTEM.equals(expectedScope)) {
610             filter = new ScopeArtifactFilter(Artifact.SCOPE_COMPILE);
611         } else {
612             filter = new ScopeArtifactFilter(expectedScope);
613         }
614 
615         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}), filter);
616         Artifact artifact = getArtifact("d", res.getArtifacts());
617         assertNotNull("MNG-1895 Dependency was not added to resolution", artifact);
618         assertEquals("Check artifactScope", expectedScope, artifact.getScope());
619         assertEquals("Check version", expectedVersion, artifact.getVersion());
620 
621         ArtifactSpec d = createArtifactSpec("d", "1.0");
622         res = collect(createSet(new Object[] {a.artifact, b.artifact, d.artifact}), filter);
623         artifact = getArtifact("d", res.getArtifacts());
624         assertNotNull("MNG-1895 Dependency was not added to resolution", artifact);
625         assertEquals("Check artifactScope", d.artifact.getScope(), artifact.getScope());
626         assertEquals("Check version", "1.0", artifact.getVersion());
627     }
628 
629     public void disabledtestOptionalNotTransitiveButVersionIsInfluential()
630             throws ArtifactResolutionException, InvalidVersionSpecificationException {
631         ArtifactSpec a = createArtifactSpec("a", "1.0");
632         ArtifactSpec b = createArtifactSpec("b", "1.0");
633         b.addDependency("c", "3.0", true);
634         ArtifactSpec d = a.addDependency("d", "1.0");
635         ArtifactSpec e = d.addDependency("e", "1.0");
636         e.addDependency("c", "2.0");
637 
638         ArtifactSpec c = createArtifactSpec("c", "3.0");
639 
640         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
641         assertEquals(
642                 "Check artifact list",
643                 createSet(new Object[] {a.artifact, b.artifact, c.artifact, d.artifact, e.artifact}),
644                 res.getArtifacts());
645         Artifact artifact = getArtifact("c", res.getArtifacts());
646         assertEquals("Check version", "3.0", artifact.getVersion());
647     }
648 
649     public void testTestScopeNotTransitive() throws ArtifactResolutionException, InvalidVersionSpecificationException {
650         ArtifactSpec a = createArtifactSpec("a", "1.0", Artifact.SCOPE_TEST);
651         ArtifactSpec b = createArtifactSpec("b", "1.0");
652         b.addDependency("c", "3.0", Artifact.SCOPE_TEST);
653 
654         ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact, b.artifact}));
655         assertEquals("Check artifact list", createSet(new Object[] {a.artifact, b.artifact}), res.getArtifacts());
656     }
657 
658     public void testSnapshotNotIncluded() throws ArtifactResolutionException, InvalidVersionSpecificationException {
659         ArtifactSpec a = createArtifactSpec("a", "1.0");
660         a.addDependency("b", "[1.0,)");
661         createArtifactSpec("b", "1.0-SNAPSHOT");
662 
663         ArtifactResolutionResult res = collect(a);
664 
665         assertTrue(res.hasVersionRangeViolations());
666 
667         /*
668          * try { ArtifactResolutionResult res = collect( a ); fail( "Expected b not to resolve: " + res ); } catch (
669          * OverConstrainedVersionException e ) { assertTrue( e.getMessage().indexOf( "[1.0-SNAPSHOT]" ) <
670          * e.getMessage().indexOf( "[1.0,)" ) ); }
671          */
672     }
673 
674     public void testOverConstrainedVersionException()
675             throws ArtifactResolutionException, InvalidVersionSpecificationException {
676         ArtifactSpec a = createArtifactSpec("a", "1.0");
677         a.addDependency("b", "[1.0, 2.0)");
678         a.addDependency("c", "[3.3.0,4.0.0)");
679 
680         ArtifactSpec b = createArtifactSpec("b", "1.0.0");
681         b.addDependency("c", "3.3.0-v3346");
682 
683         ArtifactSpec c = createArtifactSpec("c", "3.2.1-v3235e");
684 
685         try {
686             ArtifactResolutionResult res = collect(createSet(new Object[] {a.artifact}));
687         } catch (OverConstrainedVersionException e) {
688             assertTrue("Versions unordered", e.getMessage().contains("[3.2.1-v3235e, 3.3.0-v3346]"));
689             assertTrue("DependencyTrail unresolved", e.getMessage().contains("Path to dependency:"));
690         }
691     }
692 
693     private Artifact getArtifact(String id, Set artifacts) {
694         for (Object artifact : artifacts) {
695             Artifact a = (Artifact) artifact;
696             if (a.getArtifactId().equals(id) && a.getGroupId().equals(GROUP_ID)) {
697                 return a;
698             }
699         }
700         return null;
701     }
702 
703     private ArtifactResolutionResult collect(Set<Artifact> artifacts) throws ArtifactResolutionException {
704         return collect(artifacts, null);
705     }
706 
707     private ArtifactResolutionResult collect(Set<Artifact> artifacts, ArtifactFilter filter)
708             throws ArtifactResolutionException {
709         return artifactCollector.collect(
710                 artifacts,
711                 projectArtifact.artifact,
712                 null,
713                 null,
714                 null,
715                 source,
716                 filter,
717                 Collections.<ResolutionListener>emptyList(),
718                 null);
719     }
720 
721     private ArtifactResolutionResult collect(ArtifactSpec a) throws ArtifactResolutionException {
722         return artifactCollector.collect(
723                 Collections.singleton(a.artifact),
724                 projectArtifact.artifact,
725                 null,
726                 null,
727                 null,
728                 source,
729                 null,
730                 Collections.<ResolutionListener>emptyList(),
731                 null);
732     }
733 
734     private ArtifactResolutionResult collect(ArtifactSpec a, ArtifactFilter filter) throws ArtifactResolutionException {
735         return artifactCollector.collect(
736                 Collections.singleton(a.artifact),
737                 projectArtifact.artifact,
738                 null,
739                 null,
740                 null,
741                 source,
742                 filter,
743                 Collections.<ResolutionListener>emptyList(),
744                 null);
745     }
746 
747     private ArtifactResolutionResult collect(ArtifactSpec a, Artifact managedVersion)
748             throws ArtifactResolutionException {
749         Map managedVersions = Collections.singletonMap(managedVersion.getDependencyConflictId(), managedVersion);
750         return artifactCollector.collect(
751                 Collections.singleton(a.artifact),
752                 projectArtifact.artifact,
753                 managedVersions,
754                 null,
755                 null,
756                 source,
757                 null,
758                 Collections.<ResolutionListener>emptyList(),
759                 null);
760     }
761 
762     private ArtifactSpec createArtifactSpec(String id, String version) throws InvalidVersionSpecificationException {
763         return createArtifactSpec(id, version, Artifact.SCOPE_COMPILE);
764     }
765 
766     private ArtifactSpec createArtifactSpec(String id, String version, boolean optional)
767             throws InvalidVersionSpecificationException {
768         return createArtifactSpec(id, version, Artifact.SCOPE_COMPILE, null, optional);
769     }
770 
771     private ArtifactSpec createArtifactSpec(String id, String version, String scope)
772             throws InvalidVersionSpecificationException {
773         return createArtifactSpec(id, version, scope, null, false);
774     }
775 
776     private ArtifactSpec createArtifactSpec(
777             String id, String version, String scope, String inheritedScope, boolean optional)
778             throws InvalidVersionSpecificationException {
779         VersionRange versionRange = VersionRange.createFromVersionSpec(version);
780         Artifact artifact = artifactFactory.createDependencyArtifact(
781                 GROUP_ID, id, versionRange, "jar", null, scope, inheritedScope, optional);
782         ArtifactSpec spec = null;
783         if (artifact != null) {
784             spec = new ArtifactSpec();
785             spec.artifact = artifact;
786             source.addArtifact(spec);
787         }
788         return spec;
789     }
790 
791     @SuppressWarnings("unchecked")
792     private static Set<Artifact> createSet(Object[] x) {
793         return new LinkedHashSet(Arrays.asList(x));
794     }
795 
796     private class ArtifactSpec {
797         private Artifact artifact;
798 
799         private Set<Artifact> dependencies = new HashSet<>();
800 
801         public ArtifactSpec addDependency(String id, String version) throws InvalidVersionSpecificationException {
802             return addDependency(id, version, Artifact.SCOPE_COMPILE);
803         }
804 
805         public ArtifactSpec addDependency(String id, String version, String scope)
806                 throws InvalidVersionSpecificationException {
807             return addDependency(id, version, scope, false);
808         }
809 
810         private ArtifactSpec addDependency(ArtifactSpec dep) throws InvalidVersionSpecificationException {
811             if (dep != null) {
812                 dependencies.add(dep.artifact);
813             }
814             return dep;
815         }
816 
817         private ArtifactSpec addDependency(String id, String version, String scope, boolean optional)
818                 throws InvalidVersionSpecificationException {
819             ArtifactSpec dep = createArtifactSpec(id, version, scope, artifact.getScope(), optional);
820             return addDependency(dep);
821         }
822 
823         public ArtifactSpec addDependency(String id, String version, boolean optional)
824                 throws InvalidVersionSpecificationException {
825             return addDependency(id, version, Artifact.SCOPE_COMPILE, optional);
826         }
827     }
828 
829     private class Source implements ArtifactMetadataSource {
830         private Map<String, ArtifactSpec> artifacts = new HashMap<>();
831 
832         private Map<String, List<ArtifactVersion>> versions = new HashMap<>();
833 
834         public ResolutionGroup retrieve(
835                 Artifact artifact, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories)
836                 throws ArtifactMetadataRetrievalException {
837             String key = getKey(artifact);
838 
839             ArtifactSpec a = (ArtifactSpec) artifacts.get(key);
840             try {
841                 return new ResolutionGroup(
842                         artifact,
843                         createArtifacts(
844                                 artifactFactory, a.dependencies, artifact.getScope(), artifact.getDependencyFilter()),
845                         Collections.EMPTY_LIST);
846             } catch (InvalidVersionSpecificationException e) {
847                 throw new ArtifactMetadataRetrievalException("Invalid version creating artifacts", e, artifact);
848             }
849         }
850 
851         private String getKey(Artifact artifact) {
852             return artifact.getDependencyConflictId();
853         }
854 
855         private Set<Artifact> createArtifacts(
856                 ArtifactFactory artifactFactory,
857                 Set<Artifact> dependencies,
858                 String inheritedScope,
859                 ArtifactFilter dependencyFilter)
860                 throws InvalidVersionSpecificationException {
861             Set<Artifact> projectArtifacts = new HashSet<>();
862 
863             for (Artifact d : dependencies) {
864                 VersionRange versionRange;
865                 if (d.getVersionRange() != null) {
866                     versionRange = d.getVersionRange();
867                 } else {
868                     versionRange = VersionRange.createFromVersionSpec(d.getVersion());
869                 }
870                 Artifact artifact;
871                 if (d.getScope().equals(Artifact.SCOPE_TEST) || d.getScope().equals(Artifact.SCOPE_PROVIDED)) {
872                     /* don't call createDependencyArtifact as it'll ignore test and provided scopes */
873                     artifact = artifactFactory.createArtifact(
874                             d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getScope(), d.getType());
875                 } else {
876                     artifact = artifactFactory.createDependencyArtifact(
877                             d.getGroupId(),
878                             d.getArtifactId(),
879                             versionRange,
880                             d.getType(),
881                             d.getClassifier(),
882                             d.getScope(),
883                             inheritedScope,
884                             d.isOptional());
885                 }
886 
887                 if (artifact != null && (dependencyFilter == null || dependencyFilter.include(artifact))) {
888                     artifact.setDependencyFilter(dependencyFilter);
889 
890                     projectArtifacts.add(artifact);
891                 }
892             }
893 
894             return projectArtifacts;
895         }
896 
897         public void addArtifact(ArtifactSpec spec) {
898             artifacts.put(getKey(spec.artifact), spec);
899 
900             String key = spec.artifact.getDependencyConflictId();
901             List<ArtifactVersion> artifactVersions = versions.get(key);
902             if (artifactVersions == null) {
903                 artifactVersions = new ArrayList<>();
904                 versions.put(key, artifactVersions);
905             }
906             if (spec.artifact.getVersion() != null) {
907                 artifactVersions.add(new DefaultArtifactVersion(spec.artifact.getVersion()));
908             }
909         }
910 
911         public List<ArtifactVersion> retrieveAvailableVersions(
912                 Artifact artifact, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories)
913                 throws ArtifactMetadataRetrievalException {
914             return retrieveAvailableVersions(artifact);
915         }
916 
917         public List<ArtifactVersion> retrieveAvailableVersionsFromDeploymentRepository(
918                 Artifact artifact, ArtifactRepository localRepository, ArtifactRepository remoteRepository)
919                 throws ArtifactMetadataRetrievalException {
920             return retrieveAvailableVersions(artifact);
921         }
922 
923         private List<ArtifactVersion> retrieveAvailableVersions(Artifact artifact) {
924             List<ArtifactVersion> artifactVersions = versions.get(artifact.getDependencyConflictId());
925             if (artifactVersions == null) {
926                 artifactVersions = Collections.emptyList();
927             }
928             return artifactVersions;
929         }
930 
931         public ResolutionGroup retrieve(MetadataResolutionRequest request) throws ArtifactMetadataRetrievalException {
932             return retrieve(request.getArtifact(), request.getLocalRepository(), request.getRemoteRepositories());
933         }
934 
935         public List<ArtifactVersion> retrieveAvailableVersions(MetadataResolutionRequest request)
936                 throws ArtifactMetadataRetrievalException {
937             return retrieveAvailableVersions(
938                     request.getArtifact(), request.getLocalRepository(), request.getRemoteRepositories());
939         }
940     }
941 }