package org.apache.maven.plugin.nar; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.resolver.ArtifactResolver; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.apache.maven.surefire.booter.ForkConfiguration; import org.apache.maven.surefire.booter.SurefireBooter; import org.apache.maven.surefire.booter.SurefireBooterForkException; import org.apache.maven.surefire.booter.SurefireExecutionException; import org.apache.maven.surefire.report.BriefConsoleReporter; import org.apache.maven.surefire.report.BriefFileReporter; import org.apache.maven.surefire.report.ConsoleReporter; import org.apache.maven.surefire.report.DetailedConsoleReporter; import org.apache.maven.surefire.report.FileReporter; import org.apache.maven.surefire.report.ForkingConsoleReporter; import org.apache.maven.surefire.report.XMLReporter; import org.apache.maven.toolchain.Toolchain; import org.apache.maven.toolchain.ToolchainManager; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.util.StringUtils; // Copied from Maven maven-surefire-plugin 2.4.3 /** * Run integration tests using Surefire. This goal was copied from Maven's surefire plugin to accomodate a few things * for the NAR plugin: *
* 1. To test a jar file with its native module we can only run after the package phase, so we use the integration-test * phase. *
** 2. We need to set java.library.path to an AOL (architecture-os-linker) specific value, but AOL is only known in the * NAR plugin and thus cannot be set from the pom. *
** 3. To have the java.library.path definition picked up by java we need the "pertest" forkmode. To use this goal you * need to put the test sources in the regular test directories but disable the running of the tests by the * maven-surefire-plugin by setting maven.test.skip.exec to false in your pom. *
* * @author Jason van Zyl (modified by Mark Donszelmann, noted by DUNS) * @version $Id: SurefirePlugin.java 652773 2008-05-02 05:58:54Z dfabulich $ Mods by Duns for NAR * @requiresDependencyResolution test * @goal nar-integration-test * @phase integration-test */ // DUNS, changed class name, inheritance, goal and phase public class NarIntegrationTestMojo extends AbstractCompileMojo { // DUNS added test for JNI module private boolean testJNIModule() { for ( Iterator i = getLibraries().iterator(); i.hasNext(); ) { Library lib = (Library) i.next(); if ( lib.getType().equals( Library.JNI ) ) { return true; } } return false; } // DUNS added because of naming conflict /** * Skip running of NAR integration test plugin * * @parameter expression="${skipNar}" default-value="false" */ private boolean skipNar; // DUNS changed to nar. because of naming conflict /** * Set this to 'true' to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite * convenient on occasion. * * @parameter expression="${skipNarTests}" * @since 2.4 */ private boolean skipNarTests; // DUNS changed to nar. because of naming conflict /** * DEPRECATED This old parameter is just like skipTests, but bound to the old property maven.test.skip.exec. Use * -DskipTests instead; it's shorter. * * @deprecated * @parameter expression="${nar.test.skip.exec}" * @since 2.3 */ private boolean skipNarExec; // DUNS changed to nar. because of naming conflict /** * Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on * occasion. * * @parameter expression="${nar.test.failure.ignore}" */ private boolean testFailureIgnore; /** * The base directory of the project being tested. This can be obtained in your unit test by * System.getProperty("basedir"). * * @parameter expression="${basedir}" * @required */ private File basedir; /** * The directory containing generated test classes of the project being tested. * * @parameter expression="${project.build.testOutputDirectory}" * @required */ private File testClassesDirectory; /** * The directory containing generated classes of the project being tested. * * @parameter expression="${project.build.outputDirectory}" * @required */ private File classesDirectory; /** * The Maven Project Object * * @parameter expression="${project}" * @required * @readonly */ // DUNS, made private private MavenProject project; /** * The classpath elements of the project being tested. * * @parameter expression="${project.testClasspathElements}" * @required * @readonly */ private List classpathElements; /** * Additional elements to be appended to the classpath. * * @parameter * @since 2.4 */ private List additionalClasspathElements; /** * Base directory where all reports are written to. * * @parameter expression="${project.build.directory}/surefire-reports" */ private File reportsDirectory; /** * The test source directory containing test class sources. * * @parameter expression="${project.build.testSourceDirectory}" * @required * @since 2.2 */ private File testSourceDirectory; /** * Specify this parameter to run individual tests by file name, overriding theincludes/excludes
* parameters. Each pattern you specify here will be used to create an include pattern formatted like
* **/${test}.java
, so you can just type "-Dtest=MyTest" to run a single test called
* "foo/MyTest.java". This parameter will override the TestNG suiteXmlFiles parameter.
*
* @parameter expression="${test}"
*/
private String test;
/**
* List of patterns (separated by commas) used to specify the tests that should be included in testing. When not
* specified and when the test
parameter is not specified, the default includes will be
* **/Test*.java **/*Test.java **/*TestCase.java
. This parameter is ignored if TestNG
* suiteXmlFiles are specified.
*
* @parameter
*/
private List includes;
/**
* List of patterns (separated by commas) used to specify the tests that should be excluded in testing. When not
* specified and when the test
parameter is not specified, the default excludes will be
* **/*$*
(which excludes all inner classes). This parameter is ignored if TestNG suiteXmlFiles are
* specified.
*
* @parameter
*/
private List excludes;
/**
* ArtifactRepository of the localRepository. To obtain the directory of localRepository in unit tests use
* System.setProperty( "localRepository").
*
* @parameter expression="${localRepository}"
* @required
* @readonly
*/
// DUNS, removed, already in superclass
// private ArtifactRepository localRepository;
/**
* List of System properties to pass to the JUnit tests.
*
* @parameter
*/
private Properties systemProperties;
/**
* List of properties for configuring all TestNG related configurations. This is the new preferred method of
* configuring TestNG.
*
* @parameter
* @since 2.4
*/
private Properties properties;
/**
* Map of of plugin artifacts.
*
* @parameter expression="${plugin.artifactMap}"
* @required
* @readonly
*/
private Map pluginArtifactMap;
/**
* Map of of project artifacts.
*
* @parameter expression="${project.artifactMap}"
* @required
* @readonly
*/
private Map projectArtifactMap;
/**
* Option to print summary of test suites or just print the test cases that has errors.
*
* @parameter expression="${surefire.printSummary}" default-value="true"
*/
private boolean printSummary;
/**
* Selects the formatting for the test report to be generated. Can be set as brief or plain.
*
* @parameter expression="${surefire.reportFormat}" default-value="brief"
*/
private String reportFormat;
/**
* Option to generate a file test report or just output the test report to the console.
*
* @parameter expression="${surefire.useFile}" default-value="true"
*/
private boolean useFile;
// DUNS changed to nar. because of naming conflict
/**
* When forking, set this to true to redirect the unit test standard output to a file (found in
* reportsDirectory/testName-output.txt).
*
* @parameter expression="${nar.test.redirectTestOutputToFile}" default-value="false"
* @since 2.3
*/
private boolean redirectTestOutputToFile;
/**
* Set this to "true" to cause a failure if there are no tests to run. Defaults to false.
*
* @parameter expression="${failIfNoTests}"
* @since 2.4
*/
private Boolean failIfNoTests;
/**
* Option to specify the forking mode. Can be "never", "once" or "always". "none" and "pertest" are also accepted
* for backwards compatibility.
*
* @parameter expression="${forkMode}" default-value="once"
* @since 2.1
*/
private String forkMode;
/**
* Option to specify the jvm (or path to the java executable) to use with the forking options. For the default, the
* jvm will be the same as the one used to run Maven.
*
* @parameter expression="${jvm}"
* @since 2.1
*/
private String jvm;
/**
* Arbitrary JVM options to set on the command line.
*
* @parameter expression="${argLine}"
* @since 2.1
*/
private String argLine;
/**
* Attach a debugger to the forked JVM. If set to "true", the process will suspend and wait for a debugger to attach
* on port 5005. If set to some other string, that string will be appended to the argLine, allowing you to configure
* arbitrary debuggability options (without overwriting the other options specified in the argLine).
*
* @parameter expression="${maven.surefire.debug}"
* @since 2.4
*/
private String debugForkedProcess;
/**
* Kill the forked test process after a certain number of seconds. If set to 0, wait forever for the process, never
* timing out.
*
* @parameter expression="${surefire.timeout}"
* @since 2.4
*/
private int forkedProcessTimeoutInSeconds;
/**
* Additional environments to set on the command line.
*
* @parameter
* @since 2.1.3
*/
private Map environmentVariables = new HashMap();
/**
* Command line working directory.
*
* @parameter expression="${basedir}"
* @since 2.1.3
*/
private File workingDirectory;
/**
* When false it makes tests run using the standard classloader delegation instead of the default Maven isolated
* classloader. Only used when forking (forkMode is not "none").junit:junit
will be used.
*
* @parameter expression="${junitArtifactName}" default-value="junit:junit"
* @since 2.3.1
*/
private String junitArtifactName;
/**
* Allows you to specify the name of the TestNG artifact. If not set, org.testng:testng
will be used.
*
* @parameter expression="${testNGArtifactName}" default-value="org.testng:testng"
* @since 2.3.1
*/
private String testNGArtifactName;
/**
* (TestNG only) The attribute thread-count allows you to specify how many threads should be allocated for this
* execution. Only makes sense to use in conjunction with parallel.
*
* @parameter expression="${threadCount}"
* @since 2.2
*/
private int threadCount;
/**
* (TestNG only) When you use the parallel attribute, TestNG will try to run all your test methods in separate
* threads, except for methods that depend on each other, which will be run in the same thread in order to respect
* their order of execution.
*
* @parameter expression="${parallel}"
* @todo test how this works with forking, and console/file output parallelism
* @since 2.2
*/
private String parallel;
/**
* Whether to trim the stack trace in the reports to just the lines within the test, or show the full trace.
*
* @parameter expression="${trimStackTrace}" default-value="true"
* @since 2.2
*/
private boolean trimStackTrace;
/**
* Resolves the artifacts needed.
*
* @component
*/
private ArtifactResolver artifactResolver;
/**
* Creates the artifact
*
* @component
*/
private ArtifactFactory artifactFactory;
/**
* The plugin remote repositories declared in the pom.
*
* @parameter expression="${project.pluginArtifactRepositories}"
* @since 2.2
*/
private List remoteRepositories;
/**
* For retrieval of artifact's metadata.
*
* @component
*/
private ArtifactMetadataSource metadataSource;
private static final String BRIEF_REPORT_FORMAT = "brief";
private static final String PLAIN_REPORT_FORMAT = "plain";
private Properties originalSystemProperties;
/**
* Flag to disable the generation of report files in xml format.
*
* @parameter expression="${disableXmlReport}" default-value="false"
* @since 2.2
*/
private boolean disableXmlReport;
/**
* Option to pass dependencies to the system's classloader instead of using an isolated class loader when forking.
* Prevents problems with JDKs which implement the service provider lookup mechanism by using the system's
* classloader. Default value is "true".
*
* @parameter expression="${surefire.useSystemClassLoader}"
* @since 2.3
*/
private Boolean useSystemClassLoader;
/**
* By default, Surefire forks your tests using a manifest-only jar; set this parameter to "false" to force it to
* launch your tests with a plain old Java classpath. (See
* http://maven.apache.org/plugins/maven-surefire-plugin/examples/class-loading.html for a more detailed explanation
* of manifest-only jars and their benefits.) Default value is "true". Beware, setting this to "false" may cause
* your tests to fail on Windows if your classpath is too long.
*
* @parameter expression="${surefire.useManifestOnlyJar}" default-value="true"
* @since 2.4.3
*/
private boolean useManifestOnlyJar;
/**
* By default, Surefire enables JVM assertions for the execution of your test cases. To disable the assertions, set
* this flag to false
.
*
* @parameter expression="${enableAssertions}" default-value="true"
* @since 2.3.1
*/
private boolean enableAssertions;
/**
* The current build session instance.
*
* @parameter expression="${session}"
* @required
* @readonly
*/
private MavenSession session;
// DUNS, changed name
public void narExecute()
throws MojoExecutionException, MojoFailureException
{
if ( verifyParameters() )
{
SurefireBooter surefireBooter = constructSurefireBooter();
getLog().info( "Surefire report directory: " + reportsDirectory );
int result;
try
{
result = surefireBooter.run();
}
catch ( SurefireBooterForkException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
catch ( SurefireExecutionException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
if ( originalSystemProperties != null && !surefireBooter.isForking() )
{
// restore system properties, only makes sense when not forking..
System.setProperties( originalSystemProperties );
}
if ( result == 0 )
{
return;
}
String msg;
if ( result == SurefireBooter.NO_TESTS_EXIT_CODE )
{
if ( ( failIfNoTests == null ) || !failIfNoTests.booleanValue() )
{
return;
}
// TODO: i18n
throw new MojoFailureException(
"No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)" );
}
else
{
// TODO: i18n
msg =
"There are test failures.\n\nPlease refer to " + reportsDirectory
+ " for the individual test results.";
}
if ( testFailureIgnore )
{
getLog().error( msg );
}
else
{
throw new MojoFailureException( msg );
}
}
}
private boolean verifyParameters()
throws MojoFailureException
{
// DUNS
if ( skipNar || skipNarTests || skipNarExec )
{
getLog().info( "Tests are skipped." );
return false;
}
if ( !testClassesDirectory.exists() )
{
if ( failIfNoTests != null && failIfNoTests.booleanValue() )
{
throw new MojoFailureException( "No tests to run!" );
}
getLog().info( "No tests to run." );
return false;
}
if ( useSystemClassLoader != null && ForkConfiguration.FORK_NEVER.equals( forkMode ) )
{
getLog().warn( "useSystemClassloader setting has no effect when not forking" );
}
return true;
}
/**
* Converts old TestNG configuration parameters over to new properties based configuration method. (if any are
* defined the old way)
*/
private void convertTestNGParameters()
{
if ( properties == null )
{
properties = new Properties();
}
if ( this.parallel != null )
{
properties.setProperty( "parallel", this.parallel );
}
if ( this.excludedGroups != null )
{
properties.setProperty( "excludegroups", this.excludedGroups );
}
if ( this.groups != null )
{
properties.setProperty( "groups", this.groups );
}
if ( this.threadCount > 0 )
{
properties.setProperty( "threadcount", new Integer( this.threadCount ).toString() );
}
}
private SurefireBooter constructSurefireBooter()
throws MojoExecutionException, MojoFailureException
{
SurefireBooter surefireBooter = new SurefireBooter();
Artifact surefireArtifact = (Artifact) pluginArtifactMap.get( "org.apache.maven.surefire:surefire-booter" );
if ( surefireArtifact == null )
{
throw new MojoExecutionException( "Unable to locate surefire-booter in the list of plugin artifacts" );
}
surefireArtifact.isSnapshot(); // TODO: this is ridiculous, but it fixes getBaseVersion to be -SNAPSHOT if
// needed
Artifact junitArtifact;
Artifact testNgArtifact;
try
{
addArtifact( surefireBooter, surefireArtifact );
junitArtifact = (Artifact) projectArtifactMap.get( junitArtifactName );
// SUREFIRE-378, junit can have an alternate artifact name
if ( junitArtifact == null && "junit:junit".equals( junitArtifactName ) )
{
junitArtifact = (Artifact) projectArtifactMap.get( "junit:junit-dep" );
}
// TODO: this is pretty manual, but I'd rather not require the plugin > dependencies section right now
testNgArtifact = (Artifact) projectArtifactMap.get( testNGArtifactName );
if ( testNgArtifact != null )
{
VersionRange range = VersionRange.createFromVersionSpec( "[4.7,)" );
if ( !range.containsVersion( new DefaultArtifactVersion( testNgArtifact.getVersion() ) ) )
{
throw new MojoFailureException(
"TestNG support requires version 4.7 or above. You have declared version "
+ testNgArtifact.getVersion() );
}
convertTestNGParameters();
if ( this.testClassesDirectory != null )
{
properties.setProperty( "testng.test.classpath", testClassesDirectory.getAbsolutePath() );
}
addArtifact( surefireBooter, testNgArtifact );
// The plugin uses a JDK based profile to select the right testng. We might be explicity using a
// different one since its based on the source level, not the JVM. Prune using the filter.
addProvider( surefireBooter, "surefire-testng", surefireArtifact.getBaseVersion(), testNgArtifact );
}
else if ( junitArtifact != null && junitArtifact.getBaseVersion().startsWith( "4" ) )
{
addProvider( surefireBooter, "surefire-junit4", surefireArtifact.getBaseVersion(), null );
}
else
{
// add the JUnit provider as default - it doesn't require JUnit to be present,
// since it supports POJO tests.
addProvider( surefireBooter, "surefire-junit", surefireArtifact.getBaseVersion(), null );
}
}
catch ( ArtifactNotFoundException e )
{
throw new MojoExecutionException( "Unable to locate required surefire provider dependency: "
+ e.getMessage(), e );
}
catch ( InvalidVersionSpecificationException e )
{
throw new MojoExecutionException( "Error determining the TestNG version requested: " + e.getMessage(), e );
}
catch ( ArtifactResolutionException e )
{
throw new MojoExecutionException( "Error to resolving surefire provider dependency: " + e.getMessage(), e );
}
if ( suiteXmlFiles != null && suiteXmlFiles.length > 0 && test == null )
{
if ( testNgArtifact == null )
{
throw new MojoExecutionException( "suiteXmlFiles is configured, but there is no TestNG dependency" );
}
// TODO: properties should be passed in here too
surefireBooter.addTestSuite( "org.apache.maven.surefire.testng.TestNGXmlTestSuite", new Object[] {
suiteXmlFiles, testSourceDirectory.getAbsolutePath(), testNgArtifact.getVersion(),
testNgArtifact.getClassifier(), properties, reportsDirectory } );
}
else
{
List includeList;
List excludeList;
if ( test != null )
{
// Check to see if we are running a single test. The raw parameter will
// come through if it has not been set.
// FooTest -> **/FooTest.java
includeList = new ArrayList();
excludeList = new ArrayList();
if ( failIfNoTests == null )
{
failIfNoTests = Boolean.TRUE;
}
String[] testRegexes = StringUtils.split( test, "," );
for ( int i = 0; i < testRegexes.length; i++ )
{
String testRegex = testRegexes[i];
if ( testRegex.endsWith( ".java" ) )
{
testRegex = testRegex.substring( 0, testRegex.length() - 5 );
}
// Allow paths delimited by '.' or '/'
testRegex = testRegex.replace( '.', '/' );
includeList.add( "**/" + testRegex + ".java" );
}
}
else
{
includeList = this.includes;
excludeList = this.excludes;
// defaults here, qdox doesn't like the end javadoc value
// Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason
if ( includeList == null || includeList.size() == 0 )
{
includeList =
new ArrayList( Arrays.asList( new String[] { "**/Test*.java", "**/*Test.java",
"**/*TestCase.java" } ) );
}
if ( excludeList == null || excludeList.size() == 0 )
{
excludeList = new ArrayList( Arrays.asList( new String[] { "**/*$*" } ) );
}
}
if ( testNgArtifact != null )
{
surefireBooter.addTestSuite( "org.apache.maven.surefire.testng.TestNGDirectoryTestSuite", new Object[] {
testClassesDirectory, includeList, excludeList, testSourceDirectory.getAbsolutePath(),
testNgArtifact.getVersion(), testNgArtifact.getClassifier(), properties, reportsDirectory } );
}
else
{
String junitDirectoryTestSuite;
if ( junitArtifact != null && junitArtifact.getBaseVersion() != null
&& junitArtifact.getBaseVersion().startsWith( "4" ) )
{
junitDirectoryTestSuite = "org.apache.maven.surefire.junit4.JUnit4DirectoryTestSuite";
}
else
{
junitDirectoryTestSuite = "org.apache.maven.surefire.junit.JUnitDirectoryTestSuite";
}
// fall back to JUnit, which also contains POJO support. Also it can run
// classes compiled against JUnit since it has a dependency on JUnit itself.
surefireBooter.addTestSuite( junitDirectoryTestSuite, new Object[] { testClassesDirectory, includeList,
excludeList } );
}
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
getLog().debug( "Test Classpath :" );
// Check if we need to add configured classes/test classes directories here.
// If they are configured, we should remove the default to avoid conflicts.
if ( !project.getBuild().getOutputDirectory().equals( classesDirectory.getAbsolutePath() ) )
{
classpathElements.remove( project.getBuild().getOutputDirectory() );
classpathElements.add( classesDirectory.getAbsolutePath() );
}
if ( !project.getBuild().getTestOutputDirectory().equals( testClassesDirectory.getAbsolutePath() ) )
{
classpathElements.remove( project.getBuild().getTestOutputDirectory() );
classpathElements.add( testClassesDirectory.getAbsolutePath() );
}
for ( Iterator i = classpathElements.iterator(); i.hasNext(); )
{
String classpathElement = (String) i.next();
getLog().debug( " " + classpathElement );
surefireBooter.addClassPathUrl( classpathElement );
}
Toolchain tc = getToolchain();
if ( tc != null )
{
getLog().info( "Toolchain in surefire-plugin: " + tc );
if ( ForkConfiguration.FORK_NEVER.equals( forkMode ) )
{
forkMode = ForkConfiguration.FORK_ONCE;
}
if ( jvm != null )
{
getLog().warn( "Toolchains are ignored, 'executable' parameter is set to " + jvm );
}
else
{
jvm = tc.findTool( "java" ); // NOI18N
}
}
if ( additionalClasspathElements != null )
{
for ( Iterator i = additionalClasspathElements.iterator(); i.hasNext(); )
{
String classpathElement = (String) i.next();
getLog().debug( " " + classpathElement );
surefireBooter.addClassPathUrl( classpathElement );
}
}
// ----------------------------------------------------------------------
// Forking
// ----------------------------------------------------------------------
ForkConfiguration fork = new ForkConfiguration();
// DUNS
if ( project.getPackaging().equals( "nar" ) || ( getNarManager().getNarDependencies( "test" ).size() > 0 ) )
{
forkMode = "pertest";
}
fork.setForkMode( forkMode );
processSystemProperties( !fork.isForking() );
if ( getLog().isDebugEnabled() )
{
showMap( systemProperties, "system property" );
}
if ( fork.isForking() )
{
useSystemClassLoader = useSystemClassLoader == null ? Boolean.TRUE : useSystemClassLoader;
fork.setUseSystemClassLoader( useSystemClassLoader.booleanValue() );
fork.setUseManifestOnlyJar( useManifestOnlyJar );
fork.setSystemProperties( systemProperties );
if ( "true".equals( debugForkedProcess ) )
{
debugForkedProcess =
"-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005";
}
fork.setDebugLine( debugForkedProcess );
if ( jvm == null || "".equals( jvm ) )
{
// use the same JVM as the one used to run Maven (the "java.home" one)
jvm = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
getLog().debug( "Using JVM: " + jvm );
}
fork.setJvmExecutable( jvm );
if ( workingDirectory != null )
{
fork.setWorkingDirectory( workingDirectory );
}
else
{
fork.setWorkingDirectory( basedir );
}
// BEGINDUNS
if ( argLine == null )
{
argLine = "";
}
StringBuffer javaLibraryPath = new StringBuffer();
if ( testJNIModule() )
{
// Add libraries to java.library.path for testing
File jniLibraryPathEntry =
getLayout().getLibDirectory( getTargetDirectory(), getMavenProject().getArtifactId(),
getMavenProject().getVersion(), getAOL().toString(), Library.JNI );
if ( jniLibraryPathEntry.exists() )
{
getLog().debug( "Adding library directory to java.library.path: " + jniLibraryPathEntry );
if ( javaLibraryPath.length() > 0 )
{
javaLibraryPath.append( File.pathSeparator );
}
javaLibraryPath.append( jniLibraryPathEntry );
}
File sharedLibraryPathEntry =
getLayout().getLibDirectory( getTargetDirectory(), getMavenProject().getArtifactId(),
getMavenProject().getVersion(), getAOL().toString(), Library.SHARED );
if ( sharedLibraryPathEntry.exists() )
{
getLog().debug( "Adding library directory to java.library.path: " + sharedLibraryPathEntry );
if ( javaLibraryPath.length() > 0 )
{
javaLibraryPath.append( File.pathSeparator );
}
javaLibraryPath.append( sharedLibraryPathEntry );
}
// add jar file to classpath, as one may want to read a
// properties file for artifactId and version
String narFile = "target/" + project.getArtifactId() + "-" + project.getVersion() + ".jar";
getLog().debug( "Adding to surefire test classpath: " + narFile );
surefireBooter.addClassPathUrl( narFile );
}
List dependencies = getNarManager().getNarDependencies( "test" );
for ( Iterator i = dependencies.iterator(); i.hasNext(); )
{
NarArtifact dependency = (NarArtifact) i.next();
// FIXME this should be overridable
// NarInfo info = dependency.getNarInfo();
// String binding = info.getBinding(getAOL(), Library.STATIC);
// NOTE: fixed to shared, jni
String[] bindings = { Library.SHARED, Library.JNI };
for ( int j = 0; j < bindings.length; j++ )
{
String binding = bindings[j];
if ( !binding.equals( Library.STATIC ) )
{
File depLibPathEntry =
getLayout().getLibDirectory( getUnpackDirectory(), dependency.getArtifactId(),
dependency.getVersion(), getAOL().toString(), binding );
if ( depLibPathEntry.exists() )
{
getLog().debug( "Adding dependency directory to java.library.path: " + depLibPathEntry );
if ( javaLibraryPath.length() > 0 )
{
javaLibraryPath.append( File.pathSeparator );
}
javaLibraryPath.append( depLibPathEntry );
}
}
}
}
// add final javalibrary path
if ( javaLibraryPath.length() > 0 )
{
// NOTE java.library.path only works for the jni lib itself, and
// not for its dependent shareables.
// NOTE: java.library.path does not work with arguments with
// spaces as
// SureFireBooter splits the line in parts and then quotes
// it wrongly
NarUtil.addLibraryPathToEnv( javaLibraryPath.toString(), environmentVariables, getOS() );
}
// necessary to find WinSxS
if ( getOS().equals( OS.WINDOWS ) )
{
environmentVariables.put( "SystemRoot", NarUtil.getEnv( "SystemRoot", "SystemRoot", "C:\\Windows" ) );
}
// ENDDUNS
fork.setArgLine( argLine );
fork.setEnvironmentVariables( environmentVariables );
if ( getLog().isDebugEnabled() )
{
showMap( environmentVariables, "environment variable" );
fork.setDebug( true );
}
if ( argLine != null )
{
List args = Arrays.asList( argLine.split( " " ) );
if ( args.contains( "-da" ) || args.contains( "-disableassertions" ) )
{
enableAssertions = false;
}
}
}
surefireBooter.setFailIfNoTests( failIfNoTests == null ? false : failIfNoTests.booleanValue() );
surefireBooter.setForkedProcessTimeoutInSeconds( forkedProcessTimeoutInSeconds );
surefireBooter.setRedirectTestOutputToFile( redirectTestOutputToFile );
surefireBooter.setForkConfiguration( fork );
surefireBooter.setChildDelegation( childDelegation );
surefireBooter.setEnableAssertions( enableAssertions );
surefireBooter.setReportsDirectory( reportsDirectory );
addReporters( surefireBooter, fork.isForking() );
return surefireBooter;
}
private void showMap( Map map, String setting )
{
for ( Iterator i = map.keySet().iterator(); i.hasNext(); )
{
String key = (String) i.next();
String value = (String) map.get( key );
getLog().debug( "Setting " + setting + " [" + key + "]=[" + value + "]" );
}
}
private void addProvider( SurefireBooter surefireBooter, String provider, String version, Artifact filteredArtifact )
throws ArtifactNotFoundException, ArtifactResolutionException
{
Artifact providerArtifact =
artifactFactory.createDependencyArtifact( "org.apache.maven.surefire", provider,
VersionRange.createFromVersion( version ), "jar", null,
Artifact.SCOPE_TEST );
ArtifactResolutionResult result = resolveArtifact( filteredArtifact, providerArtifact );
for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
{
Artifact artifact = (Artifact) i.next();
getLog().debug( "Adding to surefire test classpath: " + artifact.getFile().getAbsolutePath() );
surefireBooter.addSurefireClassPathUrl( artifact.getFile().getAbsolutePath() );
}
}
private ArtifactResolutionResult resolveArtifact( Artifact filteredArtifact, Artifact providerArtifact )
throws ArtifactResolutionException, ArtifactNotFoundException
{
ArtifactFilter filter = null;
if ( filteredArtifact != null )
{
filter =
new ExcludesArtifactFilter( Collections.singletonList( filteredArtifact.getGroupId() + ":"
+ filteredArtifact.getArtifactId() ) );
}
Artifact originatingArtifact = artifactFactory.createBuildArtifact( "dummy", "dummy", "1.0", "jar" );
// DUNS, use access method rather than "localRepository" field.
return artifactResolver.resolveTransitively( Collections.singleton( providerArtifact ), originatingArtifact,
getLocalRepository(), remoteRepositories, metadataSource, filter );
}
private void addArtifact( SurefireBooter surefireBooter, Artifact surefireArtifact )
throws ArtifactNotFoundException, ArtifactResolutionException
{
ArtifactResolutionResult result = resolveArtifact( null, surefireArtifact );
for ( Iterator i = result.getArtifacts().iterator(); i.hasNext(); )
{
Artifact artifact = (Artifact) i.next();
getLog().debug( "Adding to surefire booter test classpath: " + artifact.getFile().getAbsolutePath() );
surefireBooter.addSurefireBootClassPathUrl( artifact.getFile().getAbsolutePath() );
}
}
protected void processSystemProperties( boolean setInSystem )
{
if ( systemProperties == null )
{
systemProperties = new Properties();
}
originalSystemProperties = (Properties) System.getProperties().clone();
// We used to take all of our system properties and dump them in with the
// user specified properties for SUREFIRE-121, causing SUREFIRE-491.
// Not gonna do THAT any more... but I'm leaving this code here in case
// we need it later when we try to fix SUREFIRE-121 again.
// Get the properties from the MavenSession instance to make embedded use work correctly
Properties userSpecifiedProperties = (Properties) session.getExecutionProperties().clone();
userSpecifiedProperties.putAll( systemProperties );
// systemProperties = userSpecifiedProperties;
systemProperties.setProperty( "basedir", basedir.getAbsolutePath() );
systemProperties.setProperty( "user.dir", workingDirectory.getAbsolutePath() );
// DUNS, use access method rather than "localRepository" field.
systemProperties.setProperty( "localRepository", getLocalRepository().getBasedir() );
if ( setInSystem )
{
// Add all system properties configured by the user
Iterator iter = systemProperties.keySet().iterator();
while ( iter.hasNext() )
{
String key = (String) iter.next();
String value = systemProperties.getProperty( key );
System.setProperty( key, value );
}
}
}
/**
* * Adds Reporters that will generate reports with different formatting. *
* The Reporter that will be added will be based on the value of the parameter useFile, reportFormat, and * printSummary. * * @param surefireBooter The surefire booter that will run tests. * @param forking */ private void addReporters( SurefireBooter surefireBooter, boolean forking ) { Boolean trimStackTrace = Boolean.valueOf( this.trimStackTrace ); if ( useFile ) { if ( printSummary ) { if ( forking ) { surefireBooter.addReport( ForkingConsoleReporter.class.getName(), new Object[] { trimStackTrace } ); } else { surefireBooter.addReport( ConsoleReporter.class.getName(), new Object[] { trimStackTrace } ); } } if ( BRIEF_REPORT_FORMAT.equals( reportFormat ) ) { surefireBooter.addReport( BriefFileReporter.class.getName(), new Object[] { reportsDirectory, trimStackTrace } ); } else if ( PLAIN_REPORT_FORMAT.equals( reportFormat ) ) { surefireBooter.addReport( FileReporter.class.getName(), new Object[] { reportsDirectory, trimStackTrace } ); } } else { if ( BRIEF_REPORT_FORMAT.equals( reportFormat ) ) { surefireBooter.addReport( BriefConsoleReporter.class.getName(), new Object[] { trimStackTrace } ); } else if ( PLAIN_REPORT_FORMAT.equals( reportFormat ) ) { surefireBooter.addReport( DetailedConsoleReporter.class.getName(), new Object[] { trimStackTrace } ); } } if ( !disableXmlReport ) { surefireBooter.addReport( XMLReporter.class.getName(), new Object[] { reportsDirectory, trimStackTrace } ); } } /** * @return SurefirePlugin Returns the skipExec. */ public boolean isSkipExec() { return this.skipNarTests; } /** * @param skipExec the skipExec to set */ public void setSkipExec( boolean skipExec ) { this.skipNarTests = skipExec; } // TODO remove the part with ToolchainManager lookup once we depend on // 3.0.9 (have it as prerequisite). Define as regular component field then. private Toolchain getToolchain() { Toolchain tc = null; try { if ( session != null ) // session is null in tests.. { ToolchainManager toolchainManager = (ToolchainManager) session.getContainer().lookup( ToolchainManager.ROLE ); if ( toolchainManager != null ) { tc = toolchainManager.getToolchainFromBuildContext( "jdk", session ); } } } catch ( ComponentLookupException componentLookupException ) { // just ignore, could happen in pre-3.0.9 builds.. } return tc; } }