1 package org.apache.maven.plugin.surefire;
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.artifact.Artifact;
23 import org.apache.maven.artifact.DefaultArtifact;
24 import org.apache.maven.artifact.handler.ArtifactHandler;
25 import org.apache.maven.artifact.versioning.VersionRange;
26 import org.apache.maven.plugin.surefire.log.PluginConsoleLogger;
27 import org.apache.maven.project.MavenProject;
28 import org.apache.maven.surefire.booter.ClassLoaderConfiguration;
29 import org.apache.maven.surefire.booter.Classpath;
30 import org.apache.maven.surefire.booter.StartupConfiguration;
31 import org.apache.maven.surefire.suite.RunResult;
32 import org.codehaus.plexus.logging.Logger;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.mockito.ArgumentCaptor;
36 import org.mockito.Mock;
37 import org.powermock.core.classloader.annotations.PrepareForTest;
38 import org.powermock.modules.junit4.PowerMockRunner;
39
40 import java.io.File;
41 import java.io.IOException;
42 import java.util.ArrayList;
43 import java.util.Collection;
44 import java.util.HashMap;
45 import java.util.HashSet;
46 import java.util.LinkedHashSet;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Set;
50
51 import static java.io.File.separatorChar;
52 import static java.util.Arrays.asList;
53 import static java.util.Collections.singleton;
54 import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS;
55 import static org.apache.maven.artifact.versioning.VersionRange.createFromVersion;
56 import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec;
57 import static org.fest.assertions.Assertions.assertThat;
58 import static org.mockito.ArgumentMatchers.any;
59 import static org.mockito.ArgumentMatchers.anyString;
60 import static org.mockito.Mockito.times;
61 import static org.mockito.Mockito.when;
62 import static org.mockito.Mockito.verify;
63 import static org.powermock.api.mockito.PowerMockito.doNothing;
64 import static org.powermock.api.mockito.PowerMockito.doReturn;
65 import static org.powermock.api.mockito.PowerMockito.mock;
66 import static org.powermock.api.mockito.PowerMockito.spy;
67 import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
68 import static org.powermock.reflect.Whitebox.invokeMethod;
69
70
71
72
73 @RunWith( PowerMockRunner.class )
74 @PrepareForTest( AbstractSurefireMojo.class )
75 public class AbstractSurefireMojoTest
76 {
77 @Mock
78 private ArtifactHandler handler;
79
80 private final Mojo mojo = new Mojo();
81
82 @Test
83 public void shouldRetainInPluginArtifacts() throws Exception
84 {
85 Artifact provider = new DefaultArtifact( "g", "a", createFromVersionSpec( "1" ), "compile", "jar", "", null );
86 Artifact common = new DefaultArtifact( "g", "c", createFromVersionSpec( "1" ), "compile", "jar", "", null );
87 Artifact api = new DefaultArtifact( "g", "a", createFromVersionSpec( "1" ), "compile", "jar", "", null );
88
89 Set<Artifact> providerArtifacts = singleton( provider );
90 Artifact[] inPluginArtifacts = { common, api };
91 Set<Artifact> inPluginClasspath = invokeMethod( AbstractSurefireMojo.class,
92 "retainInProcArtifactsUnique", providerArtifacts, inPluginArtifacts );
93
94 assertThat( inPluginClasspath )
95 .containsOnly( common );
96 }
97
98 @Test
99 public void shouldRetainInProcArtifactsUnique() throws Exception
100 {
101 Artifact provider = new DefaultArtifact( "g", "p", createFromVersionSpec( "1" ), "compile", "jar", "", null );
102 Artifact common = new DefaultArtifact( "g", "c", createFromVersionSpec( "1" ), "compile", "jar", "", null );
103 Artifact api = new DefaultArtifact( "g", "a", createFromVersionSpec( "1" ), "compile", "jar", "", null );
104
105 Set<Artifact> providerArtifacts = singleton( provider );
106 Artifact[] inPluginArtifacts = { common, api };
107 Set<Artifact> inPluginClasspath = invokeMethod( AbstractSurefireMojo.class,
108 "retainInProcArtifactsUnique", providerArtifacts, inPluginArtifacts );
109
110 assertThat( inPluginClasspath )
111 .containsOnly( common, api );
112 }
113
114 @Test
115 public void shouldCreateInProcClasspath() throws Exception
116 {
117 Artifact provider = new DefaultArtifact( "g", "p", createFromVersionSpec( "1" ), "compile", "jar", "", null );
118 provider.setFile( mockFile( "provider.jar" ) );
119
120 Artifact common = new DefaultArtifact( "g", "c", createFromVersionSpec( "1" ), "compile", "jar", "", null );
121 common.setFile( mockFile( "maven-surefire-common.jar" ) );
122
123 Artifact api = new DefaultArtifact( "g", "a", createFromVersionSpec( "1" ), "compile", "jar", "", null );
124 api.setFile( mockFile( "surefire-api.jar" ) );
125
126 Set<Artifact> newArtifacts = new LinkedHashSet<>();
127 newArtifacts.add( common );
128 newArtifacts.add( api );
129
130 Classpath providerClasspath = new Classpath( singleton( provider.getFile().getAbsolutePath() ) );
131
132 Classpath inPluginClasspath = invokeMethod( AbstractSurefireMojo.class,
133 "createInProcClasspath", providerClasspath, newArtifacts );
134
135 Classpath expectedClasspath =
136 new Classpath( asList( provider.getFile().getAbsolutePath(),
137 common.getFile().getAbsolutePath(),
138 api.getFile().getAbsolutePath() ) );
139
140 assertThat( (Object ) inPluginClasspath )
141 .isEqualTo( expectedClasspath );
142
143 }
144
145 @Test
146 public void shouldGenerateTestClasspath() throws Exception
147 {
148 AbstractSurefireMojo mojo = spy( this.mojo );
149
150 when( mojo.getClassesDirectory() ).thenReturn( new File( "target" + separatorChar + "classes" ) );
151 when( mojo.getTestClassesDirectory() ).thenReturn( new File( "target" + separatorChar + "test-classes" ) );
152 when( mojo.getClasspathDependencyScopeExclude() ).thenReturn( "runtime" );
153 when( mojo.getClasspathDependencyExcludes() ).thenReturn( new String[]{ "g3:a3" } );
154 doReturn( mock( Artifact.class ) ).when( mojo, "getTestNgArtifact" );
155
156 Set<Artifact> artifacts = new HashSet<>();
157
158 Artifact a1 = mock( Artifact.class );
159 when( a1.getGroupId() ).thenReturn( "g1" );
160 when( a1.getArtifactId() ).thenReturn( "a1" );
161 when( a1.getVersion() ).thenReturn( "1" );
162 when( a1.getScope() ).thenReturn( "runtime" );
163 when( a1.getDependencyConflictId() ).thenReturn( "g1:a1:jar" );
164 when( a1.getId() ).thenReturn( "g1:a1:jar:1" );
165 artifacts.add( a1 );
166
167 ArtifactHandler artifactHandler = mock( ArtifactHandler.class );
168 when( artifactHandler.isAddedToClasspath() ).thenReturn( true );
169
170 Artifact a2 = mock( Artifact.class );
171 when( a2.getGroupId() ).thenReturn( "g2" );
172 when( a2.getArtifactId() ).thenReturn( "a2" );
173 when( a2.getVersion() ).thenReturn( "2" );
174 when( a2.getScope() ).thenReturn( "test" );
175 when( a2.getDependencyConflictId() ).thenReturn( "g2:a2:jar" );
176 when( a2.getId() ).thenReturn( "g2:a2:jar:2" );
177 when( a2.getFile() ).thenReturn( new File( "a2-2.jar" ) );
178 when( a2.getArtifactHandler() ).thenReturn( artifactHandler );
179 artifacts.add( a2 );
180
181 Artifact a3 = mock( Artifact.class );
182 when( a3.getGroupId() ).thenReturn( "g3" );
183 when( a3.getArtifactId() ).thenReturn( "a3" );
184 when( a3.getVersion() ).thenReturn( "3" );
185 when( a3.getScope() ).thenReturn( "test" );
186 when( a3.getDependencyConflictId() ).thenReturn( "g3:a3:jar" );
187 when( a3.getId() ).thenReturn( "g3:a3:jar:3" );
188 when( a3.getFile() ).thenReturn( new File( "a3-3.jar" ) );
189 when( a3.getArtifactHandler() ).thenReturn( artifactHandler );
190 artifacts.add( a3 );
191
192 MavenProject project = mock( MavenProject.class );
193 when( project.getArtifacts() ).thenReturn( artifacts );
194 when( mojo.getProject() ).thenReturn( project );
195
196 TestClassPath cp = invokeMethod( mojo, "generateTestClasspath" );
197
198 verifyPrivate( mojo, times( 1 ) ).invoke( "generateTestClasspath" );
199 verify( mojo, times( 1 ) ).getClassesDirectory();
200 verify( mojo, times( 1 ) ).getTestClassesDirectory();
201 verify( mojo, times( 3 ) ).getClasspathDependencyScopeExclude();
202 verify( mojo, times( 2 ) ).getClasspathDependencyExcludes();
203 verify( mojo, times( 1 ) ).getAdditionalClasspathElements();
204
205 assertThat( cp.toClasspath().getClassPath() ).hasSize( 3 );
206 assertThat( cp.toClasspath().getClassPath().get( 0 ) ).endsWith( "test-classes" );
207 assertThat( cp.toClasspath().getClassPath().get( 1 ) ).endsWith( "classes" );
208 assertThat( cp.toClasspath().getClassPath().get( 2 ) ).endsWith( "a2-2.jar" );
209 }
210
211 @Test
212 public void shouldHaveStartupConfigForNonModularClasspath()
213 throws Exception
214 {
215 AbstractSurefireMojo mojo = spy( this.mojo );
216
217 Artifact common = new DefaultArtifact( "org.apache.maven.surefire", "maven-surefire-common",
218 createFromVersion( "1" ), "runtime", "jar", "", handler );
219 common.setFile( mockFile( "maven-surefire-common.jar" ) );
220
221 Artifact api = new DefaultArtifact( "org.apache.maven.surefire", "surefire-api",
222 createFromVersion( "1" ), "runtime", "jar", "", handler );
223 api.setFile( mockFile( "surefire-api.jar" ) );
224
225 Artifact loggerApi = new DefaultArtifact( "org.apache.maven.surefire", "surefire-logger-api",
226 createFromVersion( "1" ), "runtime", "jar", "", handler );
227 loggerApi.setFile( mockFile( "surefire-logger-api.jar" ) );
228
229 Map<String, Artifact> providerArtifactsMap = new HashMap<>();
230 providerArtifactsMap.put( "org.apache.maven.surefire:maven-surefire-common", common );
231 providerArtifactsMap.put( "org.apache.maven.surefire:surefire-api", api );
232 providerArtifactsMap.put( "org.apache.maven.surefire:surefire-logger-api", loggerApi );
233
234 when( mojo.getPluginArtifactMap() )
235 .thenReturn( providerArtifactsMap );
236
237 when( handler.isAddedToClasspath() ).thenReturn( true );
238
239 VersionRange v1 = createFromVersion( "4.12" );
240 Artifact junit = new DefaultArtifact( "junit", "junit", v1, "test", "jar", "", handler );
241 junit.setFile( mockFile( "junit.jar" ) );
242
243 VersionRange v2 = createFromVersion( "1.3.0" );
244 Artifact hamcrest = new DefaultArtifact( "org.hamcrest", "hamcrest-core", v2, "test", "jar", "", handler );
245 hamcrest.setFile( mockFile( "hamcrest.jar" ) );
246
247 File classesDir = mockFile( "classes" );
248 File testClassesDir = mockFile( "test-classes" );
249 TestClassPath testClasspath =
250 new TestClassPath( asList( junit, hamcrest ), classesDir, testClassesDir, null, null );
251
252 doReturn( testClasspath ).when( mojo, "generateTestClasspath" );
253 doReturn( 1 ).when( mojo, "getEffectiveForkCount" );
254 doReturn( true ).when( mojo, "effectiveIsEnableAssertions" );
255 when( mojo.isChildDelegation() ).thenReturn( false );
256
257 ClassLoaderConfiguration classLoaderConfiguration = new ClassLoaderConfiguration( false, true );
258
259 VersionRange v3 = createFromVersion( "1" );
260 Artifact provider = new DefaultArtifact( "x", "surefire-provider", v3, "runtime", "jar", "", handler );
261 provider.setFile( mockFile( "surefire-provider.jar" ) );
262 Set<Artifact> providerArtifacts = singleton( provider );
263
264 Logger logger = mock( Logger.class );
265 when( logger.isDebugEnabled() ).thenReturn( true );
266 doNothing().when( logger ).debug( anyString() );
267 when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) );
268
269 StartupConfiguration conf = invokeMethod( mojo, "newStartupConfigWithClasspath",
270 classLoaderConfiguration, providerArtifacts, "org.asf.Provider" );
271
272 verify( mojo, times( 1 ) ).effectiveIsEnableAssertions();
273 verify( mojo, times( 1 ) ).isChildDelegation();
274 verifyPrivate( mojo, times( 1 ) ).invoke( "generateTestClasspath" );
275 verify( mojo, times( 1 ) ).getEffectiveForkCount();
276 ArgumentCaptor<String> argument = ArgumentCaptor.forClass( String.class );
277 verify( logger, times( 6 ) ).debug( argument.capture() );
278 assertThat( argument.getAllValues() )
279 .containsExactly( "test classpath: test-classes classes junit.jar hamcrest.jar",
280 "provider classpath: surefire-provider.jar",
281 "test(compact) classpath: test-classes classes junit.jar hamcrest.jar",
282 "provider(compact) classpath: surefire-provider.jar",
283 "in-process classpath: surefire-provider.jar maven-surefire-common.jar surefire-api.jar surefire-logger-api.jar",
284 "in-process(compact) classpath: surefire-provider.jar maven-surefire-common.jar surefire-api.jar surefire-logger-api.jar"
285 );
286
287 assertThat( conf.getClassLoaderConfiguration() )
288 .isSameAs( classLoaderConfiguration );
289
290 assertThat( ( Object ) conf.getClasspathConfiguration().getTestClasspath() )
291 .isEqualTo( testClasspath.toClasspath() );
292
293 Collection<String> files = new ArrayList<>();
294 for ( Artifact providerArtifact : providerArtifacts )
295 {
296 files.add( providerArtifact.getFile().getAbsolutePath() );
297 }
298 assertThat( ( Object ) conf.getClasspathConfiguration().getProviderClasspath() )
299 .isEqualTo( new Classpath( files ) );
300
301 assertThat( ( Object ) conf.getClasspathConfiguration().isClassPathConfig() )
302 .isEqualTo( true );
303
304 assertThat( ( Object ) conf.getClasspathConfiguration().isModularPathConfig() )
305 .isEqualTo( false );
306
307 assertThat( ( Object ) conf.getClasspathConfiguration().isEnableAssertions() )
308 .isEqualTo( true );
309
310 assertThat( conf.getProviderClassName() )
311 .isEqualTo( "org.asf.Provider" );
312 }
313
314 @Test
315 public void shouldExistTmpDirectory() throws IOException
316 {
317 String systemTmpDir = System.getProperty( "java.io.tmpdir" );
318 String usrDir = new File( System.getProperty( "user.dir" ) ).getCanonicalPath();
319
320 String tmpDir = "surefireX" + System.currentTimeMillis();
321
322
323 new File( systemTmpDir, tmpDir ).delete();
324
325 File targetDir = new File( usrDir, "target" );
326
327 new File( targetDir, tmpDir ).delete();
328
329 AbstractSurefireMojo mojo = mock( AbstractSurefireMojo.class );
330 Logger logger = mock( Logger.class );
331 when( logger.isDebugEnabled() ).thenReturn( false );
332 when( logger.isErrorEnabled() ).thenReturn( false );
333 doNothing().when( logger ).debug( anyString() );
334 doNothing().when( logger ).error( anyString(), any( Throwable.class ) );
335 when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) );
336 when( mojo.getTempDir() ).thenReturn( tmpDir );
337 when( mojo.getProjectBuildDirectory() ).thenReturn( targetDir );
338 when( mojo.createSurefireBootDirectoryInTemp() ).thenCallRealMethod();
339 when( mojo.createSurefireBootDirectoryInBuild() ).thenCallRealMethod();
340 when( mojo.getSurefireTempDir() ).thenCallRealMethod();
341
342 File bootDir = mojo.createSurefireBootDirectoryInTemp();
343 assertThat( bootDir ).isNotNull();
344 assertThat( bootDir ).isDirectory();
345
346 assertThat( new File( systemTmpDir, bootDir.getName() ) ).isDirectory();
347 assertThat( bootDir.getName() )
348 .startsWith( tmpDir );
349
350 File buildTmp = mojo.createSurefireBootDirectoryInBuild();
351 assertThat( buildTmp ).isNotNull();
352 assertThat( buildTmp ).isDirectory();
353 assertThat( buildTmp.getParentFile().getCanonicalFile().getParent() ).isEqualTo( usrDir );
354 assertThat( buildTmp.getName() ).isEqualTo( tmpDir );
355
356 File tmp = mojo.getSurefireTempDir();
357 assertThat( tmp ).isNotNull();
358 assertThat( tmp ).isDirectory();
359 assertThat( IS_OS_WINDOWS ? new File( systemTmpDir, bootDir.getName() ) : new File( targetDir, tmpDir ) )
360 .isDirectory();
361 }
362
363 public static class Mojo
364 extends AbstractSurefireMojo
365 {
366 @Override
367 protected String getPluginName()
368 {
369 return null;
370 }
371
372 @Override
373 protected int getRerunFailingTestsCount()
374 {
375 return 0;
376 }
377
378 @Override
379 public boolean isSkipTests()
380 {
381 return false;
382 }
383
384 @Override
385 public void setSkipTests( boolean skipTests )
386 {
387
388 }
389
390 @Override
391 public boolean isSkipExec()
392 {
393 return false;
394 }
395
396 @Override
397 public void setSkipExec( boolean skipExec )
398 {
399
400 }
401
402 @Override
403 public boolean isSkip()
404 {
405 return false;
406 }
407
408 @Override
409 public void setSkip( boolean skip )
410 {
411
412 }
413
414 @Override
415 public File getBasedir()
416 {
417 return null;
418 }
419
420 @Override
421 public void setBasedir( File basedir )
422 {
423
424 }
425
426 @Override
427 public File getTestClassesDirectory()
428 {
429 return null;
430 }
431
432 @Override
433 public void setTestClassesDirectory( File testClassesDirectory )
434 {
435
436 }
437
438 @Override
439 public File getClassesDirectory()
440 {
441 return null;
442 }
443
444 @Override
445 public void setClassesDirectory( File classesDirectory )
446 {
447
448 }
449
450 @Override
451 public File getReportsDirectory()
452 {
453 return null;
454 }
455
456 @Override
457 public void setReportsDirectory( File reportsDirectory )
458 {
459
460 }
461
462 @Override
463 public String getTest()
464 {
465 return null;
466 }
467
468 @Override
469 public void setTest( String test )
470 {
471
472 }
473
474 @Override
475 public List<String> getIncludes()
476 {
477 return null;
478 }
479
480 @Override
481 public File getIncludesFile()
482 {
483 return null;
484 }
485
486 @Override
487 public void setIncludes( List<String> includes )
488 {
489
490 }
491
492 @Override
493 public boolean isPrintSummary()
494 {
495 return false;
496 }
497
498 @Override
499 public void setPrintSummary( boolean printSummary )
500 {
501
502 }
503
504 @Override
505 public String getReportFormat()
506 {
507 return null;
508 }
509
510 @Override
511 public void setReportFormat( String reportFormat )
512 {
513
514 }
515
516 @Override
517 public boolean isUseFile()
518 {
519 return false;
520 }
521
522 @Override
523 public void setUseFile( boolean useFile )
524 {
525
526 }
527
528 @Override
529 public String getDebugForkedProcess()
530 {
531 return null;
532 }
533
534 @Override
535 public void setDebugForkedProcess( String debugForkedProcess )
536 {
537
538 }
539
540 @Override
541 public int getForkedProcessTimeoutInSeconds()
542 {
543 return 0;
544 }
545
546 @Override
547 public void setForkedProcessTimeoutInSeconds( int forkedProcessTimeoutInSeconds )
548 {
549
550 }
551
552 @Override
553 public int getForkedProcessExitTimeoutInSeconds()
554 {
555 return 0;
556 }
557
558 @Override
559 public void setForkedProcessExitTimeoutInSeconds( int forkedProcessTerminationTimeoutInSeconds )
560 {
561
562 }
563
564 @Override
565 public double getParallelTestsTimeoutInSeconds()
566 {
567 return 0;
568 }
569
570 @Override
571 public void setParallelTestsTimeoutInSeconds( double parallelTestsTimeoutInSeconds )
572 {
573
574 }
575
576 @Override
577 public double getParallelTestsTimeoutForcedInSeconds()
578 {
579 return 0;
580 }
581
582 @Override
583 public void setParallelTestsTimeoutForcedInSeconds( double parallelTestsTimeoutForcedInSeconds )
584 {
585
586 }
587
588 @Override
589 public boolean isUseSystemClassLoader()
590 {
591 return false;
592 }
593
594 @Override
595 public void setUseSystemClassLoader( boolean useSystemClassLoader )
596 {
597
598 }
599
600 @Override
601 public boolean isUseManifestOnlyJar()
602 {
603 return false;
604 }
605
606 @Override
607 public void setUseManifestOnlyJar( boolean useManifestOnlyJar )
608 {
609
610 }
611
612 @Override
613 public String getEncoding()
614 {
615 return null;
616 }
617
618 @Override
619 public void setEncoding( String encoding )
620 {
621
622 }
623
624 @Override
625 public Boolean getFailIfNoSpecifiedTests()
626 {
627 return null;
628 }
629
630 @Override
631 public void setFailIfNoSpecifiedTests( boolean failIfNoSpecifiedTests )
632 {
633
634 }
635
636 @Override
637 public int getSkipAfterFailureCount()
638 {
639 return 0;
640 }
641
642 @Override
643 public String getShutdown()
644 {
645 return null;
646 }
647
648 @Override
649 public File getExcludesFile()
650 {
651 return null;
652 }
653
654 @Override
655 protected List<File> suiteXmlFiles()
656 {
657 return null;
658 }
659
660 @Override
661 protected boolean hasSuiteXmlFiles()
662 {
663 return false;
664 }
665
666 @Override
667 public File[] getSuiteXmlFiles()
668 {
669 return new File[0];
670 }
671
672 @Override
673 public void setSuiteXmlFiles( File[] suiteXmlFiles )
674 {
675
676 }
677
678 @Override
679 public String getRunOrder()
680 {
681 return null;
682 }
683
684 @Override
685 public void setRunOrder( String runOrder )
686 {
687
688 }
689
690 @Override
691 protected void handleSummary( RunResult summary, Exception firstForkException )
692 {
693
694 }
695
696 @Override
697 protected boolean isSkipExecution()
698 {
699 return false;
700 }
701
702 @Override
703 protected String[] getDefaultIncludes()
704 {
705 return new String[0];
706 }
707
708 @Override
709 protected String getReportSchemaLocation()
710 {
711 return null;
712 }
713
714 @Override
715 protected boolean useModulePath()
716 {
717 return false;
718 }
719
720 @Override
721 protected void setUseModulePath( boolean useModulePath )
722 {
723
724 }
725
726 @Override
727 protected Artifact getMojoArtifact()
728 {
729 return null;
730 }
731 }
732
733 private static File mockFile( String absolutePath )
734 {
735 File f = mock( File.class );
736 when( f.getAbsolutePath() ).thenReturn( absolutePath );
737 return f;
738 }
739 }