1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.cling.executor;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.nio.file.Paths;
26 import java.util.Collection;
27 import java.util.List;
28
29 import org.apache.maven.api.annotations.Nullable;
30 import org.apache.maven.api.cli.Executor;
31 import org.apache.maven.api.cli.ExecutorRequest;
32 import org.apache.maven.cling.executor.embedded.EmbeddedMavenExecutor;
33 import org.apache.maven.cling.executor.forked.ForkedMavenExecutor;
34 import org.junit.jupiter.api.AfterAll;
35 import org.junit.jupiter.api.Test;
36 import org.junit.jupiter.api.Timeout;
37 import org.junit.jupiter.api.condition.DisabledOnOs;
38 import org.junit.jupiter.api.io.CleanupMode;
39 import org.junit.jupiter.api.io.TempDir;
40
41 import static org.junit.jupiter.api.Assertions.assertEquals;
42 import static org.junit.jupiter.api.Assertions.assertFalse;
43 import static org.junit.jupiter.api.Assertions.assertTrue;
44 import static org.junit.jupiter.api.condition.OS.WINDOWS;
45
46 public abstract class MavenExecutorTestSupport {
47 @Timeout(15)
48 @Test
49 void mvnenc(
50 @TempDir(cleanup = CleanupMode.ON_SUCCESS) Path cwd,
51 @TempDir(cleanup = CleanupMode.ON_SUCCESS) Path userHome)
52 throws Exception {
53 String logfile = "m4.log";
54 execute(
55 cwd.resolve(logfile),
56 List.of(mvn4ExecutorRequestBuilder()
57 .command("mvnenc")
58 .cwd(cwd)
59 .userHomeDirectory(userHome)
60 .argument("diag")
61 .argument("-l")
62 .argument(logfile)
63 .build()));
64 System.out.println(Files.readString(cwd.resolve(logfile)));
65 }
66
67 @DisabledOnOs(
68 value = WINDOWS,
69 disabledReason = "JUnit on Windows fails to clean up as mvn3 does not close log file properly")
70 @Timeout(15)
71 @Test
72 void dump3(
73 @TempDir(cleanup = CleanupMode.ON_SUCCESS) Path cwd,
74 @TempDir(cleanup = CleanupMode.ON_SUCCESS) Path userHome)
75 throws Exception {
76 String logfile = "m3.log";
77 execute(
78 cwd.resolve(logfile),
79 List.of(mvn3ExecutorRequestBuilder()
80 .cwd(cwd)
81 .userHomeDirectory(userHome)
82 .argument("eu.maveniverse.maven.plugins:toolbox:0.7.4:gav-dump")
83 .argument("-l")
84 .argument(logfile)
85 .build()));
86 System.out.println(Files.readString(cwd.resolve(logfile)));
87 }
88
89 @Timeout(15)
90 @Test
91 void dump4(
92 @TempDir(cleanup = CleanupMode.ON_SUCCESS) Path cwd,
93 @TempDir(cleanup = CleanupMode.ON_SUCCESS) Path userHome)
94 throws Exception {
95 String logfile = "m4.log";
96 execute(
97 cwd.resolve(logfile),
98 List.of(mvn4ExecutorRequestBuilder()
99 .cwd(cwd)
100 .userHomeDirectory(userHome)
101 .argument("eu.maveniverse.maven.plugins:toolbox:0.7.4:gav-dump")
102 .argument("-l")
103 .argument(logfile)
104 .build()));
105 System.out.println(Files.readString(cwd.resolve(logfile)));
106 }
107
108 @Timeout(15)
109 @Test
110 void defaultFs(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir) throws Exception {
111 layDownFiles(tempDir);
112 String logfile = "m4.log";
113 execute(
114 tempDir.resolve(logfile),
115 List.of(mvn4ExecutorRequestBuilder()
116 .cwd(tempDir)
117 .argument("-V")
118 .argument("verify")
119 .argument("-l")
120 .argument(logfile)
121 .build()));
122 }
123
124 @Timeout(15)
125 @Test
126 void version() throws Exception {
127 assertEquals(
128 System.getProperty("maven4version"),
129 mavenVersion(mvn4ExecutorRequestBuilder().build()));
130 }
131
132 @DisabledOnOs(
133 value = WINDOWS,
134 disabledReason = "JUnit on Windows fails to clean up as mvn3 does not close log file properly")
135 @Timeout(15)
136 @Test
137 void defaultFs3x(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir) throws Exception {
138 layDownFiles(tempDir);
139 String logfile = "m3.log";
140 execute(
141 tempDir.resolve(logfile),
142 List.of(mvn3ExecutorRequestBuilder()
143 .cwd(tempDir)
144 .argument("-V")
145 .argument("verify")
146 .argument("-l")
147 .argument(logfile)
148 .build()));
149 }
150
151 @Timeout(15)
152 @Test
153 void version3x() throws Exception {
154 assertEquals(
155 System.getProperty("maven3version"),
156 mavenVersion(mvn3ExecutorRequestBuilder().build()));
157 }
158
159 @Timeout(15)
160 @Test
161 void defaultFsCaptureOutput(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir) throws Exception {
162 layDownFiles(tempDir);
163 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
164 execute(
165 null,
166 List.of(mvn4ExecutorRequestBuilder()
167 .cwd(tempDir)
168 .argument("-V")
169 .argument("verify")
170 .stdOut(stdout)
171 .build()));
172 assertFalse(stdout.toString().contains("[\u001B["), "By default no ANSI color codes");
173 assertTrue(stdout.toString().contains("INFO"), "No INFO found");
174 }
175
176 @Timeout(15)
177 @Test
178 void defaultFsCaptureOutputWithForcedColor(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir)
179 throws Exception {
180 layDownFiles(tempDir);
181 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
182 execute(
183 null,
184 List.of(mvn4ExecutorRequestBuilder()
185 .cwd(tempDir)
186 .argument("-V")
187 .argument("verify")
188 .argument("--color=yes")
189 .stdOut(stdout)
190 .build()));
191 assertTrue(stdout.toString().contains("[\u001B["), "No ANSI codes present");
192 assertTrue(stdout.toString().contains("INFO"), "No INFO found");
193 }
194
195 @Timeout(15)
196 @Test
197 void defaultFsCaptureOutputWithForcedOffColor(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir)
198 throws Exception {
199 layDownFiles(tempDir);
200 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
201 execute(
202 null,
203 List.of(mvn4ExecutorRequestBuilder()
204 .cwd(tempDir)
205 .argument("-V")
206 .argument("verify")
207 .argument("--color=no")
208 .stdOut(stdout)
209 .build()));
210 assertFalse(stdout.toString().contains("[\u001B["), "No ANSI codes present");
211 assertTrue(stdout.toString().contains("INFO"), "No INFO found");
212 }
213
214 @Timeout(15)
215 @Test
216 void defaultFs3xCaptureOutput(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir) throws Exception {
217 layDownFiles(tempDir);
218 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
219 execute(
220 null,
221 List.of(mvn3ExecutorRequestBuilder()
222 .cwd(tempDir)
223 .argument("-V")
224 .argument("verify")
225 .stdOut(stdout)
226 .build()));
227
228
229 assertTrue(stdout.toString().contains("INFO"), "No INFO found");
230 }
231
232 @Timeout(15)
233 @Test
234 void defaultFs3xCaptureOutputWithForcedColor(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir)
235 throws Exception {
236 layDownFiles(tempDir);
237 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
238 execute(
239 null,
240 List.of(mvn3ExecutorRequestBuilder()
241 .cwd(tempDir)
242 .argument("-V")
243 .argument("verify")
244 .argument("--color=yes")
245 .stdOut(stdout)
246 .build()));
247 assertTrue(stdout.toString().contains("[\u001B["), "No ANSI codes present");
248 assertTrue(stdout.toString().contains("INFO"), "No INFO found");
249 }
250
251 @Timeout(15)
252 @Test
253 void defaultFs3xCaptureOutputWithForcedOffColor(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path tempDir)
254 throws Exception {
255 layDownFiles(tempDir);
256 ByteArrayOutputStream stdout = new ByteArrayOutputStream();
257 execute(
258 null,
259 List.of(mvn3ExecutorRequestBuilder()
260 .cwd(tempDir)
261 .argument("-V")
262 .argument("verify")
263 .argument("--color=no")
264 .stdOut(stdout)
265 .build()));
266 assertFalse(stdout.toString().contains("[\u001B["), "No ANSI codes present");
267 assertTrue(stdout.toString().contains("INFO"), "No INFO found");
268 }
269
270 public static final String POM_STRING =
271 """
272 <?xml version="1.0" encoding="UTF-8"?>
273 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
274 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
275
276 <modelVersion>4.0.0</modelVersion>
277
278 <groupId>org.apache.maven.samples</groupId>
279 <artifactId>sample</artifactId>
280 <version>1.0.0</version>
281
282 <dependencyManagement>
283 <dependencies>
284 <dependency>
285 <groupId>org.junit</groupId>
286 <artifactId>junit-bom</artifactId>
287 <version>5.11.1</version>
288 <type>pom</type>
289 <scope>import</scope>
290 </dependency>
291 </dependencies>
292 </dependencyManagement>
293
294 <dependencies>
295 <dependency>
296 <groupId>org.junit.jupiter</groupId>
297 <artifactId>junit-jupiter-api</artifactId>
298 <scope>test</scope>
299 </dependency>
300 </dependencies>
301
302 </project>
303 """;
304
305 public static final String APP_JAVA_STRING =
306 """
307 package org.apache.maven.samples.sample;
308
309 public class App {
310 public static void main(String... args) {
311 System.out.println("Hello World!");
312 }
313 }
314 """;
315
316 protected void execute(@Nullable Path logFile, Collection<ExecutorRequest> requests) throws Exception {
317 Executor invoker = createAndMemoizeExecutor();
318 for (ExecutorRequest request : requests) {
319 MimirInfuser.infuse(request.userHomeDirectory());
320 int exitCode = invoker.execute(request);
321 if (exitCode != 0) {
322 throw new FailedExecution(request, exitCode, logFile == null ? "" : Files.readString(logFile));
323 }
324 }
325 }
326
327 protected String mavenVersion(ExecutorRequest request) throws Exception {
328 return createAndMemoizeExecutor().mavenVersion(request);
329 }
330
331 public static ExecutorRequest.Builder mvn3ExecutorRequestBuilder() {
332 return ExecutorRequest.mavenBuilder(Paths.get(System.getProperty("maven3home")));
333 }
334
335 public static ExecutorRequest.Builder mvn4ExecutorRequestBuilder() {
336 return ExecutorRequest.mavenBuilder(Paths.get(System.getProperty("maven4home")));
337 }
338
339 protected void layDownFiles(Path cwd) throws IOException {
340 Files.createDirectory(cwd.resolve(".mvn"));
341 Path pom = cwd.resolve("pom.xml").toAbsolutePath();
342 Files.writeString(pom, POM_STRING);
343 Path appJava = cwd.resolve("src/main/java/org/apache/maven/samples/sample/App.java");
344 Files.createDirectories(appJava.getParent());
345 Files.writeString(appJava, APP_JAVA_STRING);
346 }
347
348 protected static class FailedExecution extends Exception {
349 private final ExecutorRequest request;
350 private final int exitCode;
351 private final String log;
352
353 public FailedExecution(ExecutorRequest request, int exitCode, String log) {
354 super(request.toString() + " => " + exitCode + "\n" + log);
355 this.request = request;
356 this.exitCode = exitCode;
357 this.log = log;
358 }
359
360 public ExecutorRequest getRequest() {
361 return request;
362 }
363
364 public int getExitCode() {
365 return exitCode;
366 }
367
368 public String getLog() {
369 return log;
370 }
371 }
372
373 private static Executor executor;
374
375 protected final Executor createAndMemoizeExecutor() {
376 if (executor == null) {
377 executor = doSelectExecutor();
378 }
379 return executor;
380 }
381
382 @AfterAll
383 static void afterAll() {
384 if (executor != null) {
385 executor = null;
386 }
387 }
388
389
390
391
392 public static final EmbeddedMavenExecutor EMBEDDED_MAVEN_EXECUTOR = new EmbeddedMavenExecutor();
393 public static final ForkedMavenExecutor FORKED_MAVEN_EXECUTOR = new ForkedMavenExecutor();
394
395 protected abstract Executor doSelectExecutor();
396 }