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.List;
22  
23  import org.eclipse.aether.collection.UnsolvableVersionConflictException;
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  /**
31   */
32  public class NearestVersionSelectorTest extends AbstractDependencyGraphTransformerTest {
33  
34      @Override
35      protected ConflictResolver newTransformer() {
36          return new ConflictResolver(
37                  new NearestVersionSelector(), new JavaScopeSelector(),
38                  new SimpleOptionalitySelector(), new JavaScopeDeriver());
39      }
40  
41      @Override
42      protected DependencyGraphParser newParser() {
43          return new DependencyGraphParser("transformer/version-resolver/");
44      }
45  
46      @Test
47      void testSelectHighestVersionFromMultipleVersionsAtSameLevel() throws Exception {
48          DependencyNode root = parseResource("sibling-versions.txt");
49          assertSame(root, transform(root));
50  
51          assertEquals(1, root.getChildren().size());
52          assertEquals("3", root.getChildren().get(0).getArtifact().getVersion());
53      }
54  
55      @Test
56      void testSelectedVersionAtDeeperLevelThanOriginallySeen() throws Exception {
57          DependencyNode root = parseResource("nearest-underneath-loser-a.txt");
58  
59          assertSame(root, transform(root));
60  
61          List<DependencyNode> trail = find(root, "j");
62          assertEquals(5, trail.size());
63      }
64  
65      @Test
66      void testNearestDirtyVersionUnderneathRemovedNode() throws Exception {
67          DependencyNode root = parseResource("nearest-underneath-loser-b.txt");
68  
69          assertSame(root, transform(root));
70  
71          List<DependencyNode> trail = find(root, "j");
72          assertEquals(5, trail.size());
73      }
74  
75      @Test
76      void testViolationOfHardConstraintFallsBackToNearestSeenNotFirstSeen() throws Exception {
77          DependencyNode root = parseResource("range-backtracking.txt");
78  
79          assertSame(root, transform(root));
80  
81          List<DependencyNode> trail = find(root, "x");
82          assertEquals(3, trail.size());
83          assertEquals("2", trail.get(0).getArtifact().getVersion());
84      }
85  
86      @Test
87      void testCyclicConflictIdGraph() throws Exception {
88          DependencyNode root = parseResource("conflict-id-cycle.txt");
89  
90          assertSame(root, transform(root));
91  
92          assertEquals(2, root.getChildren().size());
93          assertEquals("a", root.getChildren().get(0).getArtifact().getArtifactId());
94          assertEquals("b", root.getChildren().get(1).getArtifact().getArtifactId());
95          assertTrue(root.getChildren().get(0).getChildren().isEmpty());
96          assertTrue(root.getChildren().get(1).getChildren().isEmpty());
97      }
98  
99      @Test
100     void testUnsolvableRangeConflictBetweenHardConstraints() {
101         assertThrows(UnsolvableVersionConflictException.class, () -> {
102             DependencyNode root = parseResource("unsolvable.txt");
103             transform(root);
104         });
105     }
106 
107     @Test
108     void testUnsolvableRangeConflictWithUnrelatedCycle() throws Exception {
109         assertThrows(UnsolvableVersionConflictException.class, () -> {
110             DependencyNode root = parseResource("unsolvable-with-cycle.txt");
111             assertSame(root, transform(root));
112         });
113     }
114 
115     @Test
116     void testSolvableConflictBetweenHardConstraints() throws Exception {
117         DependencyNode root = parseResource("ranges.txt");
118 
119         assertSame(root, transform(root));
120     }
121 
122     @Test
123     void testConflictGroupCompletelyDroppedFromResolvedTree() throws Exception {
124         DependencyNode root = parseResource("dead-conflict-group.txt");
125 
126         assertSame(root, transform(root));
127 
128         assertEquals(2, root.getChildren().size());
129         assertEquals("a", root.getChildren().get(0).getArtifact().getArtifactId());
130         assertEquals("b", root.getChildren().get(1).getArtifact().getArtifactId());
131         assertTrue(root.getChildren().get(0).getChildren().isEmpty());
132         assertTrue(root.getChildren().get(1).getChildren().isEmpty());
133     }
134 
135     @Test
136     void testNearestSoftVersionPrunedByFartherRange() throws Exception {
137         DependencyNode root = parseResource("soft-vs-range.txt");
138 
139         assertSame(root, transform(root));
140 
141         assertEquals(2, root.getChildren().size());
142         assertEquals("a", root.getChildren().get(0).getArtifact().getArtifactId());
143         assertEquals(0, root.getChildren().get(0).getChildren().size());
144         assertEquals("b", root.getChildren().get(1).getArtifact().getArtifactId());
145         assertEquals(1, root.getChildren().get(1).getChildren().size());
146     }
147 
148     @Test
149     void testCyclicGraph() throws Exception {
150         DependencyNode root = parseResource("cycle.txt");
151 
152         assertSame(root, transform(root));
153 
154         assertEquals(2, root.getChildren().size());
155         assertEquals(1, root.getChildren().get(0).getChildren().size());
156         assertEquals(
157                 0, root.getChildren().get(0).getChildren().get(0).getChildren().size());
158         assertEquals(0, root.getChildren().get(1).getChildren().size());
159     }
160 
161     @Test
162     void testLoop() throws Exception {
163         DependencyNode root = parseResource("loop.txt");
164 
165         assertSame(root, transform(root));
166 
167         assertEquals(0, root.getChildren().size());
168     }
169 
170     @Test
171     void testOverlappingCycles() throws Exception {
172         DependencyNode root = parseResource("overlapping-cycles.txt");
173 
174         assertSame(root, transform(root));
175 
176         assertEquals(2, root.getChildren().size());
177     }
178 
179     @Test
180     void testScopeDerivationAndConflictResolutionCantHappenForAllNodesBeforeVersionSelection() throws Exception {
181         DependencyNode root = parseResource("scope-vs-version.txt");
182 
183         assertSame(root, transform(root));
184 
185         DependencyNode[] nodes = find(root, "y").toArray(new DependencyNode[0]);
186         assertEquals(3, nodes.length);
187         assertEquals("test", nodes[1].getDependency().getScope());
188         assertEquals("test", nodes[0].getDependency().getScope());
189     }
190 
191     @Test
192     void testVerboseMode() throws Exception {
193         DependencyNode root = parseResource("verbose.txt");
194 
195         session.setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, Boolean.TRUE);
196         assertSame(root, transform(root));
197 
198         assertEquals(2, root.getChildren().size());
199         assertEquals(1, root.getChildren().get(0).getChildren().size());
200         DependencyNode winner = root.getChildren().get(0).getChildren().get(0);
201         assertEquals("test", winner.getDependency().getScope());
202         assertEquals("compile", winner.getData().get(ConflictResolver.NODE_DATA_ORIGINAL_SCOPE));
203         assertEquals(false, winner.getData().get(ConflictResolver.NODE_DATA_ORIGINAL_OPTIONALITY));
204         assertEquals(1, root.getChildren().get(1).getChildren().size());
205         DependencyNode loser = root.getChildren().get(1).getChildren().get(0);
206         assertEquals("test", loser.getDependency().getScope());
207         assertEquals(0, loser.getChildren().size());
208         assertSame(winner, loser.getData().get(ConflictResolver.NODE_DATA_WINNER));
209         assertEquals("compile", loser.getData().get(ConflictResolver.NODE_DATA_ORIGINAL_SCOPE));
210         assertEquals(false, loser.getData().get(ConflictResolver.NODE_DATA_ORIGINAL_OPTIONALITY));
211     }
212 }