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