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