001package org.eclipse.aether.util.graph.transformer;
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 static org.junit.Assert.*;
023
024import java.util.Locale;
025
026import org.eclipse.aether.collection.DependencyGraphTransformer;
027import org.eclipse.aether.graph.DependencyNode;
028import org.eclipse.aether.internal.test.util.DependencyGraphParser;
029import org.junit.Test;
030
031public class JavaScopeSelectorTest
032    extends AbstractDependencyGraphTransformerTest
033{
034
035    private enum Scope
036    {
037        TEST, PROVIDED, RUNTIME, COMPILE;
038
039        @Override
040        public String toString()
041        {
042            return super.name().toLowerCase( Locale.ENGLISH );
043        }
044    }
045
046    @Override
047    protected DependencyGraphTransformer newTransformer()
048    {
049        return new ConflictResolver( new NearestVersionSelector(), new JavaScopeSelector(),
050                                     new SimpleOptionalitySelector(), new JavaScopeDeriver() );
051    }
052
053    @Override
054    protected DependencyGraphParser newParser()
055    {
056        return new DependencyGraphParser( "transformer/scope-calculator/" );
057    }
058
059    private void expectScope( String expected, DependencyNode root, int... coords )
060    {
061        expectScope( null, expected, root, coords );
062    }
063
064    private void expectScope( String msg, String expected, DependencyNode root, int... coords )
065    {
066        if ( msg == null )
067        {
068            msg = "";
069        }
070        try
071        {
072            DependencyNode node = root;
073            node = path( node, coords );
074
075            assertEquals( msg + "\nculprit: " + node.toString() + "\n", expected, node.getDependency().getScope() );
076        }
077        catch ( IndexOutOfBoundsException e )
078        {
079            throw new IllegalArgumentException( "illegal coordinates for child", e );
080        }
081        catch ( NullPointerException e )
082        {
083            throw new IllegalArgumentException( "illegal coordinates for child", e );
084        }
085    }
086
087    private DependencyNode path( DependencyNode node, int... coords )
088    {
089        for ( int coord : coords )
090        {
091            node = node.getChildren().get( coord );
092        }
093        return node;
094    }
095
096    @Test
097    public void testScopeInheritanceProvided()
098        throws Exception
099    {
100        String resource = "inheritance.txt";
101
102        String expected = "test";
103        DependencyNode root = transform( parseResource( resource, "provided", "test" ) );
104        expectScope( parser.dump( root ), expected, root, 0, 0 );
105    }
106
107    @Test
108    public void testConflictWinningScopeGetsUsedForInheritance()
109        throws Exception
110    {
111        DependencyNode root = parseResource( "conflict-and-inheritance.txt" );
112        assertSame( root, transform( root ) );
113
114        expectScope( "compile", root, 0, 0 );
115        expectScope( "compile", root, 0, 0, 0 );
116    }
117
118    @Test
119    public void testScopeOfDirectDependencyWinsConflictAndGetsUsedForInheritanceToChildrenEverywhereInGraph()
120        throws Exception
121    {
122        DependencyNode root = parseResource( "direct-with-conflict-and-inheritance.txt" );
123        assertSame( root, transform( root ) );
124
125        expectScope( "test", root, 0, 0 );
126    }
127
128    @Test
129    public void testCycleA()
130        throws Exception
131    {
132        DependencyNode root = parseResource( "cycle-a.txt" );
133        assertSame( root, transform( root ) );
134
135        expectScope( "compile", root, 0 );
136        expectScope( "runtime", root, 1 );
137    }
138
139    @Test
140    public void testCycleB()
141        throws Exception
142    {
143        DependencyNode root = parseResource( "cycle-b.txt" );
144        assertSame( root, transform( root ) );
145
146        expectScope( "runtime", root, 0 );
147        expectScope( "compile", root, 1 );
148    }
149
150    @Test
151    public void testCycleC()
152        throws Exception
153    {
154        DependencyNode root = parseResource( "cycle-c.txt" );
155        assertSame( root, transform( root ) );
156
157        expectScope( "runtime", root, 0 );
158        expectScope( "runtime", root, 0, 0 );
159        expectScope( "runtime", root, 1 );
160        expectScope( "runtime", root, 1, 0 );
161    }
162
163    @Test
164    public void testCycleD()
165        throws Exception
166    {
167        DependencyNode root = parseResource( "cycle-d.txt" );
168        assertSame( root, transform( root ) );
169
170        expectScope( "compile", root, 0 );
171        expectScope( "compile", root, 0, 0 );
172    }
173
174    @Test
175    public void testDirectNodesAlwaysWin()
176        throws Exception
177    {
178
179        for ( Scope directScope : Scope.values() )
180        {
181            String direct = directScope.toString();
182
183            DependencyNode root = parseResource( "direct-nodes-winning.txt", direct );
184
185            String msg =
186                String.format( "direct node should be setting scope ('%s') for all nodes.\n" + parser.dump( root ),
187                               direct );
188            assertSame( root, transform( root ) );
189            msg += "\ntransformed:\n" + parser.dump( root );
190
191            expectScope( msg, direct, root, 0 );
192        }
193    }
194
195    @Test
196    public void testNonDirectMultipleInheritance()
197        throws Exception
198    {
199        for ( Scope scope1 : Scope.values() )
200        {
201            for ( Scope scope2 : Scope.values() )
202            {
203                DependencyNode root = parseResource( "multiple-inheritance.txt", scope1.toString(), scope2.toString() );
204
205                String expected = scope1.compareTo( scope2 ) >= 0 ? scope1.toString() : scope2.toString();
206                String msg = String.format( "expected '%s' to win\n" + parser.dump( root ), expected );
207
208                assertSame( root, transform( root ) );
209                msg += "\ntransformed:\n" + parser.dump( root );
210
211                expectScope( msg, expected, root, 0, 0 );
212            }
213        }
214    }
215
216    @Test
217    public void testConflictScopeOrdering()
218        throws Exception
219    {
220        for ( Scope scope1 : Scope.values() )
221        {
222            for ( Scope scope2 : Scope.values() )
223            {
224                DependencyNode root = parseResource( "dueling-scopes.txt", scope1.toString(), scope2.toString() );
225
226                String expected = scope1.compareTo( scope2 ) >= 0 ? scope1.toString() : scope2.toString();
227                String msg = String.format( "expected '%s' to win\n" + parser.dump( root ), expected );
228
229                assertSame( root, transform( root ) );
230                msg += "\ntransformed:\n" + parser.dump( root );
231
232                expectScope( msg, expected, root, 0, 0 );
233            }
234        }
235    }
236
237    /**
238     * obscure case (illegal maven POM).
239     */
240    @Test
241    public void testConflictingDirectNodes()
242        throws Exception
243    {
244        for ( Scope scope1 : Scope.values() )
245        {
246            for ( Scope scope2 : Scope.values() )
247            {
248                DependencyNode root = parseResource( "conflicting-direct-nodes.txt", scope1.toString(), scope2.toString() );
249
250                String expected = scope1.toString();
251                String msg = String.format( "expected '%s' to win\n" + parser.dump( root ), expected );
252
253                assertSame( root, transform( root ) );
254                msg += "\ntransformed:\n" + parser.dump( root );
255
256                expectScope( msg, expected, root, 0 );
257            }
258        }
259    }
260
261}