View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.util.graph.transformer;
20  
21  import java.util.Locale;
22  
23  import org.eclipse.aether.collection.DependencyGraphTransformer;
24  import org.eclipse.aether.graph.DependencyNode;
25  import org.eclipse.aether.internal.test.util.DependencyGraphParser;
26  import org.junit.jupiter.api.Test;
27  
28  import static org.junit.jupiter.api.Assertions.*;
29  
30  public class JavaScopeSelectorTest extends AbstractDependencyGraphTransformerTest {
31  
32      private enum Scope {
33          TEST,
34          PROVIDED,
35          RUNTIME,
36          COMPILE;
37  
38          @Override
39          public String toString() {
40              return super.name().toLowerCase(Locale.ENGLISH);
41          }
42      }
43  
44      @Override
45      protected DependencyGraphTransformer newTransformer() {
46          return new ConflictResolver(
47                  new NearestVersionSelector(), new JavaScopeSelector(),
48                  new SimpleOptionalitySelector(), new JavaScopeDeriver());
49      }
50  
51      @Override
52      protected DependencyGraphParser newParser() {
53          return new DependencyGraphParser("transformer/scope-calculator/");
54      }
55  
56      private void expectScope(String expected, DependencyNode root, int... coords) {
57          expectScope(null, expected, root, coords);
58      }
59  
60      private void expectScope(String msg, String expected, DependencyNode root, int... coords) {
61          if (msg == null) {
62              msg = "";
63          }
64          try {
65              DependencyNode node = root;
66              node = path(node, coords);
67  
68              assertEquals(expected, node.getDependency().getScope(), msg + "\nculprit: " + node.toString() + "\n");
69          } catch (IndexOutOfBoundsException | NullPointerException e) {
70              throw new IllegalArgumentException("illegal coordinates for child", e);
71          }
72      }
73  
74      private DependencyNode path(DependencyNode node, int... coords) {
75          for (int coord : coords) {
76              node = node.getChildren().get(coord);
77          }
78          return node;
79      }
80  
81      @Test
82      void testScopeInheritanceProvided() throws Exception {
83          String resource = "inheritance.txt";
84  
85          String expected = "test";
86          DependencyNode root = transform(parseResource(resource, "provided", "test"));
87          expectScope(parser.dump(root), expected, root, 0, 0);
88      }
89  
90      @Test
91      void testConflictWinningScopeGetsUsedForInheritance() throws Exception {
92          DependencyNode root = parseResource("conflict-and-inheritance.txt");
93          assertSame(root, transform(root));
94  
95          expectScope("compile", root, 0, 0);
96          expectScope("compile", root, 0, 0, 0);
97      }
98  
99      @Test
100     void testScopeOfDirectDependencyWinsConflictAndGetsUsedForInheritanceToChildrenEverywhereInGraph()
101             throws Exception {
102         DependencyNode root = parseResource("direct-with-conflict-and-inheritance.txt");
103         assertSame(root, transform(root));
104 
105         expectScope("test", root, 0, 0);
106     }
107 
108     @Test
109     void testCycleA() throws Exception {
110         DependencyNode root = parseResource("cycle-a.txt");
111         assertSame(root, transform(root));
112 
113         expectScope("compile", root, 0);
114         expectScope("runtime", root, 1);
115     }
116 
117     @Test
118     void testCycleB() throws Exception {
119         DependencyNode root = parseResource("cycle-b.txt");
120         assertSame(root, transform(root));
121 
122         expectScope("runtime", root, 0);
123         expectScope("compile", root, 1);
124     }
125 
126     @Test
127     void testCycleC() throws Exception {
128         DependencyNode root = parseResource("cycle-c.txt");
129         assertSame(root, transform(root));
130 
131         expectScope("runtime", root, 0);
132         expectScope("runtime", root, 0, 0);
133         expectScope("runtime", root, 1);
134         expectScope("runtime", root, 1, 0);
135     }
136 
137     @Test
138     void testCycleD() throws Exception {
139         DependencyNode root = parseResource("cycle-d.txt");
140         assertSame(root, transform(root));
141 
142         expectScope("compile", root, 0);
143         expectScope("compile", root, 0, 0);
144     }
145 
146     @Test
147     void testDirectNodesAlwaysWin() throws Exception {
148 
149         for (Scope directScope : Scope.values()) {
150             String direct = directScope.toString();
151 
152             DependencyNode root = parseResource("direct-nodes-winning.txt", direct);
153 
154             String msg = String.format(
155                     "direct node should be setting scope ('%s') for all nodes.\n" + parser.dump(root), direct);
156             assertSame(root, transform(root));
157             msg += "\ntransformed:\n" + parser.dump(root);
158 
159             expectScope(msg, direct, root, 0);
160         }
161     }
162 
163     @Test
164     void testNonDirectMultipleInheritance() throws Exception {
165         for (Scope scope1 : Scope.values()) {
166             for (Scope scope2 : Scope.values()) {
167                 DependencyNode root = parseResource("multiple-inheritance.txt", scope1.toString(), scope2.toString());
168 
169                 String expected = scope1.compareTo(scope2) >= 0 ? scope1.toString() : scope2.toString();
170                 String msg = String.format("expected '%s' to win\n" + parser.dump(root), expected);
171 
172                 assertSame(root, transform(root));
173                 msg += "\ntransformed:\n" + parser.dump(root);
174 
175                 expectScope(msg, expected, root, 0, 0);
176             }
177         }
178     }
179 
180     @Test
181     void testConflictScopeOrdering() throws Exception {
182         for (Scope scope1 : Scope.values()) {
183             for (Scope scope2 : Scope.values()) {
184                 DependencyNode root = parseResource("dueling-scopes.txt", scope1.toString(), scope2.toString());
185 
186                 String expected = scope1.compareTo(scope2) >= 0 ? scope1.toString() : scope2.toString();
187                 String msg = String.format("expected '%s' to win\n" + parser.dump(root), expected);
188 
189                 assertSame(root, transform(root));
190                 msg += "\ntransformed:\n" + parser.dump(root);
191 
192                 expectScope(msg, expected, root, 0, 0);
193             }
194         }
195     }
196 
197     /**
198      * obscure case (illegal maven POM).
199      */
200     @Test
201     void testConflictingDirectNodes() throws Exception {
202         for (Scope scope1 : Scope.values()) {
203             for (Scope scope2 : Scope.values()) {
204                 DependencyNode root =
205                         parseResource("conflicting-direct-nodes.txt", scope1.toString(), scope2.toString());
206 
207                 String expected = scope1.toString();
208                 String msg = String.format("expected '%s' to win\n" + parser.dump(root), expected);
209 
210                 assertSame(root, transform(root));
211                 msg += "\ntransformed:\n" + parser.dump(root);
212 
213                 expectScope(msg, expected, root, 0);
214             }
215         }
216     }
217 }