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.ArrayList;
22 import java.util.Arrays;
23 import java.util.List;
24
25 import org.eclipse.aether.DefaultRepositorySystemSession;
26 import org.eclipse.aether.RepositoryException;
27 import org.eclipse.aether.artifact.DefaultArtifact;
28 import org.eclipse.aether.graph.DefaultDependencyNode;
29 import org.eclipse.aether.graph.Dependency;
30 import org.eclipse.aether.graph.DependencyNode;
31 import org.eclipse.aether.internal.test.util.TestUtils;
32 import org.eclipse.aether.internal.test.util.TestVersion;
33 import org.eclipse.aether.internal.test.util.TestVersionConstraint;
34 import org.eclipse.aether.util.graph.visitor.DependencyGraphDumper;
35 import org.junit.jupiter.api.Test;
36
37 import static org.junit.jupiter.api.Assertions.*;
38
39 public class ConflictResolverTest {
40 @Test
41 void noTransformationRequired() throws RepositoryException {
42 ConflictResolver resolver = makeDefaultResolver();
43
44
45 DependencyNode fooNode = makeDependencyNode("group-id", "foo", "1.0");
46 DependencyNode barNode = makeDependencyNode("group-id", "bar", "1.0");
47 fooNode.setChildren(mutableList(barNode));
48
49 DependencyNode transformedNode =
50 resolver.transformGraph(fooNode, TestUtils.newTransformationContext(TestUtils.newSession()));
51
52 assertSame(fooNode, transformedNode);
53 assertEquals(1, transformedNode.getChildren().size());
54 assertSame(barNode, transformedNode.getChildren().get(0));
55 }
56
57 @Test
58 void versionClash() throws RepositoryException {
59 ConflictResolver resolver = makeDefaultResolver();
60
61
62
63 DependencyNode fooNode = makeDependencyNode("some-group", "foo", "1.0");
64 DependencyNode barNode = makeDependencyNode("some-group", "bar", "1.0");
65 DependencyNode baz1Node = makeDependencyNode("some-group", "baz", "1.0");
66 DependencyNode baz2Node = makeDependencyNode("some-group", "baz", "2.0");
67 fooNode.setChildren(mutableList(barNode, baz1Node));
68 barNode.setChildren(mutableList(baz2Node));
69
70 DependencyNode transformedNode =
71 resolver.transformGraph(fooNode, TestUtils.newTransformationContext(TestUtils.newSession()));
72
73 assertSame(fooNode, transformedNode);
74 assertEquals(2, fooNode.getChildren().size());
75 assertSame(barNode, fooNode.getChildren().get(0));
76 assertTrue(barNode.getChildren().isEmpty());
77 assertSame(baz1Node, fooNode.getChildren().get(1));
78 }
79
80 @Test
81 void versionClashForkedStandardVerbose() throws RepositoryException {
82
83
84
85 DependencyNode root = makeDependencyNode("some-group", "root", "1.0");
86 DependencyNode impl1 = makeDependencyNode("some-group", "impl1", "1.0");
87 DependencyNode impl2 = makeDependencyNode("some-group", "impl2", "1.0");
88 DependencyNode api1 = makeDependencyNode("some-group", "api", "1.1");
89 DependencyNode api2 = makeDependencyNode("some-group", "api", "1.0");
90
91 root.setChildren(mutableList(impl1, impl2));
92 impl1.setChildren(mutableList(api1));
93 impl2.setChildren(mutableList(api2));
94
95 DependencyNode transformedNode = versionRangeClash(root, ConflictResolver.Verbosity.STANDARD);
96
97 assertSame(root, transformedNode);
98 assertEquals(2, root.getChildren().size());
99 assertSame(impl1, root.getChildren().get(0));
100 assertSame(impl2, root.getChildren().get(1));
101 assertEquals(1, impl1.getChildren().size());
102 assertSame(api1, impl1.getChildren().get(0));
103 assertEquals(1, impl2.getChildren().size());
104 assertConflictedButSameAsOriginal(api2, impl2.getChildren().get(0));
105 }
106
107 @Test
108 void versionRangeClashAscOrder() throws RepositoryException {
109
110
111 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
112 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
113 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
114 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
115 a.setChildren(mutableList(b, c1, c2));
116 b.setChildren(mutableList(c1, c2));
117
118 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.NONE);
119
120 assertSame(a, ta);
121 assertEquals(2, a.getChildren().size());
122 assertSame(b, a.getChildren().get(0));
123 assertSame(c2, a.getChildren().get(1));
124 assertEquals(0, b.getChildren().size());
125 }
126
127 @Test
128 void versionRangeClashAscOrderStandardVerbose() throws RepositoryException {
129
130
131 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
132 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
133 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
134 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
135 a.setChildren(mutableList(b, c1, c2));
136 b.setChildren(mutableList(c1, c2));
137
138 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.STANDARD);
139
140 assertSame(a, ta);
141 assertEquals(2, a.getChildren().size());
142 assertSame(b, a.getChildren().get(0));
143 assertSame(c2, a.getChildren().get(1));
144 assertEquals(1, b.getChildren().size());
145 assertConflictedButSameAsOriginal(c2, b.getChildren().get(0));
146 }
147
148 @Test
149 void versionRangeClashAscOrderFullVerbose() throws RepositoryException {
150
151
152 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
153 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
154 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
155 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
156 a.setChildren(mutableList(b, c1, c2));
157 b.setChildren(mutableList(c1, c2));
158
159 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.FULL);
160
161 assertSame(a, ta);
162 assertEquals(3, a.getChildren().size());
163 assertSame(b, a.getChildren().get(0));
164 assertConflictedButSameAsOriginal(c1, a.getChildren().get(1));
165 assertSame(c2, a.getChildren().get(2));
166 assertEquals(2, b.getChildren().size());
167 assertConflictedButSameAsOriginal(c1, b.getChildren().get(0));
168 assertConflictedButSameAsOriginal(c2, b.getChildren().get(1));
169 }
170
171 @Test
172 void versionRangeClashDescOrder() throws RepositoryException {
173
174
175 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
176 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
177 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
178 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
179 a.setChildren(mutableList(b, c2, c1));
180 b.setChildren(mutableList(c2, c1));
181
182 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.NONE);
183
184 assertSame(a, ta);
185 assertEquals(2, a.getChildren().size());
186 assertSame(b, a.getChildren().get(0));
187 assertSame(c2, a.getChildren().get(1));
188 assertEquals(0, b.getChildren().size());
189 }
190
191 @Test
192 void versionRangeClashDescOrderStandardVerbose() throws RepositoryException {
193
194
195 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
196 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
197 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
198 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
199 a.setChildren(mutableList(b, c2, c1));
200 b.setChildren(mutableList(c2, c1));
201
202 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.STANDARD);
203
204 assertSame(a, ta);
205 assertEquals(2, a.getChildren().size());
206 assertSame(b, a.getChildren().get(0));
207 assertSame(c2, a.getChildren().get(1));
208 assertEquals(1, b.getChildren().size());
209 assertConflictedButSameAsOriginal(c2, b.getChildren().get(0));
210 }
211
212 @Test
213 void versionRangeClashDescOrderFullVerbose() throws RepositoryException {
214
215
216 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
217 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
218 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
219 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
220 a.setChildren(mutableList(b, c2, c1));
221 b.setChildren(mutableList(c2, c1));
222
223 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.FULL);
224
225 assertSame(a, ta);
226 assertEquals(3, a.getChildren().size());
227 assertSame(b, a.getChildren().get(0));
228 assertSame(c2, a.getChildren().get(1));
229 assertConflictedButSameAsOriginal(c1, a.getChildren().get(2));
230 assertEquals(2, b.getChildren().size());
231 assertConflictedButSameAsOriginal(c2, b.getChildren().get(0));
232 assertConflictedButSameAsOriginal(c1, b.getChildren().get(1));
233 }
234
235 @Test
236 void versionRangeClashMixedOrder() throws RepositoryException {
237
238
239 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
240 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
241 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
242 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
243 a.setChildren(mutableList(b, c2, c1));
244 b.setChildren(mutableList(c1, c2));
245
246 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.NONE);
247
248 assertSame(a, ta);
249 assertEquals(2, a.getChildren().size());
250 assertSame(b, a.getChildren().get(0));
251 assertSame(c2, a.getChildren().get(1));
252 assertEquals(0, b.getChildren().size());
253 }
254
255 @Test
256 void versionRangeClashMixedOrderStandardVerbose() throws RepositoryException {
257
258
259 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
260 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
261 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
262 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
263 a.setChildren(mutableList(b, c2, c1));
264 b.setChildren(mutableList(c1, c2));
265
266 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.STANDARD);
267
268 assertSame(a, ta);
269 assertEquals(2, a.getChildren().size());
270 assertSame(b, a.getChildren().get(0));
271 assertSame(c2, a.getChildren().get(1));
272 assertEquals(1, b.getChildren().size());
273 assertConflictedButSameAsOriginal(c2, b.getChildren().get(0));
274 }
275
276 @Test
277 void versionRangeClashMixedOrderStandardVerboseLeavesOne() throws RepositoryException {
278
279
280
281
282
283
284
285 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
286 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
287 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
288 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
289 DependencyNode d1 = makeDependencyNode("some-group", "d", "1.0");
290 DependencyNode d2 = makeDependencyNode("some-group", "d", "2.0");
291 a.setChildren(mutableList(b, c2, c1, d2));
292 b.setChildren(mutableList(c1, c2, d1));
293
294 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.STANDARD);
295
296 assertSame(a, ta);
297 assertEquals(3, a.getChildren().size());
298 assertSame(b, a.getChildren().get(0));
299 assertSame(c2, a.getChildren().get(1));
300 assertSame(d2, a.getChildren().get(2));
301 assertEquals(2, b.getChildren().size());
302 assertConflictedButSameAsOriginal(c2, b.getChildren().get(0));
303 assertConflictedButSameAsOriginal(d1, b.getChildren().get(1));
304 }
305
306 @Test
307 void versionRangeClashMixedOrderFullVerbose() throws RepositoryException {
308
309
310 DependencyNode a = makeDependencyNode("some-group", "a", "1.0");
311 DependencyNode b = makeDependencyNode("some-group", "b", "1.0");
312 DependencyNode c1 = makeDependencyNode("some-group", "c", "1.0");
313 DependencyNode c2 = makeDependencyNode("some-group", "c", "2.0");
314 a.setChildren(mutableList(b, c2, c1));
315 b.setChildren(mutableList(c1, c2));
316
317 DependencyNode ta = versionRangeClash(a, ConflictResolver.Verbosity.FULL);
318
319 assertSame(a, ta);
320 assertEquals(3, a.getChildren().size());
321 assertSame(b, a.getChildren().get(0));
322 assertSame(c2, a.getChildren().get(1));
323 assertConflictedButSameAsOriginal(c1, a.getChildren().get(2));
324 assertEquals(2, b.getChildren().size());
325 assertConflictedButSameAsOriginal(c1, b.getChildren().get(0));
326 assertConflictedButSameAsOriginal(c2, b.getChildren().get(1));
327 }
328
329
330
331
332
333
334 private void assertConflictedButSameAsOriginal(DependencyNode original, DependencyNode current) {
335 assertNotSame(original, current);
336 assertEquals(
337 original.getDependency().getArtifact(), current.getDependency().getArtifact());
338 assertEquals(
339 original.getDependency().getScope(), current.getDependency().getScope());
340 assertEquals(
341 original.getDependency().getOptional(), current.getDependency().getOptional());
342 assertNull(original.getData().get(ConflictResolver.NODE_DATA_WINNER));
343 assertNotNull(current.getData().get(ConflictResolver.NODE_DATA_WINNER));
344 }
345
346 private static final DependencyGraphDumper DUMPER_SOUT = new DependencyGraphDumper(System.out::println);
347
348
349
350
351 private DependencyNode versionRangeClash(DependencyNode root, ConflictResolver.Verbosity verbosity)
352 throws RepositoryException {
353 ConflictResolver resolver = makeDefaultResolver();
354
355 System.out.println();
356 System.out.println("Input node:");
357 root.accept(DUMPER_SOUT);
358
359 DefaultRepositorySystemSession session = TestUtils.newSession();
360 session.setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, verbosity);
361 DependencyNode transformedRoot = resolver.transformGraph(root, TestUtils.newTransformationContext(session));
362
363 System.out.println();
364 System.out.println("Transformed node:");
365 transformedRoot.accept(DUMPER_SOUT);
366
367 return transformedRoot;
368 }
369
370 @Test
371 void derivedScopeChange() throws RepositoryException {
372 ConflictResolver resolver = makeDefaultResolver();
373
374
375
376 DependencyNode fooNode = makeDependencyNode("some-group", "foo", "1.0");
377 DependencyNode barNode = makeDependencyNode("some-group", "bar", "1.0", "test");
378 DependencyNode bazNode = makeDependencyNode("some-group", "baz", "1.0");
379 DependencyNode jazNode = makeDependencyNode("some-group", "jaz", "1.0");
380 fooNode.setChildren(mutableList(barNode, bazNode));
381
382 List<DependencyNode> jazList = mutableList(jazNode);
383 barNode.setChildren(jazList);
384 bazNode.setChildren(jazList);
385
386 DependencyNode transformedNode =
387 resolver.transformGraph(fooNode, TestUtils.newTransformationContext(TestUtils.newSession()));
388
389 assertSame(fooNode, transformedNode);
390 assertEquals(2, fooNode.getChildren().size());
391 assertSame(barNode, fooNode.getChildren().get(0));
392 assertEquals(1, barNode.getChildren().size());
393 assertSame(jazNode, barNode.getChildren().get(0));
394 assertSame(bazNode, fooNode.getChildren().get(1));
395 assertEquals(1, barNode.getChildren().size());
396 assertSame(jazNode, barNode.getChildren().get(0));
397 }
398
399 @Test
400 void derivedOptionalStatusChange() throws RepositoryException {
401 ConflictResolver resolver = makeDefaultResolver();
402
403
404
405 DependencyNode fooNode = makeDependencyNode("some-group", "foo", "1.0");
406 DependencyNode barNode = makeDependencyNode("some-group", "bar", "1.0");
407 barNode.setOptional(true);
408 DependencyNode bazNode = makeDependencyNode("some-group", "baz", "1.0");
409 DependencyNode jazNode = makeDependencyNode("some-group", "jaz", "1.0");
410 fooNode.setChildren(mutableList(barNode, bazNode));
411
412 List<DependencyNode> jazList = mutableList(jazNode);
413 barNode.setChildren(jazList);
414 bazNode.setChildren(jazList);
415
416 DependencyNode transformedNode =
417 resolver.transformGraph(fooNode, TestUtils.newTransformationContext(TestUtils.newSession()));
418
419 assertSame(fooNode, transformedNode);
420 assertEquals(2, fooNode.getChildren().size());
421 assertSame(barNode, fooNode.getChildren().get(0));
422 assertEquals(1, barNode.getChildren().size());
423 assertSame(jazNode, barNode.getChildren().get(0));
424 assertSame(bazNode, fooNode.getChildren().get(1));
425 assertEquals(1, barNode.getChildren().size());
426 assertSame(jazNode, barNode.getChildren().get(0));
427 }
428
429 private static ConflictResolver makeDefaultResolver() {
430 return new ConflictResolver(
431 new NearestVersionSelector(),
432 new JavaScopeSelector(),
433 new SimpleOptionalitySelector(),
434 new JavaScopeDeriver());
435 }
436
437 private static DependencyNode makeDependencyNode(String groupId, String artifactId, String version) {
438 return makeDependencyNode(groupId, artifactId, version, "compile");
439 }
440
441 private static DependencyNode makeDependencyNode(String groupId, String artifactId, String version, String scope) {
442 DefaultDependencyNode node = new DefaultDependencyNode(
443 new Dependency(new DefaultArtifact(groupId + ':' + artifactId + ':' + version), scope));
444 node.setVersion(new TestVersion(version));
445 node.setVersionConstraint(new TestVersionConstraint(node.getVersion()));
446 return node;
447 }
448
449 private static List<DependencyNode> mutableList(DependencyNode... nodes) {
450 return new ArrayList<>(Arrays.asList(nodes));
451 }
452 }