1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.dependency.tree;
20
21 import javax.inject.Inject;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.OutputStreamWriter;
26 import java.io.StringReader;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Comparator;
33 import java.util.List;
34 import java.util.Set;
35 import java.util.stream.Collectors;
36
37 import jakarta.json.Json;
38 import jakarta.json.JsonArray;
39 import jakarta.json.JsonObject;
40 import jakarta.json.JsonReader;
41 import org.apache.maven.api.plugin.testing.InjectMojo;
42 import org.apache.maven.api.plugin.testing.MojoParameter;
43 import org.apache.maven.api.plugin.testing.MojoTest;
44 import org.apache.maven.artifact.Artifact;
45 import org.apache.maven.execution.MavenSession;
46 import org.apache.maven.plugins.dependency.testUtils.DependencyArtifactStubFactory;
47 import org.apache.maven.project.DefaultProjectBuildingRequest;
48 import org.apache.maven.project.MavenProject;
49 import org.apache.maven.shared.dependency.graph.DependencyNode;
50 import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyNode;
51 import org.junit.jupiter.api.BeforeEach;
52 import org.junit.jupiter.api.Test;
53 import org.junit.jupiter.api.io.TempDir;
54
55 import static org.apache.maven.api.plugin.testing.MojoExtension.setVariableValueToObject;
56 import static org.junit.jupiter.api.Assertions.assertEquals;
57 import static org.junit.jupiter.api.Assertions.assertNotNull;
58 import static org.junit.jupiter.api.Assertions.assertTrue;
59 import static org.mockito.Mockito.doAnswer;
60 import static org.mockito.Mockito.spy;
61 import static org.mockito.Mockito.when;
62
63
64
65
66
67
68
69
70 @MojoTest(realRepositorySession = true)
71 class TestTreeMojo {
72
73 @TempDir
74 private File tempDir;
75
76 @Inject
77 private MavenSession session;
78
79 private DependencyArtifactStubFactory stubFactory;
80
81 @BeforeEach
82 void setUp() {
83 stubFactory = new DependencyArtifactStubFactory(tempDir, true, false);
84 session.getRequest().setLocalRepositoryPath(new File(tempDir, "localTestRepo"));
85
86 DefaultProjectBuildingRequest pbr = spy(new DefaultProjectBuildingRequest());
87 doAnswer(__ -> session.getRepositorySession()).when(pbr).getRepositorySession();
88 when(session.getProjectBuildingRequest()).thenReturn(pbr);
89 }
90
91
92
93
94
95
96
97
98 @Test
99 @InjectMojo(goal = "tree")
100 void testTreeTestEnvironment(TreeMojo mojo) throws Exception {
101 assertNotNull(mojo);
102 assertNotNull(mojo.getProject());
103 MavenProject project = mojo.getProject();
104 project.setArtifact(this.stubFactory.createArtifact("testGroupId", "project", "1.0"));
105
106 Set<Artifact> artifacts = this.stubFactory.getScopedArtifacts();
107 Set<Artifact> directArtifacts = this.stubFactory.getReleaseAndSnapshotArtifacts();
108 artifacts.addAll(directArtifacts);
109
110 project.setArtifacts(artifacts);
111 project.setDependencyArtifacts(directArtifacts);
112
113 mojo.execute();
114
115 DependencyNode rootNode = mojo.getDependencyGraph();
116 assertNodeEquals("testGroupId:project:jar:1.0:compile", rootNode);
117 assertEquals(2, rootNode.getChildren().size());
118
119 List<String> actualNodes = Arrays.asList(
120 createArtifactCoordinateString(rootNode.getChildren().get(0)),
121 createArtifactCoordinateString(rootNode.getChildren().get(1)));
122 List<String> expectedNodes =
123 Arrays.asList("testGroupId:release:jar:1.0:compile", "testGroupId:snapshot:jar:2.0-SNAPSHOT:compile");
124
125 assertTrue(expectedNodes.containsAll(actualNodes));
126 }
127
128
129
130
131
132
133 @Test
134 @InjectMojo(goal = "tree")
135 @MojoParameter(name = "outputType", value = "dot")
136 void testTreeDotSerializing(TreeMojo mojo) throws Exception {
137 List<String> contents = runTreeMojo(mojo);
138 assertTrue(findString(contents, "digraph \"testGroupId:project:jar:1.0:compile\" {"));
139 assertTrue(findString(
140 contents,
141 "\"testGroupId:project:jar:1.0:compile\" -> \"testGroupId:snapshot:jar:2.0-SNAPSHOT:compile\""));
142 assertTrue(findString(
143 contents, "\"testGroupId:project:jar:1.0:compile\" -> \"testGroupId:release:jar:1.0:compile\""));
144 }
145
146
147
148
149
150
151 @Test
152 @InjectMojo(goal = "tree")
153 @MojoParameter(name = "outputType", value = "graphml")
154 void testTreeGraphMLSerializing(TreeMojo mojo) throws Exception {
155 List<String> contents = runTreeMojo(mojo);
156
157 assertTrue(findString(contents, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
158 assertTrue(findString(contents, "<y:NodeLabel>testGroupId:project:jar:1.0:compile</y:NodeLabel>"));
159 assertTrue(findString(contents, "<y:NodeLabel>testGroupId:snapshot:jar:2.0-SNAPSHOT:compile</y:NodeLabel>"));
160 assertTrue(findString(contents, "<y:NodeLabel>testGroupId:release:jar:1.0:compile</y:NodeLabel>"));
161 assertTrue(findString(contents, "<key for=\"node\" id=\"d0\" yfiles.type=\"nodegraphics\"/>"));
162 assertTrue(findString(contents, "<key for=\"edge\" id=\"d1\" yfiles.type=\"edgegraphics\"/>"));
163 }
164
165
166
167
168
169
170 @Test
171 @InjectMojo(goal = "tree")
172 @MojoParameter(name = "outputType", value = "tgf")
173 void testTreeTGFSerializing(TreeMojo mojo) throws Exception {
174 List<String> contents = runTreeMojo(mojo);
175 assertTrue(findString(contents, "testGroupId:project:jar:1.0:compile"));
176 assertTrue(findString(contents, "testGroupId:snapshot:jar:2.0-SNAPSHOT:compile"));
177 assertTrue(findString(contents, "testGroupId:release:jar:1.0:compile"));
178 }
179
180
181
182
183 @Test
184 void testTreeJsonCircularDependency() throws IOException {
185 File outputFile = new File(tempDir, "tree1.json");
186 Files.createDirectories(outputFile.getParentFile().toPath());
187 outputFile.createNewFile();
188
189 Artifact artifact1 = this.stubFactory.createArtifact("testGroupId", "project1", "1.0");
190 Artifact artifact2 = this.stubFactory.createArtifact("testGroupId", "project2", "1.0");
191 DefaultDependencyNode node1 = new DefaultDependencyNode(artifact1);
192 DefaultDependencyNode node2 = new DefaultDependencyNode(artifact2);
193
194 node1.setChildren(new ArrayList<>());
195 node2.setChildren(new ArrayList<>());
196
197 node1.getChildren().add(node2);
198 node2.getChildren().add(node1);
199
200 try (OutputStreamWriter outputStreamWriter =
201 new OutputStreamWriter(Files.newOutputStream(outputFile.toPath()))) {
202 JsonDependencyNodeVisitor jsonDependencyNodeVisitor = new JsonDependencyNodeVisitor(outputStreamWriter);
203
204 jsonDependencyNodeVisitor.visit(node1);
205 }
206 }
207
208
209
210
211 @Test
212 @InjectMojo(goal = "tree")
213 @MojoParameter(name = "outputType", value = "json")
214 void testTreeJsonParsing(TreeMojo mojo) throws Exception {
215 List<String> contents = runTreeMojo(mojo);
216
217 System.setProperty("jakarta.json.provider", "org.glassfish.json.JsonProviderImpl");
218 try (JsonReader reader = Json.createReader(new StringReader(String.join(System.lineSeparator(), contents)))) {
219 JsonObject root = reader.readObject();
220
221 assertEquals("testGroupId", root.getString("groupId"));
222 assertEquals("project", root.getString("artifactId"));
223 assertEquals("1.0", root.getString("version"));
224 assertEquals("jar", root.getString("type"));
225 assertEquals("compile", root.getString("scope"));
226 assertEquals("", root.getString("classifier"));
227 assertEquals("false", root.getString("optional"));
228
229 JsonArray children = root.getJsonArray("children");
230 assertEquals(2, children.size());
231
232 List<JsonObject> sortedChildren = children.stream()
233 .map(JsonObject.class::cast)
234 .sorted(Comparator.comparing(child -> child.getString("artifactId")))
235 .collect(Collectors.toList());
236
237
238 JsonObject child0 = sortedChildren.get(0);
239 assertEquals("testGroupId", child0.getString("groupId"));
240 assertEquals("release", child0.getString("artifactId"));
241 assertEquals("1.0", child0.getString("version"));
242 assertEquals("jar", child0.getString("type"));
243 assertEquals("compile", child0.getString("scope"));
244 assertEquals("", child0.getString("classifier"));
245 assertEquals("false", child0.getString("optional"));
246
247 JsonObject child1 = sortedChildren.get(1);
248 assertEquals("testGroupId", child1.getString("groupId"));
249 assertEquals("snapshot", child1.getString("artifactId"));
250 assertEquals("2.0-SNAPSHOT", child1.getString("version"));
251 assertEquals("jar", child1.getString("type"));
252 assertEquals("compile", child1.getString("scope"));
253 assertEquals("", child1.getString("classifier"));
254 assertEquals("false", child1.getString("optional"));
255 }
256 }
257
258
259
260
261
262
263
264 private List<String> runTreeMojo(TreeMojo mojo) throws Exception {
265 Path outputFilePath = Paths.get(tempDir.getPath(), "outputFile.txt");
266 setVariableValueToObject(mojo, "outputEncoding", "UTF-8");
267 setVariableValueToObject(mojo, "outputFile", outputFilePath.toFile());
268
269 assertNotNull(mojo);
270 assertNotNull(mojo.getProject());
271 MavenProject project = mojo.getProject();
272 project.setArtifact(this.stubFactory.createArtifact("testGroupId", "project", "1.0"));
273
274 Set<Artifact> artifacts = this.stubFactory.getScopedArtifacts();
275 Set<Artifact> directArtifacts = this.stubFactory.getReleaseAndSnapshotArtifacts();
276 artifacts.addAll(directArtifacts);
277
278 project.setArtifacts(artifacts);
279 project.setDependencyArtifacts(directArtifacts);
280
281 mojo.execute();
282
283 return Files.readAllLines(outputFilePath);
284 }
285
286
287
288
289
290
291
292 private boolean findString(List<String> contents, String str) {
293 for (String line : contents) {
294 if (line.contains(str)) {
295
296 return true;
297 }
298 }
299
300
301 return false;
302 }
303
304
305
306 private void assertNodeEquals(String expectedNode, DependencyNode actualNode) {
307 String[] tokens = expectedNode.split(":");
308
309 assertNodeEquals(tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], actualNode);
310 }
311
312 private void assertNodeEquals(
313 String expectedGroupId,
314 String expectedArtifactId,
315 String expectedType,
316 String expectedVersion,
317 String expectedScope,
318 DependencyNode actualNode) {
319 Artifact actualArtifact = actualNode.getArtifact();
320
321 assertEquals(expectedGroupId, actualArtifact.getGroupId(), "group id");
322 assertEquals(expectedArtifactId, actualArtifact.getArtifactId(), "artifact id");
323 assertEquals(expectedType, actualArtifact.getType(), "type");
324 assertEquals(expectedVersion, actualArtifact.getVersion(), "version");
325 assertEquals(expectedScope, actualArtifact.getScope(), "scope");
326 }
327
328 private String createArtifactCoordinateString(DependencyNode actualNode) {
329 return actualNode.getArtifact().getGroupId() + ":"
330 + actualNode.getArtifact().getArtifactId() + ":"
331 + actualNode.getArtifact().getType() + ":"
332 + actualNode.getArtifact().getVersion() + ":"
333 + actualNode.getArtifact().getScope();
334 }
335 }