This is an automated email from the ASF dual-hosted git repository. tibordigana pushed a commit to branch SUREFIRE-1534 in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit cfa69a0eace2e82e671446ecf71ba49a6d8ee196 Author: tibordigana <[email protected]> AuthorDate: Mon Jan 21 00:07:34 2019 +0100 [SUREFIRE-1534] ClassNotFoundException: org.apache.maven.plugin.surefire.StartupReportConfiguration using reuseForks set to false --- .../plugin/surefire/AbstractSurefireMojo.java | 8 +- .../AbstractSurefireMojoJava7PlusTest.java | 29 ++++-- .../ModularClasspathForkConfigurationTest.java | 3 +- .../surefire/booter/AbstractPathConfiguration.java | 20 +++-- .../booter/ModularClasspathConfiguration.java | 24 +++++ ...urefire1534ReuseForksFalseWithJavaModuleIT.java | 100 +++++++++++++++++++++ .../pom.xml | 62 +++++++++++++ .../src/main/java/it/Main.java | 17 ++++ .../src/main/java/module-info.java | 4 + .../src/test/java/it/MainTest.java | 29 ++++++ .../surefire/junitplatform/RunListenerAdapter.java | 15 +++- 11 files changed, 293 insertions(+), 18 deletions(-) diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java index c314fb4..b6bafc4 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java @@ -1845,8 +1845,12 @@ public abstract class AbstractSurefireMojo ModularClasspath modularClasspath = new ModularClasspath( moduleDescriptor, testModulepath.getClassPath(), packages, getTestClassesDirectory() ); + Artifact[] additionalInProcArtifacts = { getCommonArtifact(), getApiArtifact(), getLoggerApiArtifact() }; + Set<Artifact> inProcArtifacts = retainInProcArtifactsUnique( providerArtifacts, additionalInProcArtifacts ); + Classpath inProcClasspath = createInProcClasspath( providerClasspath, inProcArtifacts ); + ModularClasspathConfiguration classpathConfiguration = new ModularClasspathConfiguration( modularClasspath, - testClasspath, providerClasspath, effectiveIsEnableAssertions(), isChildDelegation() ); + testClasspath, providerClasspath, inProcClasspath, effectiveIsEnableAssertions(), isChildDelegation() ); getConsoleLogger().debug( testClasspath.getLogMessage( "test classpath:" ) ); getConsoleLogger().debug( testModulepath.getLogMessage( "test modulepath:" ) ); @@ -1854,6 +1858,8 @@ public abstract class AbstractSurefireMojo getConsoleLogger().debug( testClasspath.getCompactLogMessage( "test(compact) classpath:" ) ); getConsoleLogger().debug( testModulepath.getCompactLogMessage( "test(compact) modulepath:" ) ); getConsoleLogger().debug( providerClasspath.getCompactLogMessage( "provider(compact) classpath:" ) ); + getConsoleLogger().debug( inProcClasspath.getLogMessage( "in-process classpath:" ) ); + getConsoleLogger().debug( inProcClasspath.getCompactLogMessage( "in-process(compact) classpath:" ) ); return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration, isForking(), false ); diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java index 17cd930..0f9ee80 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoJava7PlusTest.java @@ -43,10 +43,7 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.io.File; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static java.util.Arrays.asList; import static java.util.Collections.singleton; @@ -154,6 +151,24 @@ public class AbstractSurefireMojoJava7PlusTest doNothing().when( logger ).debug( anyString() ); when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) ); + Artifact common = new DefaultArtifact( "org.apache.maven.surefire", "maven-surefire-common", v5, "runtime", + "jar", "", handler ); + common.setFile( mockFile( "maven-surefire-common.jar" ) ); + + Artifact api = new DefaultArtifact( "org.apache.maven.surefire", "surefire-api", v5, "runtime", + "jar", "", handler ); + api.setFile( mockFile( "surefire-api.jar" ) ); + + Artifact loggerApi = new DefaultArtifact( "org.apache.maven.surefire", "surefire-logger-api", v5, "runtime", + "jar", "", handler ); + loggerApi.setFile( mockFile( "surefire-logger-api.jar" ) ); + + Map<String, Artifact> artifacts = new HashMap<>(); + artifacts.put( "org.apache.maven.surefire:maven-surefire-common", common ); + artifacts.put( "org.apache.maven.surefire:surefire-api", api ); + artifacts.put( "org.apache.maven.surefire:surefire-logger-api", loggerApi ); + when( mojo.getPluginArtifactMap() ).thenReturn( artifacts ); + StartupConfiguration conf = invokeMethod( mojo, "newStartupConfigWithModularPath", classLoaderConfiguration, providerClasspath, "org.asf.Provider", moduleInfo, scanResult, "" ); @@ -178,14 +193,16 @@ public class AbstractSurefireMojoJava7PlusTest assertThat( argument2.getValue().getMessage() ) .isEqualTo( "low version" ); ArgumentCaptor<String> argument = ArgumentCaptor.forClass( String.class ); - verify( logger, times( 6 ) ).debug( argument.capture() ); + verify( logger, times( 8 ) ).debug( argument.capture() ); assertThat( argument.getAllValues() ) .containsExactly( "test classpath: non-modular.jar junit.jar hamcrest.jar", "test modulepath: modular.jar classes", "provider classpath: surefire-provider.jar", "test(compact) classpath: non-modular.jar junit.jar hamcrest.jar", "test(compact) modulepath: modular.jar classes", - "provider(compact) classpath: surefire-provider.jar" + "provider(compact) classpath: surefire-provider.jar", + "in-process classpath: surefire-provider.jar maven-surefire-common.jar surefire-api.jar surefire-logger-api.jar", + "in-process(compact) classpath: surefire-provider.jar maven-surefire-common.jar surefire-api.jar surefire-logger-api.jar" ); assertThat( conf ).isNotNull(); diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfigurationTest.java index d129df3..26410b5 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfigurationTest.java @@ -45,6 +45,7 @@ import static java.nio.file.Files.readAllLines; import static java.util.Arrays.asList; import static java.util.Collections.singleton; import static org.apache.maven.shared.utils.StringUtils.replace; +import static org.apache.maven.surefire.booter.Classpath.emptyClasspath; import static org.fest.assertions.Assertions.assertThat; /** @@ -146,7 +147,7 @@ public class ModularClasspathForkConfigurationTest Classpath surefireClasspathUrls = Classpath.emptyClasspath(); ModularClasspathConfiguration modularClasspathConfiguration = new ModularClasspathConfiguration( modularClasspath, testClasspathUrls, surefireClasspathUrls, - true, true ); + emptyClasspath(), true, true ); ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true ); StartupConfiguration startupConfiguration = new StartupConfiguration( "JUnitCoreProvider", modularClasspathConfiguration, clc, true, true ); diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/AbstractPathConfiguration.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/AbstractPathConfiguration.java index c9651ab..30d9a86 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/AbstractPathConfiguration.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/AbstractPathConfiguration.java @@ -21,7 +21,6 @@ package org.apache.maven.surefire.booter; import javax.annotation.Nonnull; -import static org.apache.maven.surefire.booter.Classpath.emptyClasspath; import static org.apache.maven.surefire.booter.Classpath.join; /** @@ -77,10 +76,7 @@ public abstract class AbstractPathConfiguration */ public abstract boolean isClassPathConfig(); - protected Classpath getInprocClasspath() - { - return emptyClasspath(); - } + protected abstract Classpath getInprocClasspath(); public <T extends AbstractPathConfiguration> T toRealPath( Class<T> type ) { @@ -95,8 +91,7 @@ public abstract class AbstractPathConfiguration public ClassLoader createMergedClassLoader() throws SurefireExecutionException { - return join( getInprocClasspath(), getTestClasspath() ) - .createClassLoader( isChildDelegation(), isEnableAssertions(), "test" ); + return createMergedClassLoader( getInprocTestClasspath() ); } public Classpath getProviderClasspath() @@ -114,4 +109,15 @@ public abstract class AbstractPathConfiguration { return childDelegation; } + + final Classpath getInprocTestClasspath() + { + return join( getInprocClasspath(), getTestClasspath() ); + } + + final ClassLoader createMergedClassLoader( Classpath cp ) + throws SurefireExecutionException + { + return cp.createClassLoader( isChildDelegation(), isEnableAssertions(), "test" ); + } } diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspathConfiguration.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspathConfiguration.java index 823b445..e19bd4f 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspathConfiguration.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspathConfiguration.java @@ -21,6 +21,10 @@ package org.apache.maven.surefire.booter; import javax.annotation.Nonnull; +import java.util.Collection; + +import static org.apache.maven.surefire.booter.Classpath.join; + /** * @author <a href="mailto:[email protected]">Tibor Digana (tibor17)</a> * @since 2.21.0.Jigsaw @@ -30,15 +34,22 @@ public class ModularClasspathConfiguration extends AbstractPathConfiguration private final ModularClasspath modularClasspath; private final Classpath testClasspathUrls; + /** + * The surefire classpath to use when invoking in-process with the plugin + */ + private final Classpath inprocClasspath; + public ModularClasspathConfiguration( @Nonnull ModularClasspath modularClasspath, @Nonnull Classpath testClasspathUrls, @Nonnull Classpath surefireClasspathUrls, + @Nonnull Classpath inprocClasspath, boolean enableAssertions, boolean childDelegation ) { super( surefireClasspathUrls, enableAssertions, childDelegation ); this.modularClasspath = modularClasspath; this.testClasspathUrls = testClasspathUrls; + this.inprocClasspath = inprocClasspath; } @Override @@ -63,4 +74,17 @@ public class ModularClasspathConfiguration extends AbstractPathConfiguration { return modularClasspath; } + + public ClassLoader createMergedClassLoader() + throws SurefireExecutionException + { + Collection<String> modulePath = getModularClasspath().getModulePath(); + return createMergedClassLoader( join( getInprocTestClasspath(), new Classpath( modulePath ) ) ); + } + + @Override + protected Classpath getInprocClasspath() + { + return inprocClasspath; + } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1534ReuseForksFalseWithJavaModuleIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1534ReuseForksFalseWithJavaModuleIT.java new file mode 100644 index 0000000..82dde97 --- /dev/null +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1534ReuseForksFalseWithJavaModuleIT.java @@ -0,0 +1,100 @@ +package org.apache.maven.surefire.its.jiras; + +/* + * 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 org.apache.maven.surefire.its.AbstractJigsawIT; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.TestFile; +import org.junit.Test; + +import java.io.IOException; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertTrue; + +public class Surefire1534ReuseForksFalseWithJavaModuleIT + extends AbstractJigsawIT +{ + + @Test + public void testExecuteWithReuseForksFalseWithJavaModule() + throws IOException + { + OutputValidator validator = assumeJigsaw() + .reuseForks( false ) + .forkCount( 1 ) + .executeTest(); + + validator.assertTestSuiteResults( 2, 0, 0, 0 ); + validator.verifyErrorFreeLog(); + + TestFile report = validator.getSurefireReportsFile( "TEST-MainTest.xml", UTF_8 ); + assertTrue( report.exists() ); + report.assertContainsText( "<property name=\"reuseForks\" value=\"false\"/>" ) + .assertContainsText( "<property name=\"forkCount\" value=\"1\"/>" ) + .assertContainsText( "<testcase name=\"test1\"" ) + .assertContainsText( "<testcase name=\"test2\"" ); + } + + @Test + public void testExecuteWithReuseForksFalseWithJavaModuleWithFilter() + throws IOException + { + OutputValidator validator = assumeJigsaw() + .reuseForks( false ) + .forkCount( 1 ) + .setTestToRun( "MainTest" ) + .executeTest(); + + validator.assertTestSuiteResults( 2, 0, 0, 0 ); + validator.verifyErrorFreeLog(); + + TestFile report = validator.getSurefireReportsFile( "TEST-MainTest.xml", UTF_8 ); + assertTrue( report.exists() ); + report.assertContainsText( "<property name=\"reuseForks\" value=\"false\"/>" ) + .assertContainsText( "<property name=\"forkCount\" value=\"1\"/>" ) + .assertContainsText( "<testcase name=\"test1\"" ) + .assertContainsText( "<testcase name=\"test2\"" ); + } + + @Test + public void testExecuteWithZeroForkCountWithJavaModule() + throws IOException + { + OutputValidator validator = assumeJigsaw() + .forkCount( 0 ) + .executeTest(); + + validator.assertTestSuiteResults( 2, 0, 0, 0 ); + validator.verifyErrorFreeLog(); + + TestFile report = validator.getSurefireReportsFile( "TEST-MainTest.xml", UTF_8 ); + assertTrue( report.exists() ); + report.assertContainsText( "<property name=\"forkCount\" value=\"0\"/>" ) + .assertContainsText( "<testcase name=\"test1\"" ) + .assertContainsText( "<testcase name=\"test2\"" ); + } + + @Override + protected String getProjectDirectoryName() + { + return "surefire-1534-reuse-forks-false-java-module"; + } +} diff --git a/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/pom.xml b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/pom.xml new file mode 100644 index 0000000..0b0ce25 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/pom.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <groupId>com.example</groupId> + <artifactId>surefire-1534</artifactId> + <version>1.0</version> + + <properties> + <maven.compiler.source>9</maven.compiler.source> + <maven.compiler.target>9</maven.compiler.target> + <junit.version>5.3.2</junit.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire.version}</version> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/main/java/it/Main.java b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/main/java/it/Main.java new file mode 100644 index 0000000..86491ff --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/main/java/it/Main.java @@ -0,0 +1,17 @@ +package it; + +public class Main +{ + private String id; + + public String getId() + { + return id; + } + + public void setId( String id ) + { + this.id = id; + } + +} diff --git a/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/main/java/module-info.java b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/main/java/module-info.java new file mode 100644 index 0000000..3df6ca9 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/main/java/module-info.java @@ -0,0 +1,4 @@ +module it +{ + exports it; +} diff --git a/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/test/java/it/MainTest.java b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/test/java/it/MainTest.java new file mode 100644 index 0000000..fbc0e07 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/src/test/java/it/MainTest.java @@ -0,0 +1,29 @@ +package it; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MainTest +{ + + // The intent is to run these two tests in different JVMs + + @Test + public void test1() + { + Main main = new Main(); + main.setId( "test1" ); + assertEquals( "test1", main.getId() ); + } + + @Test + public void test2() + { + Main main = new Main(); + main.setId( "test2" ); + assertEquals( "test2", main.getId() ); + } + +} + diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java index 85227f3..71c8bc0 100644 --- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java +++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java @@ -19,10 +19,13 @@ package org.apache.maven.surefire.junitplatform; * under the License. */ +import static java.util.Collections.emptyMap; import static org.apache.maven.surefire.report.SimpleReportEntry.ignored; +import static org.apache.maven.surefire.util.internal.ObjectUtils.systemProps; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -165,7 +168,7 @@ final class RunListenerAdapter private void completeTestSet( TestIdentifier testIdentifier ) { - runListener.testSetCompleted( createTestSetReportEntry( testIdentifier ) ); + runListener.testSetCompleted( createTestSetReportEntry( testIdentifier, systemProps() ) ); testSetNodes.remove( testIdentifier ); } @@ -185,8 +188,14 @@ final class RunListenerAdapter private SimpleReportEntry createTestSetReportEntry( TestIdentifier testIdentifier ) { - return new SimpleReportEntry( - JUnitPlatformProvider.class.getName(), testIdentifier.getLegacyReportingName() ); + return createTestSetReportEntry( testIdentifier, emptyMap() ); + } + + private SimpleReportEntry createTestSetReportEntry( TestIdentifier testIdentifier, + Map<String, String> systemProperties ) + { + return new SimpleReportEntry( JUnitPlatformProvider.class.getName(), + testIdentifier.getLegacyReportingName(), systemProperties ); } private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier )
