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