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