001package org.eclipse.aether.internal.impl.collect;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.Arrays;
025import java.util.Collection;
026import java.util.Collections;
027import java.util.HashMap;
028import java.util.Iterator;
029import java.util.LinkedList;
030import java.util.List;
031import java.util.Map;
032
033import org.eclipse.aether.DefaultRepositorySystemSession;
034import org.eclipse.aether.RepositorySystemSession;
035import org.eclipse.aether.artifact.Artifact;
036import org.eclipse.aether.artifact.ArtifactProperties;
037import org.eclipse.aether.artifact.DefaultArtifact;
038import org.eclipse.aether.collection.CollectRequest;
039import org.eclipse.aether.collection.CollectResult;
040import org.eclipse.aether.collection.DependencyCollectionContext;
041import org.eclipse.aether.collection.DependencyCollectionException;
042import org.eclipse.aether.collection.DependencyManagement;
043import org.eclipse.aether.collection.DependencyManager;
044import org.eclipse.aether.graph.DefaultDependencyNode;
045import org.eclipse.aether.graph.Dependency;
046import org.eclipse.aether.graph.DependencyCycle;
047import org.eclipse.aether.graph.DependencyNode;
048import org.eclipse.aether.graph.Exclusion;
049import org.eclipse.aether.impl.ArtifactDescriptorReader;
050import org.eclipse.aether.internal.impl.IniArtifactDescriptorReader;
051import org.eclipse.aether.internal.test.util.DependencyGraphParser;
052import org.eclipse.aether.internal.test.util.TestUtils;
053import org.eclipse.aether.repository.RemoteRepository;
054import org.eclipse.aether.resolution.ArtifactDescriptorException;
055import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
056import org.eclipse.aether.resolution.ArtifactDescriptorResult;
057import org.eclipse.aether.util.artifact.ArtifactIdUtils;
058import org.eclipse.aether.util.graph.manager.ClassicDependencyManager;
059import org.eclipse.aether.util.graph.manager.DefaultDependencyManager;
060import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
061import org.eclipse.aether.util.graph.manager.TransitiveDependencyManager;
062import org.eclipse.aether.util.graph.transformer.ConflictResolver;
063import org.eclipse.aether.util.graph.transformer.JavaScopeDeriver;
064import org.eclipse.aether.util.graph.transformer.JavaScopeSelector;
065import org.eclipse.aether.util.graph.transformer.NearestVersionSelector;
066import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector;
067import org.eclipse.aether.util.graph.version.HighestVersionFilter;
068import org.junit.Before;
069import org.junit.Test;
070
071import static java.util.Collections.singletonList;
072import static java.util.Objects.requireNonNull;
073import static org.junit.Assert.assertEquals;
074import static org.junit.Assert.assertNotEquals;
075import static org.junit.Assert.assertNotNull;
076import static org.junit.Assert.assertNull;
077import static org.junit.Assert.assertSame;
078import static org.junit.Assert.assertTrue;
079import static org.junit.Assert.fail;
080
081/**
082 * Common tests for various {@link DependencyCollectorDelegate} implementations.
083 */
084public abstract class DependencyCollectorDelegateTestSupport
085{
086
087    protected DefaultRepositorySystemSession session;
088
089    protected DependencyGraphParser parser;
090
091    protected RemoteRepository repository;
092
093    protected DependencyCollectorDelegate collector;
094
095    protected IniArtifactDescriptorReader newReader( String prefix )
096    {
097        return new IniArtifactDescriptorReader( "artifact-descriptions/" + prefix );
098    }
099
100    protected Dependency newDep( String coords )
101    {
102        return newDep( coords, "" );
103    }
104
105    protected Dependency newDep( String coords, String scope )
106    {
107        return new Dependency( new DefaultArtifact( coords ), scope );
108    }
109
110    @Before
111    public void setup()
112    {
113        session = TestUtils.newSession();
114        parser = new DependencyGraphParser( "artifact-descriptions/" );
115        repository = new RemoteRepository.Builder( "id", "default", "file:///" ).build();
116        setupCollector();
117    }
118
119    protected abstract void setupCollector();
120
121    private static void assertEqualSubtree( DependencyNode expected, DependencyNode actual )
122    {
123        assertEqualSubtree( expected, actual, new LinkedList<>() );
124    }
125
126    private static void assertEqualSubtree( DependencyNode expected, DependencyNode actual,
127                                            LinkedList<DependencyNode> parents )
128    {
129        assertEquals( "path: " + parents, expected.getDependency(), actual.getDependency() );
130
131        if ( actual.getDependency() != null )
132        {
133            Artifact artifact = actual.getDependency().getArtifact();
134            for ( DependencyNode parent : parents )
135            {
136                if ( parent.getDependency() != null && artifact.equals( parent.getDependency().getArtifact() ) )
137                {
138                    return;
139                }
140            }
141        }
142
143        parents.addLast( expected );
144
145        assertEquals( "path: " + parents + ", expected: " + expected.getChildren() + ", actual: "
146                + actual.getChildren(), expected.getChildren().size(), actual.getChildren().size() );
147
148        Iterator<DependencyNode> iterator1 = expected.getChildren().iterator();
149        Iterator<DependencyNode> iterator2 = actual.getChildren().iterator();
150
151        while ( iterator1.hasNext() )
152        {
153            assertEqualSubtree( iterator1.next(), iterator2.next(), parents );
154        }
155
156        parents.removeLast();
157    }
158
159    protected Dependency dep( DependencyNode root, int... coords )
160    {
161        return path( root, coords ).getDependency();
162    }
163
164    protected DependencyNode path( DependencyNode root, int... coords )
165    {
166        try
167        {
168            DependencyNode node = root;
169            for ( int coord : coords )
170            {
171                node = node.getChildren().get( coord );
172            }
173
174            return node;
175        }
176        catch ( IndexOutOfBoundsException | NullPointerException e )
177        {
178            throw new IllegalArgumentException( "illegal coordinates for child", e );
179        }
180    }
181
182    @Test
183    public void testSimpleCollection()
184            throws DependencyCollectionException
185    {
186        Dependency dependency = newDep( "gid:aid:ext:ver", "compile" );
187        CollectRequest request = new CollectRequest( dependency, singletonList( repository ) );
188        CollectResult result = collector.collectDependencies( session, request );
189
190        assertEquals( 0, result.getExceptions().size() );
191
192        DependencyNode root = result.getRoot();
193        Dependency newDependency = root.getDependency();
194
195        assertEquals( dependency, newDependency );
196        assertEquals( dependency.getArtifact(), newDependency.getArtifact() );
197
198        assertEquals( 1, root.getChildren().size() );
199
200        Dependency expect = newDep( "gid:aid2:ext:ver", "compile" );
201        assertEquals( expect, root.getChildren().get( 0 ).getDependency() );
202    }
203
204    @Test
205    public void testMissingDependencyDescription()
206    {
207        CollectRequest request =
208                new CollectRequest( newDep( "missing:description:ext:ver" ), singletonList( repository ) );
209        try
210        {
211            collector.collectDependencies( session, request );
212            fail( "expected exception" );
213        }
214        catch ( DependencyCollectionException e )
215        {
216            CollectResult result = e.getResult();
217            assertSame( request, result.getRequest() );
218            assertNotNull( result.getExceptions() );
219            assertEquals( 1, result.getExceptions().size() );
220
221            assertTrue( result.getExceptions().get( 0 ) instanceof ArtifactDescriptorException );
222
223            assertEquals( request.getRoot(), result.getRoot().getDependency() );
224        }
225    }
226
227    @Test
228    public void testDuplicates()
229            throws DependencyCollectionException
230    {
231        Dependency dependency = newDep( "duplicate:transitive:ext:dependency" );
232        CollectRequest request = new CollectRequest( dependency, singletonList( repository ) );
233
234        CollectResult result = collector.collectDependencies( session, request );
235
236        assertEquals( 0, result.getExceptions().size() );
237
238        DependencyNode root = result.getRoot();
239        Dependency newDependency = root.getDependency();
240
241        assertEquals( dependency, newDependency );
242        assertEquals( dependency.getArtifact(), newDependency.getArtifact() );
243
244        assertEquals( 2, root.getChildren().size() );
245
246        Dependency dep = newDep( "gid:aid:ext:ver", "compile" );
247        assertEquals( dep, dep( root, 0 ) );
248
249        dep = newDep( "gid:aid2:ext:ver", "compile" );
250        assertEquals( dep, dep( root, 1 ) );
251        assertEquals( dep, dep( root, 0, 0 ) );
252        assertEquals( dep( root, 1 ), dep( root, 0, 0 ) );
253    }
254
255    @Test
256    public void testEqualSubtree()
257            throws IOException, DependencyCollectionException
258    {
259        DependencyNode root = parser.parseResource( "expectedSubtreeComparisonResult.txt" );
260        Dependency dependency = root.getDependency();
261        CollectRequest request = new CollectRequest( dependency, singletonList( repository ) );
262
263        CollectResult result = collector.collectDependencies( session, request );
264        assertEqualSubtree( root, result.getRoot() );
265    }
266
267    @Test
268    public void testCyclicDependencies()
269            throws Exception
270    {
271        DependencyNode root = parser.parseResource( "cycle.txt" );
272        CollectRequest request = new CollectRequest( root.getDependency(), singletonList( repository ) );
273        CollectResult result = collector.collectDependencies( session, request );
274        assertEqualSubtree( root, result.getRoot() );
275    }
276
277    @Test
278    public void testCyclicDependenciesBig()
279            throws Exception
280    {
281        CollectRequest request = new CollectRequest( newDep( "1:2:pom:5.50-SNAPSHOT" ), singletonList( repository ) );
282        collector.setArtifactDescriptorReader( newReader( "cycle-big/" ) );
283        CollectResult result = collector.collectDependencies( session, request );
284        assertNotNull( result.getRoot() );
285        // we only care about the performance here, this test must not hang or run out of mem
286    }
287
288    @Test
289    public void testCyclicProjects()
290            throws Exception
291    {
292        CollectRequest request = new CollectRequest( newDep( "test:a:2" ), singletonList( repository ) );
293        collector.setArtifactDescriptorReader( newReader( "versionless-cycle/" ) );
294        CollectResult result = collector.collectDependencies( session, request );
295        DependencyNode root = result.getRoot();
296        DependencyNode a1 = path( root, 0, 0 );
297        assertEquals( "a", a1.getArtifact().getArtifactId() );
298        assertEquals( "1", a1.getArtifact().getVersion() );
299        for ( DependencyNode child : a1.getChildren() )
300        {
301            assertNotEquals( "1", child.getArtifact().getVersion() );
302        }
303
304        assertEquals( 1, result.getCycles().size() );
305        DependencyCycle cycle = result.getCycles().get( 0 );
306        assertEquals( Collections.emptyList(), cycle.getPrecedingDependencies() );
307        assertEquals( Arrays.asList( root.getDependency(), path( root, 0 ).getDependency(), a1.getDependency() ),
308                cycle.getCyclicDependencies() );
309    }
310
311    @Test
312    public void testCyclicProjects_ConsiderLabelOfRootlessGraph()
313            throws Exception
314    {
315        Dependency dep = newDep( "gid:aid:ver", "compile" );
316        CollectRequest request =
317                new CollectRequest().addDependency( dep ).addRepository( repository )
318                        .setRootArtifact( dep.getArtifact() );
319        CollectResult result = collector.collectDependencies( session, request );
320        DependencyNode root = result.getRoot();
321        DependencyNode a1 = root.getChildren().get( 0 );
322        assertEquals( "aid", a1.getArtifact().getArtifactId() );
323        assertEquals( "ver", a1.getArtifact().getVersion() );
324        DependencyNode a2 = a1.getChildren().get( 0 );
325        assertEquals( "aid2", a2.getArtifact().getArtifactId() );
326        assertEquals( "ver", a2.getArtifact().getVersion() );
327
328        assertEquals( 1, result.getCycles().size() );
329        DependencyCycle cycle = result.getCycles().get( 0 );
330        assertEquals( Collections.emptyList(), cycle.getPrecedingDependencies() );
331        assertEquals( Arrays.asList( new Dependency( dep.getArtifact(), null ), a1.getDependency() ),
332                cycle.getCyclicDependencies() );
333    }
334
335    @Test
336    public void testPartialResultOnError()
337            throws IOException
338    {
339        DependencyNode root = parser.parseResource( "expectedPartialSubtreeOnError.txt" );
340
341        Dependency dependency = root.getDependency();
342        CollectRequest request = new CollectRequest( dependency, singletonList( repository ) );
343
344        CollectResult result;
345        try
346        {
347            result = collector.collectDependencies( session, request );
348            fail( "expected exception " );
349        }
350        catch ( DependencyCollectionException e )
351        {
352            result = e.getResult();
353
354            assertSame( request, result.getRequest() );
355            assertNotNull( result.getExceptions() );
356            assertEquals( 1, result.getExceptions().size() );
357
358            assertTrue( result.getExceptions().get( 0 ) instanceof ArtifactDescriptorException );
359
360            assertEqualSubtree( root, result.getRoot() );
361        }
362    }
363
364    @Test
365    public void testCollectMultipleDependencies()
366            throws DependencyCollectionException
367    {
368        Dependency root1 = newDep( "gid:aid:ext:ver", "compile" );
369        Dependency root2 = newDep( "gid:aid2:ext:ver", "compile" );
370        List<Dependency> dependencies = Arrays.asList( root1, root2 );
371        CollectRequest request = new CollectRequest( dependencies, null, singletonList( repository ) );
372        CollectResult result = collector.collectDependencies( session, request );
373
374        assertEquals( 0, result.getExceptions().size() );
375        assertEquals( 2, result.getRoot().getChildren().size() );
376        assertEquals( root1, dep( result.getRoot(), 0 ) );
377
378        assertEquals( 1, path( result.getRoot(), 0 ).getChildren().size() );
379        assertEquals( root2, dep( result.getRoot(), 0, 0 ) );
380
381        assertEquals( 0, path( result.getRoot(), 1 ).getChildren().size() );
382        assertEquals( root2, dep( result.getRoot(), 1 ) );
383    }
384
385    @Test
386    public void testArtifactDescriptorResolutionNotRestrictedToRepoHostingSelectedVersion()
387            throws Exception
388    {
389        RemoteRepository repo2 = new RemoteRepository.Builder( "test", "default", "file:///" ).build();
390
391        final List<RemoteRepository> repos = new ArrayList<>();
392
393        collector.setArtifactDescriptorReader( new ArtifactDescriptorReader()
394        {
395            public ArtifactDescriptorResult readArtifactDescriptor( RepositorySystemSession session,
396                                                                    ArtifactDescriptorRequest request )
397            {
398                repos.addAll( request.getRepositories() );
399                return new ArtifactDescriptorResult( request );
400            }
401        } );
402
403        List<Dependency> dependencies = singletonList( newDep( "verrange:parent:jar:1[1,)", "compile" ) );
404        CollectRequest request = new CollectRequest( dependencies, null, Arrays.asList( repository, repo2 ) );
405        CollectResult result = collector.collectDependencies( session, request );
406
407        assertEquals( 0, result.getExceptions().size() );
408        assertEquals( 2, repos.size() );
409        assertEquals( "id", repos.get( 0 ).getId() );
410        assertEquals( "test", repos.get( 1 ).getId() );
411    }
412
413    @Test
414    public void testManagedVersionScope()
415            throws DependencyCollectionException
416    {
417        Dependency dependency = newDep( "managed:aid:ext:ver" );
418        CollectRequest request = new CollectRequest( dependency, singletonList( repository ) );
419
420        session.setDependencyManager( new ClassicDependencyManager() );
421
422        CollectResult result = collector.collectDependencies( session, request );
423
424        assertEquals( 0, result.getExceptions().size() );
425
426        DependencyNode root = result.getRoot();
427
428        assertEquals( dependency, dep( root ) );
429        assertEquals( dependency.getArtifact(), dep( root ).getArtifact() );
430
431        assertEquals( 1, root.getChildren().size() );
432        Dependency expect = newDep( "gid:aid:ext:ver", "compile" );
433        assertEquals( expect, dep( root, 0 ) );
434
435        assertEquals( 1, path( root, 0 ).getChildren().size() );
436        expect = newDep( "gid:aid2:ext:managedVersion", "managedScope" );
437        assertEquals( expect, dep( root, 0, 0 ) );
438    }
439
440    @Test
441    public void testDependencyManagement()
442            throws IOException, DependencyCollectionException
443    {
444        collector.setArtifactDescriptorReader( newReader( "managed/" ) );
445
446        DependencyNode root = parser.parseResource( "expectedSubtreeComparisonResult.txt" );
447        TestDependencyManager depMgmt = new TestDependencyManager();
448        depMgmt.add( dep( root, 0 ), "managed", null, null );
449        depMgmt.add( dep( root, 0, 1 ), "managed", "managed", null );
450        depMgmt.add( dep( root, 1 ), null, null, "managed" );
451        session.setDependencyManager( depMgmt );
452
453        // collect result will differ from expectedSubtreeComparisonResult.txt
454        // set localPath -> no dependency traversal
455        CollectRequest request = new CollectRequest( dep( root ), singletonList( repository ) );
456        CollectResult result = collector.collectDependencies( session, request );
457
458        DependencyNode node = result.getRoot();
459        assertEquals( "managed", dep( node, 0, 1 ).getArtifact().getVersion() );
460        assertEquals( "managed", dep( node, 0, 1 ).getScope() );
461
462        assertEquals( "managed", dep( node, 1 ).getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) );
463        assertEquals( "managed", dep( node, 0, 0 ).getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) );
464    }
465
466    @Test
467    public void testDependencyManagement_VerboseMode()
468            throws Exception
469    {
470        String depId = "gid:aid2:ext";
471        TestDependencyManager depMgmt = new TestDependencyManager();
472        depMgmt.version( depId, "managedVersion" );
473        depMgmt.scope( depId, "managedScope" );
474        depMgmt.optional( depId, Boolean.TRUE );
475        depMgmt.path( depId, "managedPath" );
476        depMgmt.exclusions( depId, new Exclusion( "gid", "aid", "*", "*" ) );
477        session.setDependencyManager( depMgmt );
478        session.setConfigProperty( DependencyManagerUtils.CONFIG_PROP_VERBOSE, Boolean.TRUE );
479
480        CollectRequest request = new CollectRequest().setRoot( newDep( "gid:aid:ver" ) );
481        CollectResult result = collector.collectDependencies( session, request );
482        DependencyNode node = result.getRoot().getChildren().get( 0 );
483        assertEquals( DependencyNode.MANAGED_VERSION | DependencyNode.MANAGED_SCOPE | DependencyNode.MANAGED_OPTIONAL
484                | DependencyNode.MANAGED_PROPERTIES | DependencyNode.MANAGED_EXCLUSIONS, node.getManagedBits() );
485        assertEquals( "ver", DependencyManagerUtils.getPremanagedVersion( node ) );
486        assertEquals( "compile", DependencyManagerUtils.getPremanagedScope( node ) );
487        assertEquals( Boolean.FALSE, DependencyManagerUtils.getPremanagedOptional( node ) );
488    }
489
490    @Test
491    public void testDependencyManagement_TransitiveDependencyManager()
492            throws DependencyCollectionException, IOException
493    {
494        collector.setArtifactDescriptorReader( newReader( "managed/" ) );
495        parser = new DependencyGraphParser( "artifact-descriptions/managed/" );
496        session.setDependencyManager( new TransitiveDependencyManager() );
497        final Dependency root = newDep( "gid:root:ext:ver", "compile" );
498        CollectRequest request = new CollectRequest( root, singletonList( repository ) );
499        request.addManagedDependency( newDep( "gid:root:ext:must-retain-core-management" ) );
500        CollectResult result = collector.collectDependencies( session, request );
501
502        final DependencyNode expectedTree = parser.parseResource( "management-tree.txt" );
503        assertEqualSubtree( expectedTree, result.getRoot() );
504
505        // Same test for root artifact (POM) request.
506        final CollectRequest rootArtifactRequest = new CollectRequest();
507        rootArtifactRequest.setRepositories( singletonList( repository ) );
508        rootArtifactRequest.setRootArtifact( new DefaultArtifact( "gid:root:ext:ver" ) );
509        rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "compile" ) );
510        rootArtifactRequest.addManagedDependency( newDep( "gid:root:ext:must-retain-core-management" ) );
511        rootArtifactRequest.addManagedDependency( newDep( "gid:direct:ext:must-retain-core-management" ) );
512        rootArtifactRequest.addManagedDependency( newDep( "gid:transitive-1:ext:managed-by-root" ) );
513        session.setDependencyManager( new TransitiveDependencyManager() );
514        result = collector.collectDependencies( session, rootArtifactRequest );
515        assertEqualSubtree( expectedTree, toDependencyResult( result.getRoot(), "compile", null ) );
516    }
517
518    @Test
519    public void testDependencyManagement_DefaultDependencyManager()
520            throws DependencyCollectionException, IOException
521    {
522        collector.setArtifactDescriptorReader( newReader( "managed/" ) );
523        parser = new DependencyGraphParser( "artifact-descriptions/managed/" );
524        session.setDependencyManager( new DefaultDependencyManager() );
525        final Dependency root = newDep( "gid:root:ext:ver", "compile" );
526        CollectRequest request = new CollectRequest( root, singletonList( repository ) );
527        request.addManagedDependency( newDep( "gid:root:ext:must-not-manage-root" ) );
528        request.addManagedDependency( newDep( "gid:direct:ext:managed-by-dominant-request" ) );
529        CollectResult result = collector.collectDependencies( session, request );
530
531        final DependencyNode expectedTree = parser.parseResource( "default-management-tree.txt" );
532        assertEqualSubtree( expectedTree, result.getRoot() );
533
534        // Same test for root artifact (POM) request.
535        final CollectRequest rootArtifactRequest = new CollectRequest();
536        rootArtifactRequest.setRepositories( singletonList( repository ) );
537        rootArtifactRequest.setRootArtifact( new DefaultArtifact( "gid:root:ext:ver" ) );
538        rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "compile" ) );
539        rootArtifactRequest.addManagedDependency( newDep( "gid:root:ext:must-not-manage-root" ) );
540        rootArtifactRequest.addManagedDependency( newDep( "gid:direct:ext:managed-by-dominant-request" ) );
541        rootArtifactRequest.addManagedDependency( newDep( "gid:transitive-1:ext:managed-by-root" ) );
542        session.setDependencyManager( new DefaultDependencyManager() );
543        result = collector.collectDependencies( session, rootArtifactRequest );
544        assertEqualSubtree( expectedTree, toDependencyResult( result.getRoot(), "compile", null ) );
545    }
546
547    private DependencyNode toDependencyResult( final DependencyNode root, final String rootScope,
548                                               final Boolean optional )
549    {
550        // Make the root artifact resultion result a dependency resolution result for the subtree check.
551        assertNull( "Expected root artifact resolution result.", root.getDependency() );
552        final DefaultDependencyNode defaultNode =
553                new DefaultDependencyNode( new Dependency( root.getArtifact(), rootScope ) );
554
555        defaultNode.setChildren( root.getChildren() );
556
557        if ( optional != null )
558        {
559            defaultNode.setOptional( optional );
560        }
561
562        return defaultNode;
563    }
564
565    @Test
566    public void testVersionFilter()
567            throws Exception
568    {
569        session.setVersionFilter( new HighestVersionFilter() );
570        CollectRequest request = new CollectRequest().setRoot( newDep( "gid:aid:1" ) );
571        CollectResult result = collector.collectDependencies( session, request );
572        assertEquals( 1, result.getRoot().getChildren().size() );
573    }
574
575
576    @Test
577    public void testDescriptorDependenciesEmpty()
578            throws Exception
579    {
580        collector.setArtifactDescriptorReader( newReader( "dependencies-empty/" ) );
581
582        session.setDependencyGraphTransformer( new ConflictResolver(
583                new NearestVersionSelector(), new JavaScopeSelector(), new SimpleOptionalitySelector(),
584                new JavaScopeDeriver()
585        ) );
586
587
588        DependencyNode root = parser.parseResource( "expectedSubtreeOnDescriptorDependenciesEmptyLeft.txt" );
589        Dependency dependency = root.getDependency();
590        CollectRequest request = new CollectRequest( dependency, singletonList( repository ) );
591        CollectResult result = collector.collectDependencies( session, request );
592        assertEqualSubtree( root, result.getRoot() );
593
594        root = parser.parseResource( "expectedSubtreeOnDescriptorDependenciesEmptyRight.txt" );
595        dependency = root.getDependency();
596        request = new CollectRequest( dependency, singletonList( repository ) );
597        result = collector.collectDependencies( session, request );
598        assertEqualSubtree( root, result.getRoot() );
599    }
600
601    static class TestDependencyManager
602            implements DependencyManager
603    {
604
605        private final Map<String, String> versions = new HashMap<>();
606
607        private final Map<String, String> scopes = new HashMap<>();
608
609        private final Map<String, Boolean> optionals = new HashMap<>();
610
611        private final Map<String, String> paths = new HashMap<>();
612
613        private final Map<String, Collection<Exclusion>> exclusions = new HashMap<>();
614
615        public void add( Dependency d, String version, String scope, String localPath )
616        {
617            String id = toKey( d );
618            version( id, version );
619            scope( id, scope );
620            path( id, localPath );
621        }
622
623        public void version( String id, String version )
624        {
625            versions.put( id, version );
626        }
627
628        public void scope( String id, String scope )
629        {
630            scopes.put( id, scope );
631        }
632
633        public void optional( String id, Boolean optional )
634        {
635            optionals.put( id, optional );
636        }
637
638        public void path( String id, String path )
639        {
640            paths.put( id, path );
641        }
642
643        public void exclusions( String id, Exclusion... exclusions )
644        {
645            this.exclusions.put( id, exclusions != null ? Arrays.asList( exclusions ) : null );
646        }
647
648        @Override
649        public DependencyManagement manageDependency( Dependency dependency )
650        {
651            requireNonNull( dependency, "dependency cannot be null" );
652            String id = toKey( dependency );
653            DependencyManagement mgmt = new DependencyManagement();
654            mgmt.setVersion( versions.get( id ) );
655            mgmt.setScope( scopes.get( id ) );
656            mgmt.setOptional( optionals.get( id ) );
657            String path = paths.get( id );
658            if ( path != null )
659            {
660                mgmt.setProperties( Collections.singletonMap( ArtifactProperties.LOCAL_PATH, path ) );
661            }
662            mgmt.setExclusions( exclusions.get( id ) );
663            return mgmt;
664        }
665
666        private String toKey( Dependency dependency )
667        {
668            return ArtifactIdUtils.toVersionlessId( dependency.getArtifact() );
669        }
670
671        @Override
672        public DependencyManager deriveChildManager( DependencyCollectionContext context )
673        {
674            requireNonNull( context, "context cannot be null" );
675            return this;
676        }
677
678    }
679
680}