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 | NullPointerException e )
078        {
079            throw new IllegalArgumentException( "illegal coordinates for child", e );
080        }
081    }
082
083    private DependencyNode path( DependencyNode node, int... coords )
084    {
085        for ( int coord : coords )
086        {
087            node = node.getChildren().get( coord );
088        }
089        return node;
090    }
091
092    @Test
093    public void testScopeInheritanceProvided()
094        throws Exception
095    {
096        String resource = "inheritance.txt";
097
098        String expected = "test";
099        DependencyNode root = transform( parseResource( resource, "provided", "test" ) );
100        expectScope( parser.dump( root ), expected, root, 0, 0 );
101    }
102
103    @Test
104    public void testConflictWinningScopeGetsUsedForInheritance()
105        throws Exception
106    {
107        DependencyNode root = parseResource( "conflict-and-inheritance.txt" );
108        assertSame( root, transform( root ) );
109
110        expectScope( "compile", root, 0, 0 );
111        expectScope( "compile", root, 0, 0, 0 );
112    }
113
114    @Test
115    public void testScopeOfDirectDependencyWinsConflictAndGetsUsedForInheritanceToChildrenEverywhereInGraph()
116        throws Exception
117    {
118        DependencyNode root = parseResource( "direct-with-conflict-and-inheritance.txt" );
119        assertSame( root, transform( root ) );
120
121        expectScope( "test", root, 0, 0 );
122    }
123
124    @Test
125    public void testCycleA()
126        throws Exception
127    {
128        DependencyNode root = parseResource( "cycle-a.txt" );
129        assertSame( root, transform( root ) );
130
131        expectScope( "compile", root, 0 );
132        expectScope( "runtime", root, 1 );
133    }
134
135    @Test
136    public void testCycleB()
137        throws Exception
138    {
139        DependencyNode root = parseResource( "cycle-b.txt" );
140        assertSame( root, transform( root ) );
141
142        expectScope( "runtime", root, 0 );
143        expectScope( "compile", root, 1 );
144    }
145
146    @Test
147    public void testCycleC()
148        throws Exception
149    {
150        DependencyNode root = parseResource( "cycle-c.txt" );
151        assertSame( root, transform( root ) );
152
153        expectScope( "runtime", root, 0 );
154        expectScope( "runtime", root, 0, 0 );
155        expectScope( "runtime", root, 1 );
156        expectScope( "runtime", root, 1, 0 );
157    }
158
159    @Test
160    public void testCycleD()
161        throws Exception
162    {
163        DependencyNode root = parseResource( "cycle-d.txt" );
164        assertSame( root, transform( root ) );
165
166        expectScope( "compile", root, 0 );
167        expectScope( "compile", root, 0, 0 );
168    }
169
170    @Test
171    public void testDirectNodesAlwaysWin()
172        throws Exception
173    {
174
175        for ( Scope directScope : Scope.values() )
176        {
177            String direct = directScope.toString();
178
179            DependencyNode root = parseResource( "direct-nodes-winning.txt", direct );
180
181            String msg =
182                String.format( "direct node should be setting scope ('%s') for all nodes.\n" + parser.dump( root ),
183                               direct );
184            assertSame( root, transform( root ) );
185            msg += "\ntransformed:\n" + parser.dump( root );
186
187            expectScope( msg, direct, root, 0 );
188        }
189    }
190
191    @Test
192    public void testNonDirectMultipleInheritance()
193        throws Exception
194    {
195        for ( Scope scope1 : Scope.values() )
196        {
197            for ( Scope scope2 : Scope.values() )
198            {
199                DependencyNode root = parseResource( "multiple-inheritance.txt", scope1.toString(), scope2.toString() );
200
201                String expected = scope1.compareTo( scope2 ) >= 0 ? scope1.toString() : scope2.toString();
202                String msg = String.format( "expected '%s' to win\n" + parser.dump( root ), expected );
203
204                assertSame( root, transform( root ) );
205                msg += "\ntransformed:\n" + parser.dump( root );
206
207                expectScope( msg, expected, root, 0, 0 );
208            }
209        }
210    }
211
212    @Test
213    public void testConflictScopeOrdering()
214        throws Exception
215    {
216        for ( Scope scope1 : Scope.values() )
217        {
218            for ( Scope scope2 : Scope.values() )
219            {
220                DependencyNode root = parseResource( "dueling-scopes.txt", scope1.toString(), scope2.toString() );
221
222                String expected = scope1.compareTo( scope2 ) >= 0 ? scope1.toString() : scope2.toString();
223                String msg = String.format( "expected '%s' to win\n" + parser.dump( root ), expected );
224
225                assertSame( root, transform( root ) );
226                msg += "\ntransformed:\n" + parser.dump( root );
227
228                expectScope( msg, expected, root, 0, 0 );
229            }
230        }
231    }
232
233    /**
234     * obscure case (illegal maven POM).
235     */
236    @Test
237    public void testConflictingDirectNodes()
238        throws Exception
239    {
240        for ( Scope scope1 : Scope.values() )
241        {
242            for ( Scope scope2 : Scope.values() )
243            {
244                DependencyNode root = parseResource( "conflicting-direct-nodes.txt", scope1.toString(), scope2.toString() );
245
246                String expected = scope1.toString();
247                String msg = String.format( "expected '%s' to win\n" + parser.dump( root ), expected );
248
249                assertSame( root, transform( root ) );
250                msg += "\ntransformed:\n" + parser.dump( root );
251
252                expectScope( msg, expected, root, 0 );
253            }
254        }
255    }
256
257}