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