1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.surefire.its.fixture;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.net.URL;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.ListIterator;
28 import java.util.Map;
29 import java.util.Properties;
30
31 import org.apache.maven.shared.utils.io.FileUtils;
32 import org.apache.maven.shared.verifier.VerificationException;
33 import org.apache.maven.shared.verifier.Verifier;
34 import org.apache.maven.shared.verifier.util.ResourceExtractor;
35
36 import static java.util.Collections.singletonMap;
37 import static java.util.Collections.unmodifiableList;
38
39
40
41
42
43
44
45 public final class MavenLauncher {
46 private static final File SETTINGS_XML_PATH = settingsXmlPath();
47
48 private final List<String> cliOptions = new ArrayList<>();
49
50 private final List<String> goals = new ArrayList<>();
51
52 private final Map<String, String> envVars = new HashMap<>();
53
54 private final Properties props = new Properties();
55
56 private File unpackedAt;
57
58 private Verifier verifier;
59
60 private OutputValidator validator;
61
62 private final Class<?> testCaseBeingRun;
63
64 private final String resourceName;
65
66 private final String suffix;
67
68 private final String[] cli;
69
70 private boolean expectFailure;
71
72 MavenLauncher(Class<?> testClass, String resourceName, String suffix, String[] cli) {
73 this.testCaseBeingRun = testClass;
74 this.resourceName = resourceName;
75 this.suffix = suffix != null ? suffix : "";
76 this.cli = cli == null ? null : cli.clone();
77 resetGoals();
78 resetCliOptions();
79 }
80
81 public MavenLauncher(Class<?> testClass, String resourceName, String suffix) {
82 this(testClass, resourceName, suffix, null);
83 }
84
85 public File getUnpackedAt() {
86 return ensureUnpacked();
87 }
88
89 private File ensureUnpacked() {
90 if (unpackedAt == null) {
91 unpackedAt = simpleExtractResources(testCaseBeingRun, resourceName);
92 }
93 return unpackedAt;
94 }
95
96 public void moveUnpackTo(File dest) throws IOException {
97 FileUtils.deleteDirectory(dest);
98
99 boolean moved = getUnpackedAt().renameTo(dest);
100 if (!moved) {
101 String fileEncoding = System.getProperty("file.encoding");
102 String os = System.getProperty("os.name");
103 String version = System.getProperty("os.version");
104 String arch = System.getProperty("os.arch");
105 throw new IOException("Could not move " + getUnpackedAt() + " to " + dest + " (file.encoding="
106 + fileEncoding + ", " + os + " " + version + " " + arch + ").");
107 }
108 unpackedAt = dest;
109 }
110
111 private void resetGoals() {
112 goals.clear();
113 }
114
115 private void addCliOption(String cliOption) {
116 cliOptions.add(cliOption);
117 }
118
119 private StackTraceElement findTopElemenent(StackTraceElement[] stackTrace, Class<?> testClassToLookFor) {
120 StackTraceElement bestmatch = null;
121 for (StackTraceElement stackTraceElement : stackTrace) {
122 if (stackTraceElement.getClassName().equals(testClassToLookFor.getName())) {
123 bestmatch = stackTraceElement;
124 }
125 }
126 return bestmatch;
127 }
128
129 private static StackTraceElement[] getStackTraceElements() {
130 try {
131 throw new RuntimeException();
132 } catch (RuntimeException e) {
133 return e.getStackTrace();
134 }
135 }
136
137 public void reset() {
138 resetGoals();
139 resetCliOptions();
140 verifier = null;
141 validator = null;
142 }
143
144 private void resetCliOptions() {
145 cliOptions.clear();
146 }
147
148 public MavenLauncher getSubProjectLauncher(String subProject) {
149 MavenLauncher mavenLauncher =
150 new MavenLauncher(testCaseBeingRun, resourceName + File.separator + subProject, suffix, cli);
151 mavenLauncher.unpackedAt = new File(ensureUnpacked(), subProject);
152 return mavenLauncher;
153 }
154
155 public OutputValidator getSubProjectValidator(String subProject) throws VerificationException {
156 String subProjectBasedir = getValidator().getSubFile(subProject).getAbsolutePath();
157 String settingsXml = settingsXmlPath().getAbsolutePath();
158 Verifier subProjectVerifier = createVerifier(subProjectBasedir, settingsXml, null);
159 return new OutputValidator(subProjectVerifier);
160 }
161
162 public MavenLauncher addEnvVar(String key, String value) {
163 envVars.put(key, value);
164 return this;
165 }
166
167 public MavenLauncher verifyFileNotPresent(String subFile) throws VerificationException {
168 getVerifier().verifyFileNotPresent(getValidator().getSubFile(subFile).getAbsolutePath());
169 return this;
170 }
171
172 public MavenLauncher showErrorStackTraces() {
173 addCliOption("-e");
174 return this;
175 }
176
177 public MavenLauncher debugLogging() {
178 addCliOption("-X");
179 return this;
180 }
181
182 public MavenLauncher failNever() {
183 addCliOption("-fn");
184 return this;
185 }
186
187 public MavenLauncher offline() {
188 addCliOption("-o");
189 return this;
190 }
191
192 public MavenLauncher skipClean() {
193 writeGoal("-Dclean.skip=true" );
194 writeGoal("-Dmaven.clean.skip=true" );
195 return this;
196 }
197
198 public MavenLauncher addGoal(String goal) {
199 writeGoal(goal);
200 return this;
201 }
202
203 public FailsafeOutputValidator executeVerify() {
204 return new FailsafeOutputValidator(conditionalExec("verify"));
205 }
206
207 public OutputValidator executeTest() {
208 return conditionalExec("test");
209 }
210
211 List<String> getGoals() {
212 return unmodifiableList(goals);
213 }
214
215 private void writeGoal(String newGoal) {
216 if (newGoal != null && newGoal.startsWith("-D")) {
217 String sysPropKey = newGoal.contains("=") ? newGoal.substring(0, newGoal.indexOf('=')) : newGoal;
218
219 String sysPropStarter = sysPropKey + "=";
220
221 for (ListIterator<String> it = goals.listIterator(); it.hasNext(); ) {
222 String goal = it.next();
223 if (goal.equals(sysPropKey) || goal.startsWith(sysPropStarter)) {
224 System.out.printf(
225 "[WARNING] System property already exists '%s'. Overriding to '%s'.%n", goal, newGoal);
226 it.set(newGoal);
227 return;
228 }
229 }
230 }
231 goals.add(newGoal);
232 }
233
234 private OutputValidator conditionalExec(String goal) {
235 OutputValidator verify;
236 try {
237 verify = execute(goal);
238 } catch (SurefireVerifierException exc) {
239 if (expectFailure) {
240 return getValidator();
241 } else {
242 throw exc;
243 }
244 }
245 if (expectFailure) {
246 throw new RuntimeException("Expecting build failure, have got none!");
247 }
248 return verify;
249 }
250
251 public MavenLauncher withFailure() {
252 expectFailure = true;
253 return this;
254 }
255
256 public OutputValidator execute(String goal) {
257 addGoal(goal);
258 return executeCurrentGoals();
259 }
260
261 public OutputValidator executeCurrentGoals() {
262 try {
263 getVerifier().addCliArguments(cliOptions.toArray(new String[0]));
264 getVerifier().addCliArguments(goals.toArray(new String[] {}));
265 getVerifier().setSystemProperties(props);
266 getVerifier().setEnvironmentVariables(envVars);
267 getVerifier().execute();
268 return getValidator();
269 } catch (VerificationException e) {
270 throw new SurefireVerifierException(e.getLocalizedMessage(), e);
271 }
272 }
273
274 public MavenLauncher activateProfile(String profile) {
275 return addGoal("-P" + profile);
276 }
277
278 public MavenLauncher sysProp(String key, String value) {
279 return sysProp(singletonMap(key, value));
280 }
281
282 public MavenLauncher sysProp(Map<String, String> properties) {
283 props.putAll(properties);
284 return this;
285 }
286
287 public MavenLauncher sysProp(String key, boolean value) {
288 return sysProp(singletonMap(key, Boolean.toString(value)));
289 }
290
291 public MavenLauncher sysProp(String key, int value) {
292 return sysProp(singletonMap(key, Integer.toString(value)));
293 }
294
295 public MavenLauncher sysProp(String key, double value) {
296 return sysProp(singletonMap(key, Double.toString(value)));
297 }
298
299 public MavenLauncher showExceptionMessages() {
300 addCliOption("-e");
301 return this;
302 }
303
304 public MavenLauncher deleteReportsDir() {
305 try {
306 FileUtils.deleteDirectory(getValidator().getSubFile("reports"));
307 } catch (IOException e) {
308 throw new SurefireVerifierException(e);
309 }
310 return this;
311 }
312
313 public OutputValidator getValidator() {
314 if (validator == null) {
315 validator = new OutputValidator(getVerifier());
316 }
317 return validator;
318 }
319
320 public void setForkJvm(boolean forkJvm) {
321 getVerifier().setForkJvm(forkJvm);
322 }
323
324 public String getLocalRepository() {
325 return getVerifier().getLocalRepository();
326 }
327
328 public void setAutoclean(boolean autoclean) {
329 getVerifier().setAutoclean(autoclean);
330 }
331
332 public void setLogFileName(String logFileName) {
333 getVerifier().setLogFileName(logFileName);
334 }
335
336 private Verifier getVerifier() {
337 if (verifier == null) {
338 try {
339 String unpackedPath = ensureUnpacked().getAbsolutePath();
340 String settingsXml = SETTINGS_XML_PATH.getAbsolutePath();
341 verifier = createVerifier(unpackedPath, settingsXml, cli);
342 } catch (VerificationException e) {
343 throw new RuntimeException(e);
344 }
345 }
346 return verifier;
347 }
348
349 private File simpleExtractResources(Class<?> cl, String resourcePath) {
350 if (!resourcePath.startsWith("/")) {
351 resourcePath = "/" + resourcePath;
352 }
353 File tempDir = getUnpackDir();
354 File testDir = new File(tempDir, resourcePath);
355 try {
356 File parentPom = new File(tempDir.getParentFile(), "pom.xml");
357 if (!parentPom.exists()) {
358 URL resource = cl.getResource("/pom.xml");
359 FileUtils.copyURLToFile(resource, parentPom);
360 }
361
362 FileUtils.deleteDirectory(testDir);
363 File file = ResourceExtractor.extractResourceToDestination(cl, resourcePath, tempDir, true);
364 return file.getCanonicalFile();
365 } catch (IOException e) {
366 throw new RuntimeException(e);
367 }
368 }
369
370 private File getUnpackDir() {
371 String tempDirPath = System.getProperty("maven.test.tmpdir", System.getProperty("java.io.tmpdir"));
372 return new File(tempDirPath, testCaseBeingRun.getSimpleName() + "_" + getTestMethodName() + suffix);
373 }
374
375 public File getArtifactPath(String gid, String aid, String version, String ext) {
376 return new File(verifier.getArtifactPath(gid, aid, version, ext));
377 }
378
379 String getTestMethodName() {
380
381 StackTraceElement[] stackTrace = getStackTraceElements();
382 StackTraceElement topInTestClass;
383 topInTestClass = findTopElemenent(stackTrace, testCaseBeingRun);
384 if (topInTestClass == null) {
385
386 topInTestClass = findTopElemenent(stackTrace, testCaseBeingRun.getSuperclass());
387 }
388 if (topInTestClass != null) {
389 return topInTestClass.getMethodName();
390 }
391 throw new IllegalStateException("Cannot find " + testCaseBeingRun.getName() + "in stacktrace");
392 }
393
394 private static Verifier createVerifier(String basedir, String settingsFile, String[] defaultCliOptions)
395 throws VerificationException {
396
397 return defaultCliOptions == null
398 ? new Verifier(basedir, settingsFile, false)
399 : new Verifier(basedir, settingsFile, false, defaultCliOptions);
400 }
401
402 private static File settingsXmlPath() {
403 try {
404 return new File(System.getProperty("maven.settings.file")).getCanonicalFile();
405 } catch (IOException e) {
406 throw new IllegalStateException(e.getLocalizedMessage(), e);
407 }
408 }
409 }