diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000000..1d0168b20b --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,42 @@ +# 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. + +name: Java CI + +on: [push, pull_request] + +jobs: + build: + + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + fail-fast: false + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + + - name: Build with Maven + run: mvn install -e -B -V -nsu --no-transfer-progress -P run-its diff --git a/.gitignore b/.gitignore index 19e9e0bbd0..33eba3dec3 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ build .classpath .project .settings +.checkstyle .idea .surefire-* .DS_Store diff --git a/.travis.yml b/.travis.yml index c9c877a296..e8496ba89d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,31 @@ +# 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. + language: java -jdk: - - oraclejdk8 -# - oraclejdk9 +sudo: false -script: "rm -rf .repository && mvn --show-version --errors --batch-mode -Prun-its clean install -Dmaven.repo.local=.repository -Denforcer.skip=true -e" +cache: + directories: + - "$HOME/.m2" install: true +jdk: openjdk8 +script: mvn clean install -e -B -V -nsu -P run-its -DskipITs -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn branches: - except: - - gh-pages + only: + - master diff --git a/Jenkinsfile b/Jenkinsfile index 5166d0fb5f..1811100fb5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -21,21 +21,23 @@ properties( [ - buildDiscarder(logRotator(artifactDaysToKeepStr: env.BRANCH_NAME == 'master' ? '30' : '7', - artifactNumToKeepStr: '10', - daysToKeepStr: env.BRANCH_NAME == 'master' ? '30' : '7', - numToKeepStr: '10') + buildDiscarder(logRotator(artifactDaysToKeepStr: env.BRANCH_NAME == 'master' ? '1' : '2', + artifactNumToKeepStr: '50', + daysToKeepStr: env.BRANCH_NAME == 'master' ? '10' : '5', + numToKeepStr: env.BRANCH_NAME == 'master' ? '5' : '3') ), disableConcurrentBuilds() ] ) -final def oses = ['linux':'ubuntu && !H24', 'windows':'Windows'] -final def mavens = env.BRANCH_NAME == 'master' ? ['3.5.x', '3.3.x', '3.2.x'] : ['3.5.x'] -final def jdks = [12, 11, 8, 7] +final def oses = ['linux':'ubuntu && !H31', 'windows':'Windows'] +final def mavens = env.BRANCH_NAME == 'master' ? ['3.6.x', '3.2.x'] : ['3.6.x'] +// all non-EOL versions and the first EA +final def jdks = [14, 13, 11, 8, 7] final def options = ['-e', '-V', '-B', '-nsu', '-P', 'run-its'] -final def goals = ['clean', 'install', 'jacoco:report'] +final def goals = ['clean', 'install'] +final def goalsDepl = ['clean', 'deploy', 'jacoco:report'] final Map stages = [:] oses.eachWithIndex { osMapping, indexOfOs -> @@ -50,31 +52,30 @@ oses.eachWithIndex { osMapping, indexOfOs -> // Referenses for TLS: // https://central.sonatype.org/articles/2018/May/04/discontinued-support-for-tlsv11-and-below/?__hstc=31049440.ab2fd229e7f8b6176196d9f78621e1f5.1534324377408.1534324377408.1534324377408.1&__hssc=31049440.1.1534324377409&__hsfp=2729160845 - def mavenOpts = '-server -XX:+UseG1GC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:+UseNUMA -Xms64m -Djava.awt.headless=true -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2' + def mavenOpts = '-server -XX:+UseG1GC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:+UseNUMA -Xms64m -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn' mavenOpts += (os == 'linux' ? ' -Xmx1g' : ' -Xmx256m') if (label == null || jdkTestName == null || mvnName == null) { println "Skipping ${stageKey} as unsupported by Jenkins Environment." - return; + return } println "${stageKey} ==> Label: ${label}, JDK: ${jdkTestName}, Maven: ${mvnName}." stages[stageKey] = { node(label) { - if (os == 'windows' && jdk == 12) { - // https://issues.apache.org/jira/browse/INFRA-17384 - return - } timestamps { - def boolean makeReports = indexOfOs == 0 && indexOfMaven == 0 && indexOfJdk == 0 + boolean first = indexOfOs == 0 && indexOfMaven == 0 && indexOfJdk == 0 def failsafeItPort = 8000 + 100 * indexOfMaven + 10 * indexOfJdk - def allOptions = options + ["-Dfailsafe-integration-test-port=${failsafeItPort}", "-Dfailsafe-integration-test-stop-port=${1 + failsafeItPort}"] - if (jdk > 7) { - allOptions += ['-DpowermockVersion=2.0.0-RC.4', '-Denforcer.skip=true'] + def allOptions = options + ['-Djava.awt.headless=true', "-Dfailsafe-integration-test-port=${failsafeItPort}", "-Dfailsafe-integration-test-stop-port=${1 + failsafeItPort}"] + if (jdk == 7) { + allOptions += '-Dhttps.protocols=TLSv1.2' + } + if (!maven.startsWith('3.2') && !maven.startsWith('3.3') && !maven.startsWith('3.5')) { + allOptions += '--no-transfer-progress' } ws(dir: "${os == 'windows' ? "${TEMP}\\${BUILD_TAG}" : pwd()}") { - buildProcess(stageKey, jdkName, jdkTestName, mvnName, goals, allOptions, mavenOpts, makeReports) + buildProcess(stageKey, jdkName, jdkTestName, mvnName, first ? goalsDepl : goals, allOptions, mavenOpts, first) } } } @@ -114,16 +115,13 @@ timeout(time: 12, unit: 'HOURS') { currentBuild.result = 'FAILURE' throw e } finally { - stage("notifications") { - jenkinsNotify() - } + jenkinsNotify() } } def buildProcess(String stageKey, String jdkName, String jdkTestName, String mvnName, goals, options, mavenOpts, boolean makeReports) { - cleanWs() try { - def mvnLocalRepoDir = null + def mvnLocalRepoDir if (isUnix()) { sh 'mkdir -p .m2' mvnLocalRepoDir = "${pwd()}/.m2" @@ -140,7 +138,7 @@ def buildProcess(String stageKey, String jdkName, String jdkTestName, String mvn } def properties = ["-Djacoco.skip=${!makeReports}", "\"-Dmaven.repo.local=${mvnLocalRepoDir}\""] - println "Setting JDK for testing ${jdkName}" + println "Setting JDK for testing ${jdkTestName}" def cmd = ['mvn'] + goals + options + properties stage("build ${stageKey}") { @@ -150,9 +148,11 @@ def buildProcess(String stageKey, String jdkName, String jdkTestName, String mvn "MAVEN_OPTS=${mavenOpts}", "PATH+MAVEN=${tool(mvnName)}/bin:${tool(jdkName)}/bin" ]) { + sh '$JAVA_HOME_IT/bin/java -version' sh 'echo JAVA_HOME=$JAVA_HOME, JAVA_HOME_IT=$JAVA_HOME_IT, PATH=$PATH' def script = cmd + ['\"-Djdk.home=$JAVA_HOME_IT\"'] - sh script.join(' ') + def error = sh(returnStatus: true, script: script.join(' ')) + currentBuild.result = error == 0 ? 'SUCCESS' : 'FAILURE' } } else { withEnv(["JAVA_HOME=${tool(jdkName)}", @@ -160,33 +160,35 @@ def buildProcess(String stageKey, String jdkName, String jdkTestName, String mvn "MAVEN_OPTS=${mavenOpts}", "PATH+MAVEN=${tool(mvnName)}\\bin;${tool(jdkName)}\\bin" ]) { + bat '%JAVA_HOME_IT%\\bin\\java -version' bat 'echo JAVA_HOME=%JAVA_HOME%, JAVA_HOME_IT=%JAVA_HOME_IT%, PATH=%PATH%' def script = cmd + ['\"-Djdk.home=%JAVA_HOME_IT%\"'] - bat script.join(' ') + def error = bat(returnStatus: true, script: script.join(' ')) + currentBuild.result = error == 0 ? 'SUCCESS' : 'FAILURE' } } } } finally { - stage("reporting ${stageKey}") { - if (makeReports) { - openTasks(ignoreCase: true, canComputeNew: false, defaultEncoding: 'UTF-8', pattern: sourcesPatternCsv(), - high: tasksViolationHigh(), normal: tasksViolationNormal(), low: tasksViolationLow()) + if (makeReports) { + openTasks(ignoreCase: true, canComputeNew: true, defaultEncoding: 'UTF-8', pattern: sourcesPatternCsv(), + high: tasksViolationHigh(), normal: tasksViolationNormal(), low: tasksViolationLow()) - jacoco(changeBuildStatus: false, - execPattern: '**/*.exec', - sourcePattern: sourcesPatternCsv(), - classPattern: classPatternCsv()) + jacoco(changeBuildStatus: false, + execPattern: '**/*.exec', + sourcePattern: sourcesPatternCsv(), + classPattern: classPatternCsv()) - junit(healthScaleFactor: 0.0, - allowEmptyResults: true, - keepLongStdio: true, - testResults: testReportsPatternCsv()) + junit(healthScaleFactor: 0.0, + allowEmptyResults: true, + keepLongStdio: true, + testResults: testReportsPatternCsv()) - if (currentBuild.result == 'UNSTABLE') { - currentBuild.result = 'FAILURE' - } + if (currentBuild.result == 'UNSTABLE') { + currentBuild.result = 'FAILURE' } + } + if (currentBuild.result != null && currentBuild.result != 'SUCCESS') { if (fileExists('maven-failsafe-plugin/target/it')) { zip(zipFile: "maven-failsafe-plugin--${stageKey}.zip", dir: 'maven-failsafe-plugin/target/it', archive: true) } @@ -197,11 +199,8 @@ def buildProcess(String stageKey, String jdkName, String jdkTestName, String mvn archiveArtifacts(artifacts: "*--${stageKey}.zip", allowEmptyArchive: true, onlyIfSuccessful: false) } - - stage("cleanup ${stageKey}") { - // clean up after ourselves to reduce disk space - cleanWs() - } + // clean up after ourselves to reduce disk space + cleanWs() } } @@ -213,6 +212,7 @@ static def sourcesPatternCsv() { '**/maven-surefire-report-plugin/src/main/java,' + '**/surefire-api/src/main/java,' + '**/surefire-booter/src/main/java,' + + '**/surefire-extensions-api/src/main/java,' + '**/surefire-grouper/src/main/java,' + '**/surefire-its/src/main/java,' + '**/surefire-logger-api/src/main/java,' + @@ -228,6 +228,7 @@ static def classPatternCsv() { '**/maven-surefire-report-plugin/target/classes,' + '**/surefire-api/target/classes,' + '**/surefire-booter/target/classes,' + + '**/surefire-extensions-api/target/classes,' + '**/surefire-grouper/target/classes,' + '**/surefire-its/target/classes,' + '**/surefire-logger-api/target/classes,' + diff --git a/maven-failsafe-plugin/pom.xml b/maven-failsafe-plugin/pom.xml index bdaf97ffc2..03362b3a20 100644 --- a/maven-failsafe-plugin/pom.xml +++ b/maven-failsafe-plugin/pom.xml @@ -24,7 +24,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 org.apache.maven.plugins @@ -35,7 +35,7 @@ Maven Failsafe MOJO in maven-failsafe-plugin. - 3.0 + ${mavenVersion} @@ -59,6 +59,11 @@ zip site-source + + org.apache.maven + maven-core + provided + org.apache.maven.plugin-tools maven-plugin-annotations @@ -81,6 +86,12 @@ mockito-core test + + org.jacoco + org.jacoco.agent + runtime + test + @@ -107,16 +118,32 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 + ${jvm.args.tests} ${jacoco.agent} **/JUnit4SuiteTest.java @@ -208,16 +235,16 @@ - org.apache.maven.shared - org.apache.maven.surefire.shade.org.apache.maven.shared + org.apache.maven.shared.utils + org.apache.maven.surefire.shade.failsafe.org.apache.maven.shared.utils org.apache.commons.io - org.apache.maven.surefire.shade.org.apache.commons.io + org.apache.maven.surefire.shade.failsafe.org.apache.commons.io org.apache.commons.lang3 - org.apache.maven.surefire.shade.org.apache.commons.lang3 + org.apache.maven.surefire.shade.failsafe.org.apache.commons.lang3 @@ -293,9 +320,6 @@ verify -nsu - - dummy-*/pom.xml - */pom.xml @@ -307,6 +331,8 @@ ${failsafe-integration-test-port} ${failsafe-integration-test-stop-port} + ${https.protocols} + ${https.protocols} @@ -314,7 +340,6 @@ ${jdk.home} ${project.build.directory}/local-repo - -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2 diff --git a/maven-failsafe-plugin/src/it/settings.xml b/maven-failsafe-plugin/src/it/settings.xml index 144ef9a8ff..2ec940af13 100644 --- a/maven-failsafe-plugin/src/it/settings.xml +++ b/maven-failsafe-plugin/src/it/settings.xml @@ -32,7 +32,7 @@ true - true + false diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java index 77c1968549..910bf4f7a2 100644 --- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java +++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java @@ -31,11 +31,9 @@ import java.io.File; import java.io.IOException; -import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Locale; import static org.apache.maven.plugin.failsafe.util.FailsafeSummaryXmlUtils.writeSummary; @@ -61,7 +59,7 @@ public class IntegrationTestMojo @Parameter private File classesDirectory; - @Parameter( readonly = true, defaultValue = "${project.build.outputDirectory}" ) + @Parameter( defaultValue = "${project.build.outputDirectory}", readonly = true, required = true ) private File defaultClassesDirectory; /** @@ -264,7 +262,7 @@ public class IntegrationTestMojo private String encoding; /** - * (JUnit 4+ providers) + * (JUnit 4+ providers and JUnit 5+ providers since 3.0.0-M4) * The number of times each failing test will be rerun. If set larger than 0, rerun failing tests immediately after * they fail. If a failing test passes in any of those reruns, it will be marked as pass and reported as a "flake". * However, all the failing attempts will be recorded. @@ -320,6 +318,8 @@ public class IntegrationTestMojo * **{@literal /}NotIncludedByDefault.java * %regex[.*IT.*|.*Not.*] * + * + * @since 2.13 */ @Parameter( property = "failsafe.includesFile" ) private File includesFile; @@ -333,6 +333,8 @@ public class IntegrationTestMojo * **{@literal /}DontRunIT.* * %regex[.*IT.*|.*Not.*] * + * + * @since 2.13 */ @Parameter( property = "failsafe.excludesFile" ) private File excludesFile; @@ -355,10 +357,11 @@ public class IntegrationTestMojo * After the plugin process is shutdown by sending SIGTERM signal (CTRL+C), SHUTDOWN command is * received by every forked JVM. *
- * By default ({@code shutdown=testset}) forked JVM would not continue with new test which means that - * the current test may still continue to run. + * The value is set to ({@code shutdown=exit}) by default (changed in version 3.0.0-M4). + *
+ * The parameter can be configured with other two values {@code testset} and {@code kill}. *
- * The parameter can be configured with other two values {@code exit} and {@code kill}. + * With({@code shutdown=testset}) the test set may still continue to run in forked JVM. *
* Using {@code exit} forked JVM executes {@code System.exit(1)} after the plugin process has received * SIGTERM signal. @@ -367,7 +370,7 @@ public class IntegrationTestMojo * * @since 2.19 */ - @Parameter( property = "failsafe.shutdown", defaultValue = "testset" ) + @Parameter( property = "failsafe.shutdown", defaultValue = "exit" ) private String shutdown; /** @@ -381,6 +384,63 @@ public class IntegrationTestMojo @Parameter( property = "failsafe.useModulePath", defaultValue = "true" ) private boolean useModulePath; + /** + * You can selectively exclude individual environment variables by enumerating their keys. + *
+ * The environment is a system-dependent mapping from keys to values which is inherited from the Maven process + * to the forked Surefire processes. The keys must literally (case sensitive) match in order to exclude + * their environment variable. + *
+ * Example to exclude three environment variables: + *
+ * mvn test -Dfailsafe.excludedEnvironmentVariables=ACME1,ACME2,ACME3 + * + * @since 3.0.0-M4 + */ + @Parameter( property = "failsafe.excludedEnvironmentVariables" ) + private String[] excludedEnvironmentVariables; + + /** + * Since 3.0.0-M4 the process checkers are disabled. + * You can enable them namely by setting {@code ping} and {@code native} or {@code all} in this parameter. + *
+ * The checker is useful in situations when you kill the build on CI and you want the Surefire forked JVM to kill + * the tests asap and free all handlers on the file system been previously used by the JVM and by the tests. + * + *
+ * + * The {@code ping} should be safely used together with ZGC or Shenandoah Garbage Collector. + * Due to the {@code ping} relies on timing of PING (triggered every 30 seconds), slow GC may pause + * the timers and pretend that the parent process of the fork JVM does not exist. + * + *
+ * + * The {@code native} is very fast checker. + * It is useful mechanism on Unix based systems, Linux distributions and Alpine/BusyBox Linux. + * See the JIRA SUREFIRE-1631 for Windows issues. + * + *
+ * + * Another useful configuration parameter is {@code forkedProcessTimeoutInSeconds}. + *
+ * See the Frequently Asked Questions page with more details:
+ * + * http://maven.apache.org/surefire/maven-surefire-plugin/faq.html#kill-jvm + *
+ * + * http://maven.apache.org/surefire/maven-failsafe-plugin/faq.html#kill-jvm + * + *
+ * + * Example of use: + *
+ * mvn test -Dsurefire.enableProcessChecker=all + * + * @since 3.0.0-M4 + */ + @Parameter( property = "failsafe.enableProcessChecker" ) + private String enableProcessChecker; + @Override protected int getRerunFailingTestsCount() { @@ -836,8 +896,20 @@ protected final boolean hasSuiteXmlFiles() return suiteXmlFiles != null && suiteXmlFiles.length != 0; } - static Charset toCharset( String encoding ) + @Override + protected final String[] getExcludedEnvironmentVariables() + { + return excludedEnvironmentVariables == null ? new String[0] : excludedEnvironmentVariables; + } + + void setExcludedEnvironmentVariables( String[] excludedEnvironmentVariables ) + { + this.excludedEnvironmentVariables = excludedEnvironmentVariables; + } + + @Override + protected final String getEnableProcessChecker() { - return Charset.forName( Charset.isSupported( encoding ) ? encoding : encoding.toUpperCase( Locale.ROOT ) ); + return enableProcessChecker; } } diff --git a/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/IntegrationTestMojoTest.java b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/IntegrationTestMojoTest.java index 8414d6b00d..cbb0b0f002 100644 --- a/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/IntegrationTestMojoTest.java +++ b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/IntegrationTestMojoTest.java @@ -1 +1 @@ -package org.apache.maven.plugin.failsafe; /* * 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.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.project.MavenProject; import org.junit.Before; import org.junit.Test; import java.io.File; import java.io.IOException; import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import static org.fest.assertions.Assertions.assertThat; /** * @since 2.20 */ public class IntegrationTestMojoTest { private IntegrationTestMojo mojo; @Before public void init() throws InvalidVersionSpecificationException, IOException { Artifact artifact = new DefaultArtifact( "g", "a", createFromVersionSpec( "1.0" ), "compile", "jar", "", null ); artifact.setFile( new File( "./target/tmp/a-1.0.jar" ) ); new File( "./target/tmp" ).mkdir(); artifact.getFile().createNewFile(); mojo = spy( IntegrationTestMojo.class ); MavenProject project = mock( MavenProject.class ); when( project.getArtifact() ).thenReturn( artifact ); when( mojo.getProject() ).thenReturn( project ); } @Test public void shouldBeJar() { mojo.setDefaultClassesDirectory( new File( "./target/classes" ) ); File binaries = mojo.getClassesDirectory(); assertThat( binaries.getName() ).isEqualTo( "a-1.0.jar" ); } @Test public void shouldBeAnotherJar() { mojo.setClassesDirectory( new File( "./target/another-1.0.jar" ) ); mojo.setDefaultClassesDirectory( new File( "./target/classes" ) ); File binaries = mojo.getClassesDirectory(); assertThat( binaries.getName() ).isEqualTo( "another-1.0.jar" ); } @Test public void shouldBeClasses() { mojo.setClassesDirectory( new File( "./target/classes" ) ); mojo.setDefaultClassesDirectory( new File( "./target/classes" ) ); File binaries = mojo.getClassesDirectory(); assertThat( binaries.getName() ).isEqualTo( "classes" ); } } \ No newline at end of file +package org.apache.maven.plugin.failsafe; /* * 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.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.project.MavenProject; import org.junit.Before; import org.junit.Test; import java.io.File; import java.io.IOException; import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** * @since 2.20 */ public class IntegrationTestMojoTest { private IntegrationTestMojo mojo; @Before public void init() throws InvalidVersionSpecificationException, IOException { Artifact artifact = new DefaultArtifact( "g", "a", createFromVersionSpec( "1.0" ), "compile", "jar", "", null ); artifact.setFile( new File( "./target/tmp/a-1.0.jar" ) ); new File( "./target/tmp" ).mkdir(); artifact.getFile().createNewFile(); mojo = new IntegrationTestMojo(); MavenProject project = mock( MavenProject.class ); when( project.getArtifact() ).thenReturn( artifact ); mojo.setProject( project ); } @Test public void shouldBeJar() { mojo.setDefaultClassesDirectory( new File( "./target/classes" ) ); File binaries = mojo.getClassesDirectory(); assertThat( binaries.getName() ).isEqualTo( "a-1.0.jar" ); } @Test public void shouldBeAnotherJar() { mojo.setClassesDirectory( new File( "./target/another-1.0.jar" ) ); mojo.setDefaultClassesDirectory( new File( "./target/classes" ) ); File binaries = mojo.getClassesDirectory(); assertThat( binaries.getName() ).isEqualTo( "another-1.0.jar" ); } @Test public void shouldBeClasses() { mojo.setClassesDirectory( new File( "./target/classes" ) ); mojo.setDefaultClassesDirectory( new File( "./target/classes" ) ); File binaries = mojo.getClassesDirectory(); assertThat( binaries.getName() ).isEqualTo( "classes" ); } @Test public void shouldGetNullEnv() { assertThat( mojo.getExcludedEnvironmentVariables() ) .hasSize( 0 ); } @Test public void shouldGetEnv() { mojo.setExcludedEnvironmentVariables( new String[] { "ABC", "KLM" } ); assertThat( mojo.getExcludedEnvironmentVariables() ) .hasSize( 2 ) .contains( "ABC", "KLM" ); } } \ No newline at end of file diff --git a/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/MarshallerUnmarshallerTest.java b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/MarshallerUnmarshallerTest.java index 96708a8a59..94e65c8750 100644 --- a/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/MarshallerUnmarshallerTest.java +++ b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/MarshallerUnmarshallerTest.java @@ -27,6 +27,9 @@ import static org.fest.assertions.Assertions.assertThat; +/** + * + */ public class MarshallerUnmarshallerTest { @Test diff --git a/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/RunResultTest.java b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/RunResultTest.java index 5e75ebfa33..3ef140c20f 100644 --- a/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/RunResultTest.java +++ b/maven-failsafe-plugin/src/test/java/org/apache/maven/plugin/failsafe/RunResultTest.java @@ -24,7 +24,6 @@ import org.junit.Test; import java.io.File; -import java.nio.charset.Charset; import static org.fest.assertions.Assertions.assertThat; @@ -32,6 +31,7 @@ * @author Tibor Digana (tibor17) * @since 2.20 */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class RunResultTest { @@ -118,16 +118,6 @@ public void testAppendSerialization() .isEqualTo( expected ); } - @Test - public void shouldAcceptAliasCharset() - { - Charset charset1 = IntegrationTestMojo.toCharset( "UTF8" ); - assertThat( charset1.name() ).isEqualTo( "UTF-8" ); - - Charset charset2 = IntegrationTestMojo.toCharset( "utf8" ); - assertThat( charset2.name() ).isEqualTo( "UTF-8" ); - } - private void writeReadCheck( RunResult expected ) throws Exception { diff --git a/maven-surefire-common/pom.xml b/maven-surefire-common/pom.xml index 8eb22861fb..b11f5a71bc 100644 --- a/maven-surefire-common/pom.xml +++ b/maven-surefire-common/pom.xml @@ -24,7 +24,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 maven-surefire-common @@ -32,10 +32,6 @@ Maven Surefire Common API used in Surefire and Failsafe MOJO. - - 3.0 - - org.apache.maven.surefire @@ -44,17 +40,17 @@ org.apache.maven.surefire - surefire-booter + surefire-extensions-api ${project.version} - org.apache.maven - maven-core - provided + org.apache.maven.surefire + surefire-booter + ${project.version} org.apache.maven - maven-plugin-api + maven-core provided @@ -62,16 +58,6 @@ maven-plugin-annotations provided - - org.apache.maven - maven-artifact - provided - - - org.apache.maven - maven-model - provided - org.apache.maven maven-toolchain @@ -80,6 +66,10 @@ org.apache.maven.shared maven-common-artifact-filters + + org.apache.maven.shared + maven-artifact-transfer + org.codehaus.plexus plexus-java @@ -101,6 +91,10 @@ org.apache.commons commons-lang3 + + org.apache.commons + commons-compress + com.google.code.findbugs jsr305 @@ -126,24 +120,68 @@ powermock-api-mockito2 test + + org.jacoco + org.jacoco.agent + runtime + test + + + maven-dependency-plugin + + + build-test-classpath + generate-sources + + build-classpath + + + test + target/test-classpath/cp.txt + + + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-instrumentation + + instrument + + + + restore-classes + + restore-instrumented-classes + + + + maven-surefire-plugin - - - **/JUnit4SuiteTest.java - - org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 + + ${jvm.args.tests} + + **/JUnit4SuiteTest.java + + + ${project.build.directory}/jacoco.exec + + maven-shade-plugin @@ -161,12 +199,13 @@ org.apache.maven.shared:maven-common-artifact-filters commons-io:commons-io org.apache.commons:commons-lang3 + org.apache.commons:commons-compress - org.apache.maven.shared - org.apache.maven.surefire.shade.common.org.apache.maven.shared + org.apache.maven.shared.utils + org.apache.maven.surefire.shade.common.org.apache.maven.shared.utils org.apache.commons.io @@ -176,6 +215,10 @@ org.apache.commons.lang3 org.apache.maven.surefire.shade.common.org.apache.commons.lang3 + + org.apache.commons.compress + org.apache.maven.surefire.shade.common.org.apache.commons.compress + 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 677e3ee11c..a53d75a065 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 @@ -21,9 +21,15 @@ */ import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.handler.ArtifactHandler; import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.project.ProjectBuildingRequest; import org.apache.maven.repository.RepositorySystem; import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; @@ -51,6 +57,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter; +import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver; import org.apache.maven.shared.utils.io.FileUtils; import org.apache.maven.surefire.booter.ClassLoaderConfiguration; import org.apache.maven.surefire.booter.Classpath; @@ -58,6 +65,7 @@ import org.apache.maven.surefire.booter.KeyValueSource; import org.apache.maven.surefire.booter.ModularClasspath; import org.apache.maven.surefire.booter.ModularClasspathConfiguration; +import org.apache.maven.surefire.booter.ProcessCheckerType; import org.apache.maven.surefire.booter.ProviderConfiguration; import org.apache.maven.surefire.booter.ProviderParameterNames; import org.apache.maven.surefire.booter.Shutdown; @@ -91,6 +99,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; @@ -113,6 +122,7 @@ import static java.util.Collections.singletonMap; import static org.apache.commons.lang3.StringUtils.substringBeforeLast; import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS; +import static org.apache.maven.artifact.ArtifactUtils.artifactMapByVersionlessId; import static org.apache.maven.plugin.surefire.SurefireDependencyResolver.isWithinVersionSpec; import static org.apache.maven.plugin.surefire.util.DependencyScanner.filter; import static org.apache.maven.plugin.surefire.SurefireHelper.replaceThreadNumberPlaceholders; @@ -150,13 +160,27 @@ public abstract class AbstractSurefireMojo private final ProviderDetector providerDetector = new ProviderDetector(); + private final ClasspathCache classpathCache = new ClasspathCache(); + + /** + * Note: use the legacy system property disableXmlReport set to {@code true} to disable the report. + */ + @Parameter + private SurefireStatelessReporter statelessTestsetReporter; + + @Parameter + private SurefireConsoleOutputReporter consoleOutputReporter; + + @Parameter + private SurefireStatelessTestsetInfoReporter statelessTestsetInfoReporter; + /** * Information about this plugin, mainly used to lookup this plugin's configuration from the currently executing * project. * * @since 2.12 */ - @Parameter( defaultValue = "${plugin}", readonly = true ) + @Parameter( defaultValue = "${plugin}", readonly = true, required = true ) private PluginDescriptor pluginDescriptor; /** @@ -198,7 +222,7 @@ public abstract class AbstractSurefireMojo * The base directory of the project being tested. This can be obtained in your integration test via * System.getProperty("basedir"). */ - @Parameter( defaultValue = "${basedir}" ) + @Parameter( defaultValue = "${basedir}", readonly = true, required = true ) protected File basedir; /** @@ -478,15 +502,6 @@ public abstract class AbstractSurefireMojo @Parameter( property = "junitArtifactName", defaultValue = "junit:junit" ) private String junitArtifactName; - /** - * Allows you to specify the name of the JUnit Platform artifact. - * If not set, {@code org.junit.platform:junit-platform-engine} will be used. - * - * @since 2.22.0 - */ - @Parameter( property = "junitPlatformArtifactName", defaultValue = "org.junit.platform:junit-platform-engine" ) - private String junitPlatformArtifactName; - /** * Allows you to specify the name of the TestNG artifact. If not set, {@code org.testng:testng} will be used. * @@ -567,6 +582,10 @@ public abstract class AbstractSurefireMojo * Since version 2.16 (JUnit 4.7 provider), additional vales are available: *
* {@code suites}, {@code suitesAndClasses}, {@code suitesAndMethods}, {@code classesAndMethods}, {@code all}. + *
+ * By default, Surefire does not execute tests in parallel. You can set the parameter {@code parallel} to + * {@code none} to explicitly disable parallel execution (e.g. when disabling parallel execution in special Maven + * profiles when executing coverage analysis). * * @since 2.2 */ @@ -656,25 +675,24 @@ public abstract class AbstractSurefireMojo @Parameter( property = "trimStackTrace", defaultValue = "true" ) private boolean trimStackTrace; - /** - * Creates the artifact. - */ - @Component - private ArtifactFactory artifactFactory; - /** * The remote plugin repositories declared in the POM. * * @since 2.2 */ - @Parameter( defaultValue = "${project.pluginArtifactRepositories}" ) + @Parameter( defaultValue = "${project.pluginArtifactRepositories}", readonly = true, required = true ) private List remoteRepositories; + @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true ) + private List projectRemoteRepositories; + /** * Flag to disable the generation of report files in xml format. - * + * Deprecated since 3.0.0-M4. + * Instead use disable within {@code statelessTestsetReporter} since of 3.0.0-M6. * @since 2.2 */ + @Deprecated // todo make readonly to handle system property @Parameter( property = "disableXmlReport", defaultValue = "false" ) private boolean disableXmlReport; @@ -714,18 +732,34 @@ public abstract class AbstractSurefireMojo * Read-only parameter with value of Maven property project.build.directory. * @since 2.20 */ - @Parameter( defaultValue = "${project.build.directory}", readonly = true ) + @Parameter( defaultValue = "${project.build.directory}", readonly = true, required = true ) private File projectBuildDirectory; /** * List of dependencies to scan for test classes to include in the test run. * The child elements of this element must be <dependency> elements, and the - * contents of each of these elements must be a string which follows the format: - *
- * groupId:artifactId. For example: org.acme:project-a. - *
- * Since version 2.22.0 you can scan for test classes from a project - * dependency of your multi-module project. + * contents of each of these elements must be a string which follows the general form: + * + *

{@code groupId[:artifactId[:type[:classifier][:version]]]}

+ * + *

The wildcard character * can be used within the sub parts of those composite identifiers to + * do glob-like pattern matching. The classifier may be omitted when matching dependencies without a classifier.

+ * + *

Examples:

+ * + *
    + *
  • {@code group} or, equivalently, {@code group:*}
  • + *
  • {@code g*p:*rtifac*}
  • + *
  • {@code group:*:jar}
  • + *
  • {@code group:artifact:*:1.0.0} (no classifier)
  • + *
  • {@code group:*:test-jar:tests}
  • + *
  • {@code *:artifact:*:*:1.0.0}
  • + *
+ * + *

Since version 2.22.0 you can scan for test classes from a project + * dependency of your multi-module project.

+ * + *

In versions before 3.0.0-M4, only groupId:artifactId is supported.

* * @since 2.15 */ @@ -744,6 +778,9 @@ public abstract class AbstractSurefireMojo @Component private RepositorySystem repositorySystem; + @Component + private DependencyResolver dependencyResolver; + private Artifact surefireBooterArtifact; private Toolchain toolchain; @@ -777,6 +814,8 @@ public abstract class AbstractSurefireMojo */ protected abstract boolean hasSuiteXmlFiles(); + protected abstract String[] getExcludedEnvironmentVariables(); + public abstract File[] getSuiteXmlFiles(); public abstract void setSuiteXmlFiles( File[] suiteXmlFiles ); @@ -798,6 +837,8 @@ protected abstract void handleSummary( RunResult summary, Exception firstForkExc protected abstract void setUseModulePath( boolean useModulePath ); + protected abstract String getEnableProcessChecker(); + /** * This plugin MOJO artifact. * @@ -805,7 +846,7 @@ protected abstract void handleSummary( RunResult summary, Exception firstForkExc */ protected Artifact getMojoArtifact() { - return pluginDescriptor.getPluginArtifact(); + return getPluginDescriptor().getPluginArtifact(); } private String getDefaultExcludes() @@ -813,7 +854,7 @@ private String getDefaultExcludes() return "**/*$*"; } - private SurefireDependencyResolver dependencyResolver; + private SurefireDependencyResolver surefireDependencyResolver; private TestListResolver specificTests; @@ -849,6 +890,11 @@ public void execute() } } + void setLogger( Logger logger ) + { + this.logger = logger; + } + @Nonnull protected final PluginConsoleLogger getConsoleLogger() { @@ -867,9 +913,22 @@ protected final PluginConsoleLogger getConsoleLogger() private void setupStuff() { - createDependencyResolver(); - surefireBooterArtifact = getSurefireBooterArtifact(); - toolchain = getToolchain(); + surefireDependencyResolver = new SurefireDependencyResolver( getRepositorySystem(), + getConsoleLogger(), getLocalRepository(), + getRemoteRepositories(), + getProjectRemoteRepositories(), + getPluginName(), getDependencyResolver() ); + + surefireBooterArtifact = getBooterArtifact(); + if ( surefireBooterArtifact == null ) + { + throw new RuntimeException( "Unable to locate surefire-booter in the list of plugin artifacts" ); + } + + if ( getToolchainManager() != null ) + { + toolchain = getToolchainManager().getToolchainFromBuildContext( "jdk", getSession() ); + } } @Nonnull @@ -973,6 +1032,7 @@ boolean verifyParameters() } else { + ensureEnableProcessChecker(); convertDeprecatedForkMode(); ensureWorkingDirectoryExists(); ensureParallelRunningCompatibility(); @@ -990,7 +1050,8 @@ boolean verifyParameters() private void executeAfterPreconditionsChecked( @Nonnull DefaultScanResult scanResult ) throws MojoExecutionException, MojoFailureException { - List providers = createProviders(); + TestClassPath testClasspath = generateTestClasspath(); + List providers = createProviders( testClasspath ); RunResult current = noTestsRun(); @@ -999,7 +1060,7 @@ private void executeAfterPreconditionsChecked( @Nonnull DefaultScanResult scanRe { try { - current = current.aggregate( executeProvider( provider, scanResult ) ); + current = current.aggregate( executeProvider( provider, scanResult, testClasspath ) ); } catch ( SurefireBooterForkException | SurefireExecutionException | TestSetFailedException e ) { @@ -1018,21 +1079,13 @@ private void executeAfterPreconditionsChecked( @Nonnull DefaultScanResult scanRe handleSummary( current, firstForkException ); } - private void createDependencyResolver() - { - dependencyResolver = new SurefireDependencyResolver( getRepositorySystem(), getArtifactFactory(), - getConsoleLogger(), getLocalRepository(), - getRemoteRepositories(), - getPluginName() ); - } - - protected List createProviders() + protected List createProviders( TestClassPath testClasspath ) throws MojoExecutionException { Artifact junitDepArtifact = getJunitDepArtifact(); return new ProviderList( new DynamicProviderInfo( null ), new TestNgProviderInfo( getTestNgArtifact() ), - new JUnitPlatformProviderInfo( getJunitPlatformArtifact() ), + new JUnitPlatformProviderInfo( getJunitPlatformArtifact(), testClasspath ), new JUnitCoreProviderInfo( getJunitArtifact(), junitDepArtifact ), new JUnit4ProviderInfo( getJunitArtifact(), junitDepArtifact ), new JUnit3ProviderInfo() ) @@ -1124,7 +1177,8 @@ private void showToLog( SurefireProperties props, ConsoleLogger log ) } @Nonnull - private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull DefaultScanResult scanResult ) + private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull DefaultScanResult scanResult, + @Nonnull TestClassPath testClasspathWrapper ) throws MojoExecutionException, MojoFailureException, SurefireExecutionException, SurefireBooterForkException, TestSetFailedException { @@ -1139,8 +1193,8 @@ private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull Defa { createCopyAndReplaceForkNumPlaceholder( effectiveProperties, 1 ).copyToSystemProperties(); - InPluginVMSurefireStarter surefireStarter = - createInprocessStarter( provider, classLoaderConfiguration, runOrderParameters, scanResult, platform ); + InPluginVMSurefireStarter surefireStarter = createInprocessStarter( provider, classLoaderConfiguration, + runOrderParameters, scanResult, platform, testClasspathWrapper ); return surefireStarter.runSuitesInProcess( scanResult ); } else @@ -1149,6 +1203,7 @@ private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull Defa if ( getConsoleLogger().isDebugEnabled() ) { showMap( getEnvironmentVariables(), "environment variable" ); + showArray( getExcludedEnvironmentVariables(), "excluded environment variable" ); } Properties originalSystemProperties = (Properties) System.getProperties().clone(); @@ -1156,7 +1211,8 @@ private RunResult executeProvider( @Nonnull ProviderInfo provider, @Nonnull Defa try { forkStarter = createForkStarter( provider, forkConfiguration, classLoaderConfiguration, - runOrderParameters, getConsoleLogger(), scanResult, platform ); + runOrderParameters, getConsoleLogger(), scanResult, platform, + testClasspathWrapper ); return forkStarter.run( effectiveProperties, scanResult ); } @@ -1221,16 +1277,14 @@ public void setRepositorySystem( RepositorySystem repositorySystem ) this.repositorySystem = repositorySystem; } - final Toolchain getToolchain() + public DependencyResolver getDependencyResolver() { - Toolchain tc = null; - - if ( getToolchainManager() != null ) - { - tc = getToolchainManager().getToolchainFromBuildContext( "jdk", getSession() ); - } + return dependencyResolver; + } - return tc; + public void setDependencyResolver( DependencyResolver dependencyResolver ) + { + this.dependencyResolver = dependencyResolver; } private boolean existsModuleDescriptor() @@ -1695,7 +1749,7 @@ private static Map toStringProperties( Properties properties ) return h; } - public File getStatisticsFile( String configurationHash ) + private File getStatisticsFile( String configurationHash ) { return new File( getBasedir(), ".surefire-" + configurationHash ); } @@ -1703,7 +1757,8 @@ public File getStatisticsFile( String configurationHash ) private StartupConfiguration createStartupConfiguration( @Nonnull ProviderInfo provider, boolean isInprocess, @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull DefaultScanResult scanResult, - @Nonnull Platform platform ) + @Nonnull Platform platform, + @Nonnull TestClassPath testClasspathWrapper ) throws MojoExecutionException { try @@ -1721,11 +1776,12 @@ private StartupConfiguration createStartupConfiguration( @Nonnull ProviderInfo p .toString(); return newStartupConfigWithModularPath( classLoaderConfiguration, providerArtifacts, providerName, - getModuleDescriptor(), scanResult, javaHome ); + getModuleDescriptor(), scanResult, javaHome, testClasspathWrapper ); } else { - return newStartupConfigWithClasspath( classLoaderConfiguration, providerArtifacts, providerName ); + return newStartupConfigWithClasspath( classLoaderConfiguration, providerArtifacts, providerName, + testClasspathWrapper ); } } catch ( IOException e ) @@ -1736,17 +1792,14 @@ private StartupConfiguration createStartupConfiguration( @Nonnull ProviderInfo p private StartupConfiguration newStartupConfigWithClasspath( @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull Set providerArtifacts, - @Nonnull String providerName ) + @Nonnull String providerName, @Nonnull TestClassPath testClasspathWrapper ) { - TestClassPath testClasspathWrapper = generateTestClasspath(); Classpath testClasspath = testClasspathWrapper.toClasspath(); - testClasspathWrapper.avoidArtifactDuplicates( providerArtifacts ); - - Classpath providerClasspath = ClasspathCache.getCachedClassPath( providerName ); + Classpath providerClasspath = classpathCache.getCachedClassPath( providerName ); if ( providerClasspath == null ) { - providerClasspath = ClasspathCache.setCachedClasspath( providerName, providerArtifacts ); + providerClasspath = classpathCache.setCachedClasspath( providerName, providerArtifacts ); } getConsoleLogger().debug( testClasspath.getLogMessage( "test classpath:" ) ); @@ -1754,7 +1807,8 @@ private StartupConfiguration newStartupConfigWithClasspath( getConsoleLogger().debug( testClasspath.getCompactLogMessage( "test(compact) classpath:" ) ); getConsoleLogger().debug( providerClasspath.getCompactLogMessage( "provider(compact) classpath:" ) ); - Artifact[] additionalInProcArtifacts = { getCommonArtifact(), getApiArtifact(), getLoggerApiArtifact() }; + Artifact[] additionalInProcArtifacts = + { getCommonArtifact(), getExtensionsArtifact(), getApiArtifact(), getLoggerApiArtifact() }; Set inProcArtifacts = retainInProcArtifactsUnique( providerArtifacts, additionalInProcArtifacts ); Classpath inProcClasspath = createInProcClasspath( providerClasspath, inProcArtifacts ); getConsoleLogger().debug( inProcClasspath.getLogMessage( "in-process classpath:" ) ); @@ -1764,7 +1818,7 @@ private StartupConfiguration newStartupConfigWithClasspath( inProcClasspath, effectiveIsEnableAssertions(), isChildDelegation() ); return new StartupConfiguration( providerName, classpathConfiguration, classLoaderConfiguration, isForking(), - false ); + false, ProcessCheckerType.toEnum( getEnableProcessChecker() ) ); } private static Set retainInProcArtifactsUnique( Set providerArtifacts, @@ -1776,8 +1830,8 @@ private static Set retainInProcArtifactsUnique( Set provider boolean contains = false; for ( Artifact providerArtifact : providerArtifacts ) { - if ( providerArtifact.getGroupId().equals( inPluginArtifact.getGroupId() ) - && providerArtifact.getArtifactId().equals( inPluginArtifact.getArtifactId() ) ) + if ( hasGroupArtifactId( providerArtifact.getGroupId(), providerArtifact.getArtifactId(), + inPluginArtifact ) ) { contains = true; break; @@ -1791,6 +1845,11 @@ private static Set retainInProcArtifactsUnique( Set provider return result; } + private static boolean hasGroupArtifactId( String groupId, String artifactId, Artifact artifact ) + { + return groupId.equals( artifact.getGroupId() ) && artifactId.equals( artifact.getArtifactId() ); + } + private static Classpath createInProcClasspath( Classpath providerClasspath, Set newArtifacts ) { Classpath inprocClasspath = providerClasspath.clone(); @@ -1813,18 +1872,15 @@ private LocationManager getLocationManager() private StartupConfiguration newStartupConfigWithModularPath( @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull Set providerArtifacts, @Nonnull String providerName, @Nonnull File moduleDescriptor, @Nonnull DefaultScanResult scanResult, - @Nonnull String javaHome ) + @Nonnull String javaHome, @Nonnull TestClassPath testClasspathWrapper ) throws IOException { - TestClassPath testClasspathWrapper = generateTestClasspath(); Classpath testClasspath = testClasspathWrapper.toClasspath(); - testClasspathWrapper.avoidArtifactDuplicates( providerArtifacts ); - - Classpath providerClasspath = ClasspathCache.getCachedClassPath( providerName ); + Classpath providerClasspath = classpathCache.getCachedClassPath( providerName ); if ( providerClasspath == null ) { - providerClasspath = ClasspathCache.setCachedClasspath( providerName, providerArtifacts ); + providerClasspath = classpathCache.setCachedClasspath( providerName, providerArtifacts ); } ResolvePathsRequest req = ResolvePathsRequest.ofStrings( testClasspath.getClassPath() ) @@ -1849,11 +1905,18 @@ private StartupConfiguration newStartupConfigWithModularPath( packages.add( substringBeforeLast( className, "." ) ); } - ModularClasspath modularClasspath = new ModularClasspath( moduleDescriptor, testModulepath.getClassPath(), - packages, getTestClassesDirectory() ); + getConsoleLogger().debug( "main module descriptor name: " + result.getMainModuleDescriptor().name() ); + + ModularClasspath modularClasspath = new ModularClasspath( result.getMainModuleDescriptor().name(), + testModulepath.getClassPath(), packages, getTestClassesDirectory() ); + + Artifact[] additionalInProcArtifacts = + { getCommonArtifact(), getExtensionsArtifact(), getApiArtifact(), getLoggerApiArtifact() }; + Set 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:" ) ); @@ -1861,9 +1924,11 @@ private StartupConfiguration newStartupConfigWithModularPath( 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 ); + false, ProcessCheckerType.toEnum( getEnableProcessChecker() ) ); } private Artifact getCommonArtifact() @@ -1871,6 +1936,11 @@ private Artifact getCommonArtifact() return getPluginArtifactMap().get( "org.apache.maven.surefire:maven-surefire-common" ); } + private Artifact getExtensionsArtifact() + { + return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-extensions-api" ); + } + private Artifact getApiArtifact() { return getPluginArtifactMap().get( "org.apache.maven.surefire:surefire-api" ); @@ -1893,12 +1963,26 @@ private Artifact getShadefireArtifact() private StartupReportConfiguration getStartupReportConfiguration( String configChecksum, boolean isForkMode ) { + SurefireStatelessReporter xmlReporter = + statelessTestsetReporter == null + ? new SurefireStatelessReporter( /*todo call def. constr.*/ isDisableXmlReport(), "3.0" ) + : statelessTestsetReporter; + + xmlReporter.setDisable( isDisableXmlReport() ); // todo change to Boolean in the version 3.0.0-M6 + + SurefireConsoleOutputReporter outReporter = + consoleOutputReporter == null ? new SurefireConsoleOutputReporter() : consoleOutputReporter; + + SurefireStatelessTestsetInfoReporter testsetReporter = + statelessTestsetInfoReporter == null + ? new SurefireStatelessTestsetInfoReporter() : statelessTestsetInfoReporter; + return new StartupReportConfiguration( isUseFile(), isPrintSummary(), getReportFormat(), - isRedirectTestOutputToFile(), isDisableXmlReport(), + isRedirectTestOutputToFile(), getReportsDirectory(), isTrimStackTrace(), getReportNameSuffix(), getStatisticsFile( configChecksum ), requiresRunHistory(), getRerunFailingTestsCount(), getReportSchemaLocation(), getEncoding(), - isForkMode ); + isForkMode, xmlReporter, outReporter, testsetReporter ); } private boolean isSpecificTestSpecified() @@ -2124,14 +2208,19 @@ private Artifact getJunitDepArtifact() return getProjectArtifactMap().get( "junit:junit-dep" ); } - private Artifact getJunitPlatformArtifact() { - Artifact artifact = getProjectArtifactMap().get( getJunitPlatformArtifactName() ); - Artifact projectArtifact = project.getArtifact(); - String projectArtifactName = projectArtifact.getGroupId() + ":" + projectArtifact.getArtifactId(); + Artifact artifact = getProjectArtifactMap().get( "org.junit.platform:junit-platform-commons" ); + if ( artifact == null ) + { + artifact = getPluginArtifactMap().get( "org.junit.platform:junit-platform-engine" ); + } - if ( artifact == null && projectArtifactName.equals( getJunitPlatformArtifactName() ) ) + Artifact projectArtifact = project.getArtifact(); + String projectGroupId = projectArtifact.getGroupId(); + if ( artifact == null && ( "org.junit.platform".equals( projectGroupId ) + || "org.junit.jupiter".equals( projectGroupId ) + || "org.junit.vintage".equals( projectGroupId ) ) ) { artifact = projectArtifact; } @@ -2142,11 +2231,12 @@ private Artifact getJunitPlatformArtifact() private ForkStarter createForkStarter( @Nonnull ProviderInfo provider, @Nonnull ForkConfiguration forkConfiguration, @Nonnull ClassLoaderConfiguration classLoaderConfiguration, @Nonnull RunOrderParameters runOrderParameters, @Nonnull ConsoleLogger log, - @Nonnull DefaultScanResult scanResult, @Nonnull Platform platform ) + @Nonnull DefaultScanResult scanResult, @Nonnull Platform platform, + @Nonnull TestClassPath testClasspathWrapper ) throws MojoExecutionException, MojoFailureException { - StartupConfiguration startupConfiguration = - createStartupConfiguration( provider, false, classLoaderConfiguration, scanResult, platform ); + StartupConfiguration startupConfiguration = createStartupConfiguration( provider, false, + classLoaderConfiguration, scanResult, platform, testClasspathWrapper ); String configChecksum = getConfigChecksum(); StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum, true ); ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters ); @@ -2158,11 +2248,12 @@ private InPluginVMSurefireStarter createInprocessStarter( @Nonnull ProviderInfo @Nonnull ClassLoaderConfiguration classLoaderConfig, @Nonnull RunOrderParameters runOrderParameters, @Nonnull DefaultScanResult scanResult, - @Nonnull Platform platform ) + @Nonnull Platform platform, + @Nonnull TestClassPath testClasspathWrapper ) throws MojoExecutionException, MojoFailureException { - StartupConfiguration startupConfiguration = - createStartupConfiguration( provider, true, classLoaderConfig, scanResult, platform ); + StartupConfiguration startupConfiguration = createStartupConfiguration( provider, true, classLoaderConfig, + scanResult, platform, testClasspathWrapper ); String configChecksum = getConfigChecksum(); StartupReportConfiguration startupReportConfiguration = getStartupReportConfiguration( configChecksum, false ); ProviderConfiguration providerConfiguration = createProviderConfiguration( runOrderParameters ); @@ -2188,6 +2279,7 @@ private ForkConfiguration createForkConfiguration( Platform platform ) getProject().getModel().getProperties(), getArgLine(), getEnvironmentVariables(), + getExcludedEnvironmentVariables(), getConsoleLogger().isDebugEnabled(), getEffectiveForkCount(), reuseForks, @@ -2203,6 +2295,7 @@ else if ( getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable() ) getProject().getModel().getProperties(), getArgLine(), getEnvironmentVariables(), + getExcludedEnvironmentVariables(), getConsoleLogger().isDebugEnabled(), getEffectiveForkCount(), reuseForks, @@ -2218,6 +2311,7 @@ else if ( getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable() ) getProject().getModel().getProperties(), getArgLine(), getEnvironmentVariables(), + getExcludedEnvironmentVariables(), getConsoleLogger().isDebugEnabled(), getEffectiveForkCount(), reuseForks, @@ -2226,6 +2320,16 @@ else if ( getClassLoaderConfiguration().isManifestOnlyJarRequestedAndUsable() ) } } + private void ensureEnableProcessChecker() throws MojoFailureException + { + if ( !ProcessCheckerType.isValid( getEnableProcessChecker() ) ) + { + throw new MojoFailureException( "Unexpected value '" + + getEnableProcessChecker() + + "' in the configuration parameter 'enableProcessChecker'." ); + } + } + private void convertDeprecatedForkMode() { String effectiveForkMode = getEffectiveForkMode(); @@ -2354,16 +2458,6 @@ private JdkAttributes getEffectiveJvm() throws MojoFailureException return new JdkAttributes( jvmToUse, isBuiltInJava9AtLeast() ); } - private Artifact getSurefireBooterArtifact() - { - Artifact artifact = getBooterArtifact(); - if ( artifact == null ) - { - throw new RuntimeException( "Unable to locate surefire-booter in the list of plugin artifacts" ); - } - return artifact; - } - /** * Where surefire stores its own temp files * @@ -2435,6 +2529,7 @@ private String getConfigChecksum() checksum.add( getParallelTestsTimeoutInSeconds() ); checksum.add( getParallelTestsTimeoutForcedInSeconds() ); checksum.add( getEnvironmentVariables() ); + checksum.add( getExcludedEnvironmentVariables() ); checksum.add( getWorkingDirectory() ); checksum.add( isChildDelegation() ); checksum.add( getGroups() ); @@ -2452,6 +2547,7 @@ private String getConfigChecksum() checksum.add( isParallelOptimized() ); checksum.add( isTrimStackTrace() ); checksum.add( getRemoteRepositories() ); + checksum.add( getProjectRemoteRepositories() ); checksum.add( isDisableXmlReport() ); checksum.add( isUseSystemClassLoader() ); checksum.add( isUseManifestOnlyJar() ); @@ -2465,6 +2561,7 @@ private String getConfigChecksum() checksum.add( getRerunFailingTestsCount() ); checksum.add( getTempDir() ); checksum.add( useModulePath() ); + checksum.add( getEnableProcessChecker() ); addPluginSpecificChecksumItems( checksum ); return checksum.getSha1(); } @@ -2505,7 +2602,7 @@ protected ClassLoaderConfiguration getClassLoaderConfiguration() */ private TestClassPath generateTestClasspath() { - @SuppressWarnings( "unchecked" ) Set classpathArtifacts = getProject().getArtifacts(); + Set classpathArtifacts = getProject().getArtifacts(); if ( getClasspathDependencyScopeExclude() != null && !getClasspathDependencyScopeExclude().isEmpty() ) { @@ -2521,7 +2618,7 @@ private TestClassPath generateTestClasspath() } return new TestClassPath( classpathArtifacts, getClassesDirectory(), - getTestClassesDirectory(), getAdditionalClasspathElements(), getConsoleLogger() ); + getTestClassesDirectory(), getAdditionalClasspathElements() ); } /** @@ -2556,13 +2653,23 @@ private void showMap( Map map, String setting ) } } + private void showArray( T[] array, String setting ) + { + for ( T e : array ) + { + getConsoleLogger().debug( "Setting " + setting + " [" + e + "]" ); + } + } + private Classpath getArtifactClasspath( Artifact surefireArtifact ) { - Classpath existing = ClasspathCache.getCachedClassPath( surefireArtifact.getArtifactId() ); + Classpath existing = classpathCache.getCachedClassPath( surefireArtifact.getArtifactId() ); if ( existing == null ) { List items = new ArrayList<>(); - for ( Artifact artifact : dependencyResolver.resolveArtifact( surefireArtifact ).getArtifacts() ) + Set booterArtifacts = + surefireDependencyResolver.resolvePluginArtifact( surefireArtifact ).getArtifacts(); + for ( Artifact artifact : booterArtifacts ) { getConsoleLogger().debug( "Adding to " + getPluginName() + " booter test classpath: " + artifact.getFile().getAbsolutePath() @@ -2570,7 +2677,7 @@ private Classpath getArtifactClasspath( Artifact surefireArtifact ) items.add( artifact.getFile().getAbsolutePath() ); } existing = new Classpath( items ); - ClasspathCache.setCachedClasspath( surefireArtifact.getArtifactId(), existing ); + classpathCache.setCachedClasspath( surefireArtifact.getArtifactId(), existing ); } return existing; } @@ -2666,7 +2773,7 @@ private void warnIfDefunctGroupsCombinations() + "is picking up an old junit version" ); } throw new MojoFailureException( "groups/excludedGroups require TestNG, JUnit48+ or JUnit 5 " - + "on project test classpath" ); + + "(a specific engine required on classpath) on project test classpath" ); } } @@ -2790,7 +2897,7 @@ public Set getProviderClasspath() { Artifact surefireArtifact = getBooterArtifact(); String version = surefireArtifact.getBaseVersion(); - return dependencyResolver.getProviderClasspath( "surefire-testng", version ); + return surefireDependencyResolver.getProviderClasspath( "surefire-testng", version ); } } @@ -2821,7 +2928,7 @@ public Set getProviderClasspath() // add the JUnit provider as default - it doesn't require JUnit to be present, // since it supports POJO tests. String version = surefireBooterArtifact.getBaseVersion(); - return dependencyResolver.getProviderClasspath( "surefire-junit3", version ); + return surefireDependencyResolver.getProviderClasspath( "surefire-junit3", version ); } } @@ -2860,18 +2967,23 @@ public void addProviderProperties() public Set getProviderClasspath() { String version = surefireBooterArtifact.getBaseVersion(); - return dependencyResolver.getProviderClasspath( "surefire-junit4", version ); + return surefireDependencyResolver.getProviderClasspath( "surefire-junit4", version ); } } final class JUnitPlatformProviderInfo implements ProviderInfo { - private final Artifact junitArtifact; + private static final String PROVIDER_DEP_GID = "org.junit.platform"; + private static final String PROVIDER_DEP_AID = "junit-platform-launcher"; + + private final Artifact junitPlatformArtifact; + private final TestClassPath testClasspath; - JUnitPlatformProviderInfo( Artifact junitArtifact ) + JUnitPlatformProviderInfo( Artifact junitPlatformArtifact, TestClassPath testClasspath ) { - this.junitArtifact = junitArtifact; + this.junitPlatformArtifact = junitPlatformArtifact; + this.testClasspath = testClasspath; } @Override @@ -2884,7 +2996,7 @@ public String getProviderName() @Override public boolean isApplicable() { - return junitArtifact != null; + return junitPlatformArtifact != null; } @Override @@ -2895,10 +3007,134 @@ public void addProviderProperties() @Override @Nonnull - public Set getProviderClasspath() + public Set getProviderClasspath() throws MojoExecutionException { - String version = surefireBooterArtifact.getBaseVersion(); - return dependencyResolver.getProviderClasspath( "surefire-junit-platform", version ); + String surefireVersion = surefireBooterArtifact.getBaseVersion(); + Map providerArtifacts = + surefireDependencyResolver.getProviderClasspathAsMap( "surefire-junit-platform", surefireVersion ); + Map testDependencies = testClasspath.getTestDependencies(); + + if ( hasDependencyPlatformEngine( testDependencies ) ) + { + String filterTestDependency = "org.junit.platform:junit-platform-engine"; + getConsoleLogger().debug( "Test dependencies contain " + filterTestDependency ); + narrowProviderDependencies( filterTestDependency, providerArtifacts, testDependencies ); + } + else + { + ProjectBuildingRequest request = getSession().getProjectBuildingRequest(); + Collection pluginDependencies = getPluginDescriptor().getPlugin().getDependencies(); + Set engines = + surefireDependencyResolver.resolvePluginDependencies( request, pluginDependencies ); + if ( hasDependencyPlatformEngine( engines ) ) + { + Map engineArtifacts = artifactMapByVersionlessId( engines ); + providerArtifacts.putAll( engineArtifacts ); + alignVersions( providerArtifacts, engineArtifacts ); + } + else if ( hasDependencyJupiterAPI( testDependencies ) ) + { + String engineGroupId = "org.junit.jupiter"; + String engineArtifactId = "junit-jupiter-engine"; + String engineCoordinates = engineGroupId + ":" + engineArtifactId; + String api = "org.junit.jupiter:junit-jupiter-api"; + getConsoleLogger().debug( "Test dependencies contain " + api + ". Resolving " + engineCoordinates ); + String engineVersion = testDependencies.get( api ).getBaseVersion(); + addEngineByApi( engineGroupId, engineArtifactId, engineVersion, + providerArtifacts, testDependencies ); + } + } + providerArtifacts.keySet().removeAll( testDependencies.keySet() ); + return new LinkedHashSet<>( providerArtifacts.values() ); + } + + private void addEngineByApi( String engineGroupId, String engineArtifactId, String engineVersion, + Map providerArtifacts, Map testDependencies ) + { + providerArtifacts.keySet().removeAll( testDependencies.keySet() ); + for ( Artifact dep : resolve( engineGroupId, engineArtifactId, engineVersion, null, "jar" ) ) + { + String key = dep.getGroupId() + ":" + dep.getArtifactId(); + if ( !testDependencies.containsKey( key ) ) + { + providerArtifacts.put( key, dep ); + } + } + alignVersions( providerArtifacts, testDependencies ); + } + + private void narrowProviderDependencies( String filterTestDependency, + Map providerArtifacts, + Map testDependencies ) + { + Artifact engine = testDependencies.get( filterTestDependency ); + String groupId = engine.getGroupId(); + String artifactId = engine.getArtifactId(); + String version = engine.getBaseVersion(); + String classifier = engine.getClassifier(); + String type = engine.getType(); + for ( Artifact engineDep : resolve( groupId, artifactId, version, classifier, type ) ) + { + providerArtifacts.remove( engineDep.getGroupId() + ":" + engineDep.getArtifactId() ); + getConsoleLogger().debug( "Removed artifact " + engineDep + + " from provider. Already appears in test classpath." ); + } + alignVersions( providerArtifacts, testDependencies ); + } + + private void alignVersions( Map providerArtifacts, + Map referencedDependencies ) + { + String version = referencedDependencies.get( "org.junit.platform:junit-platform-commons" ).getBaseVersion(); + for ( Artifact launcherArtifact : resolve( PROVIDER_DEP_GID, PROVIDER_DEP_AID, version, null, "jar" ) ) + { + String key = launcherArtifact.getGroupId() + ":" + launcherArtifact.getArtifactId(); + if ( providerArtifacts.containsKey( key ) ) + { + providerArtifacts.put( key, launcherArtifact ); + } + } + } + + private Set resolve( String g, String a, String v, String c, String t ) + { + ArtifactHandler handler = junitPlatformArtifact.getArtifactHandler(); + Artifact artifact = new DefaultArtifact( g, a, v, null, t, c, handler ); + getConsoleLogger().debug( "Resolving artifact " + g + ":" + a + ":" + v ); + Set r = surefireDependencyResolver.resolveProjectArtifact( artifact ).getArtifacts(); + getConsoleLogger().debug( "Resolved artifact " + g + ":" + a + ":" + v + " to " + r ); + return r; + } + + private boolean hasDependencyJupiterAPI( Map dependencies ) + { + return dependencies.containsKey( "org.junit.jupiter:junit-jupiter-api" ) + || hasGroupArtifactId( "org.junit.jupiter", "junit-jupiter-api", getProject().getArtifact() ); + } + + private boolean hasDependencyPlatformEngine( Map dependencies ) + { + return dependencies.containsKey( "org.junit.platform:junit-platform-engine" ) + || hasGroupArtifactId( "org.junit.platform", "junit-platform-engine", getProject().getArtifact() ); + } + + private boolean hasDependencyPlatformEngine( Collection dependencies ) + { + if ( hasGroupArtifactId( "org.junit.platform", "junit-platform-engine", getProject().getArtifact() ) ) + { + return true; + } + + for ( Artifact dependency : dependencies ) + { + if ( dependency.getGroupId().equals( "org.junit.platform" ) + && dependency.getArtifactId().equals( "junit-platform-engine" ) ) + { + return true; + } + } + + return false; } } @@ -2946,7 +3182,7 @@ public void addProviderProperties() throws MojoExecutionException public Set getProviderClasspath() { String version = surefireBooterArtifact.getBaseVersion(); - return dependencyResolver.getProviderClasspath( "surefire-junit47", version ); + return surefireDependencyResolver.getProviderClasspath( "surefire-junit47", version ); } } @@ -2994,8 +3230,8 @@ public void addProviderProperties() throws MojoExecutionException @Nonnull public Set getProviderClasspath() { - return dependencyResolver.addProviderToClasspath( getPluginArtifactMap(), getMojoArtifact(), - getCommonArtifact(), getApiArtifact(), getLoggerApiArtifact() ); + return surefireDependencyResolver.addProviderToClasspath( getPluginArtifactMap(), getMojoArtifact(), + getApiArtifact(), getLoggerApiArtifact() ); } } @@ -3177,7 +3413,6 @@ public void setProjectArtifactMap( Map projectArtifactMap ) this.projectArtifactMap = projectArtifactMap; } - public String getReportNameSuffix() { return reportNameSuffix; @@ -3306,17 +3541,6 @@ public void setJunitArtifactName( String junitArtifactName ) this.junitArtifactName = junitArtifactName; } - public String getJunitPlatformArtifactName() - { - return junitPlatformArtifactName; - } - - @SuppressWarnings( "UnusedDeclaration" ) - public void setJunitPlatformArtifactName( String junitPlatformArtifactName ) - { - this.junitPlatformArtifactName = junitPlatformArtifactName; - } - public String getTestNGArtifactName() { return testNGArtifactName; @@ -3424,15 +3648,15 @@ public void setTrimStackTrace( boolean trimStackTrace ) this.trimStackTrace = trimStackTrace; } - public ArtifactFactory getArtifactFactory() + public List getProjectRemoteRepositories() { - return artifactFactory; + return projectRemoteRepositories; } @SuppressWarnings( "UnusedDeclaration" ) - public void setArtifactFactory( ArtifactFactory artifactFactory ) + public void setProjectRemoteRepositories( List projectRemoteRepositories ) { - this.artifactFactory = artifactFactory; + this.projectRemoteRepositories = projectRemoteRepositories; } public List getRemoteRepositories() @@ -3530,6 +3754,12 @@ public void setDependenciesToScan( String[] dependenciesToScan ) this.dependenciesToScan = dependenciesToScan; } + @SuppressWarnings( "UnusedDeclaration" ) + void setPluginDescriptor( PluginDescriptor pluginDescriptor ) + { + this.pluginDescriptor = pluginDescriptor; + } + public PluginDescriptor getPluginDescriptor() { return pluginDescriptor; @@ -3643,4 +3873,31 @@ else if ( forkMode.equals( FORK_NEVER ) || forkMode.equals( FORK_ONCE ) throw new IllegalArgumentException( "Fork mode " + forkMode + " is not a legal value" ); } } + + private static final class ClasspathCache + { + private final Map classpaths = new HashMap<>( 4 ); + + private Classpath getCachedClassPath( @Nonnull String artifactId ) + { + return classpaths.get( artifactId ); + } + + private void setCachedClasspath( @Nonnull String key, @Nonnull Classpath classpath ) + { + classpaths.put( key, classpath ); + } + + private Classpath setCachedClasspath( @Nonnull String key, @Nonnull Set artifacts ) + { + Collection files = new ArrayList<>(); + for ( Artifact artifact : artifacts ) + { + files.add( artifact.getFile().getAbsolutePath() ); + } + Classpath classpath = new Classpath( files ); + setCachedClasspath( key, classpath ); + return classpath; + } + } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ClasspathCache.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ClasspathCache.java index 7ba7b5475f..6dbaf29f92 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ClasspathCache.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ClasspathCache.java @@ -32,6 +32,7 @@ /** * @author Kristian Rosenvold */ +@Deprecated public class ClasspathCache { private static final ConcurrentHashMap CLASSPATHS = diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java index 81830ca4d4..835fb89bbc 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/CommonReflector.java @@ -19,15 +19,17 @@ * under the License. */ -import java.io.File; -import java.lang.reflect.Constructor; - +import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.plugin.surefire.report.DefaultReporterFactory; import org.apache.maven.surefire.booter.SurefireReflector; import org.apache.maven.surefire.util.SurefireReflectionException; import javax.annotation.Nonnull; +import java.io.File; +import java.lang.reflect.Constructor; import static org.apache.maven.surefire.util.ReflectionUtils.getConstructor; import static org.apache.maven.surefire.util.ReflectionUtils.instantiateObject; @@ -40,6 +42,9 @@ public class CommonReflector { private final Class startupReportConfiguration; private final Class consoleLogger; + private final Class statelessTestsetReporter; + private final Class consoleOutputReporter; + private final Class statelessTestsetInfoReporter; private final ClassLoader surefireClassLoader; public CommonReflector( @Nonnull ClassLoader surefireClassLoader ) @@ -50,6 +55,10 @@ public CommonReflector( @Nonnull ClassLoader surefireClassLoader ) { startupReportConfiguration = surefireClassLoader.loadClass( StartupReportConfiguration.class.getName() ); consoleLogger = surefireClassLoader.loadClass( ConsoleLogger.class.getName() ); + statelessTestsetReporter = surefireClassLoader.loadClass( SurefireStatelessReporter.class.getName() ); + consoleOutputReporter = surefireClassLoader.loadClass( SurefireConsoleOutputReporter.class.getName() ); + statelessTestsetInfoReporter = + surefireClassLoader.loadClass( SurefireStatelessTestsetInfoReporter.class.getName() ); } catch ( ClassNotFoundException e ) { @@ -70,18 +79,23 @@ public Object createReportingReporterFactory( @Nonnull StartupReportConfiguratio private Object createStartupReportConfiguration( @Nonnull StartupReportConfiguration reporterConfiguration ) { Constructor constructor = getConstructor( startupReportConfiguration, boolean.class, boolean.class, - String.class, boolean.class, boolean.class, File.class, - boolean.class, String.class, File.class, boolean.class, - int.class, String.class, String.class, boolean.class ); + String.class, boolean.class, File.class, + boolean.class, String.class, File.class, boolean.class, + int.class, String.class, String.class, boolean.class, + statelessTestsetReporter, consoleOutputReporter, + statelessTestsetInfoReporter ); //noinspection BooleanConstructorCall Object[] params = { reporterConfiguration.isUseFile(), reporterConfiguration.isPrintSummary(), reporterConfiguration.getReportFormat(), reporterConfiguration.isRedirectTestOutputToFile(), - reporterConfiguration.isDisableXmlReport(), reporterConfiguration.getReportsDirectory(), + reporterConfiguration.getReportsDirectory(), reporterConfiguration.isTrimStackTrace(), reporterConfiguration.getReportNameSuffix(), reporterConfiguration.getStatisticsFile(), reporterConfiguration.isRequiresRunHistory(), reporterConfiguration.getRerunFailingTestsCount(), reporterConfiguration.getXsdSchemaLocation(), - reporterConfiguration.getEncoding().name(), reporterConfiguration.isForkMode() }; + reporterConfiguration.getEncoding().name(), reporterConfiguration.isForkMode(), + reporterConfiguration.getXmlReporter().clone( surefireClassLoader ), + reporterConfiguration.getConsoleOutputReporter().clone( surefireClassLoader ), + reporterConfiguration.getTestsetReporter().clone( surefireClassLoader ) + }; return newInstance( constructor, params ); } - } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java index cb63cc1a3c..fea74fd000 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/ProviderInfo.java @@ -36,7 +36,7 @@ public interface ProviderInfo boolean isApplicable(); @Nonnull - Set getProviderClasspath(); + Set getProviderClasspath() throws MojoExecutionException; void addProviderProperties() throws MojoExecutionException; } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java index 5089973ae9..02ec44b8ef 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/StartupReportConfiguration.java @@ -19,26 +19,32 @@ * under the License. */ -import org.apache.maven.plugin.surefire.report.ConsoleOutputFileReporter; -import org.apache.maven.plugin.surefire.report.DirectConsoleOutput; -import org.apache.maven.plugin.surefire.report.FileReporter; -import org.apache.maven.plugin.surefire.report.StatelessXmlReporter; -import org.apache.maven.plugin.surefire.report.TestcycleConsoleOutputReceiver; +import org.apache.maven.plugin.surefire.extensions.DefaultStatelessReportMojoConfiguration; +import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.plugin.surefire.report.TestSetStats; import org.apache.maven.plugin.surefire.report.WrappedReportEntry; import org.apache.maven.plugin.surefire.runorder.StatisticsReporter; +import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener; +import org.apache.maven.surefire.extensions.StatelessReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener; import javax.annotation.Nonnull; import java.io.File; import java.io.PrintStream; import java.nio.charset.Charset; -import java.util.List; +import java.util.Deque; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.lang3.StringUtils.trimToNull; import static org.apache.maven.plugin.surefire.SurefireHelper.replaceForkThreadsInPath; import static org.apache.maven.plugin.surefire.report.ConsoleReporter.BRIEF; import static org.apache.maven.plugin.surefire.report.ConsoleReporter.PLAIN; -import static org.apache.commons.lang3.StringUtils.trimToNull; /** * All the parameters used to construct reporters @@ -66,8 +72,6 @@ public final class StartupReportConfiguration private final boolean redirectTestOutputToFile; - private final boolean disableXmlReport; - private final File reportsDirectory; private final boolean trimStackTrace; @@ -76,27 +80,33 @@ public final class StartupReportConfiguration private final String xsdSchemaLocation; - private final Map>> testClassMethodRunHistory - = new ConcurrentHashMap<>(); + private final Map> testClassMethodRunHistory = new ConcurrentHashMap<>(); private final Charset encoding; - private boolean isForkMode; + private final boolean isForkMode; + + private final SurefireStatelessReporter xmlReporter; + + private final SurefireConsoleOutputReporter consoleOutputReporter; + + private final SurefireStatelessTestsetInfoReporter testsetReporter; private StatisticsReporter statisticsReporter; @SuppressWarnings( "checkstyle:parameternumber" ) public StartupReportConfiguration( boolean useFile, boolean printSummary, String reportFormat, - boolean redirectTestOutputToFile, boolean disableXmlReport, - @Nonnull File reportsDirectory, boolean trimStackTrace, String reportNameSuffix, - File statisticsFile, boolean requiresRunHistory, int rerunFailingTestsCount, - String xsdSchemaLocation, String encoding, boolean isForkMode ) + boolean redirectTestOutputToFile, + @Nonnull File reportsDirectory, boolean trimStackTrace, String reportNameSuffix, + File statisticsFile, boolean requiresRunHistory, int rerunFailingTestsCount, + String xsdSchemaLocation, String encoding, boolean isForkMode, + SurefireStatelessReporter xmlReporter, SurefireConsoleOutputReporter consoleOutputReporter, + SurefireStatelessTestsetInfoReporter testsetReporter ) { this.useFile = useFile; this.printSummary = printSummary; this.reportFormat = reportFormat; this.redirectTestOutputToFile = redirectTestOutputToFile; - this.disableXmlReport = disableXmlReport; this.reportsDirectory = reportsDirectory; this.trimStackTrace = trimStackTrace; this.reportNameSuffix = reportNameSuffix; @@ -107,8 +117,11 @@ public StartupReportConfiguration( boolean useFile, boolean printSummary, String this.rerunFailingTestsCount = rerunFailingTestsCount; this.xsdSchemaLocation = xsdSchemaLocation; String charset = trimToNull( encoding ); - this.encoding = charset == null ? Charset.defaultCharset() : Charset.forName( charset ); + this.encoding = charset == null ? UTF_8 : Charset.forName( charset ); this.isForkMode = isForkMode; + this.xmlReporter = xmlReporter; + this.consoleOutputReporter = consoleOutputReporter; + this.testsetReporter = testsetReporter; } public boolean isUseFile() @@ -136,11 +149,6 @@ public boolean isRedirectTestOutputToFile() return redirectTestOutputToFile; } - public boolean isDisableXmlReport() - { - return disableXmlReport; - } - public File getReportsDirectory() { return reportsDirectory; @@ -151,44 +159,54 @@ public int getRerunFailingTestsCount() return rerunFailingTestsCount; } - @Deprecated // rename to stateful - public StatelessXmlReporter instantiateStatelessXmlReporter( Integer forkNumber ) + public StatelessReportEventListener instantiateStatelessXmlReporter( + Integer forkNumber ) { - assert forkNumber == null || isForkMode; + assert ( forkNumber == null ) == !isForkMode; // If forking TestNG the suites have same name 'TestSuite' and tend to override report statistics in stateful // reporter, see Surefire1535TestNGParallelSuitesIT. The testClassMethodRunHistory should be isolated. // In the in-plugin execution of parallel JUnit4.7 with rerun the map must be shared because reports and // listeners are in ThreadLocal, see Surefire1122ParallelAndFlakyTestsIT. - Map>> testClassMethodRunHistory + Map> testClassMethodRunHistory = isForkMode - ? new ConcurrentHashMap>>() + ? new ConcurrentHashMap>() : this.testClassMethodRunHistory; - return isDisableXmlReport() - ? null - : new StatelessXmlReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, trimStackTrace, - rerunFailingTestsCount, testClassMethodRunHistory, xsdSchemaLocation ); + DefaultStatelessReportMojoConfiguration xmlReporterConfig = + new DefaultStatelessReportMojoConfiguration( resolveReportsDirectory( forkNumber ), reportNameSuffix, + trimStackTrace, rerunFailingTestsCount, xsdSchemaLocation, testClassMethodRunHistory ); + + return xmlReporter.isDisable() ? null : xmlReporter.createListener( xmlReporterConfig ); } - public FileReporter instantiateFileReporter( Integer forkNumber ) + public StatelessTestsetInfoFileReportEventListener instantiateFileReporter( + Integer forkNumber ) { - return isUseFile() && isBriefOrPlainFormat() - ? new FileReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, encoding ) + return !testsetReporter.isDisable() && isUseFile() && isBriefOrPlainFormat() + ? testsetReporter.createListener( resolveReportsDirectory( forkNumber ), reportNameSuffix, encoding ) : null; } + public StatelessTestsetInfoConsoleReportEventListener instantiateConsoleReporter( + ConsoleLogger consoleLogger ) + { + return !testsetReporter.isDisable() && shouldReportToConsole() + ? testsetReporter.createListener( consoleLogger ) : null; + } + public boolean isBriefOrPlainFormat() { String fmt = getReportFormat(); return BRIEF.equals( fmt ) || PLAIN.equals( fmt ); } - public TestcycleConsoleOutputReceiver instantiateConsoleOutputFileReporter( Integer forkNumber ) + public ConsoleOutputReportEventListener instantiateConsoleOutputFileReporter( Integer forkNum ) { - return isRedirectTestOutputToFile() - ? new ConsoleOutputFileReporter( resolveReportsDirectory( forkNumber ), reportNameSuffix, forkNumber ) - : new DirectConsoleOutput( originalSystemOut, originalSystemErr ); + ConsoleOutputReportEventListener outputReport = isRedirectTestOutputToFile() + ? consoleOutputReporter.createListener( resolveReportsDirectory( forkNum ), reportNameSuffix, forkNum ) + : consoleOutputReporter.createListener( originalSystemOut, originalSystemErr ); + return consoleOutputReporter.isDisable() ? null : outputReport; } public synchronized StatisticsReporter getStatisticsReporter() @@ -215,11 +233,6 @@ public boolean isRequiresRunHistory() return requiresRunHistory; } - public PrintStream getOriginalSystemOut() - { - return originalSystemOut; - } - public String getXsdSchemaLocation() { return xsdSchemaLocation; @@ -239,4 +252,24 @@ private File resolveReportsDirectory( Integer forkNumber ) { return forkNumber == null ? reportsDirectory : replaceForkThreadsInPath( reportsDirectory, forkNumber ); } + + public SurefireStatelessReporter getXmlReporter() + { + return xmlReporter; + } + + public SurefireConsoleOutputReporter getConsoleOutputReporter() + { + return consoleOutputReporter; + } + + public SurefireStatelessTestsetInfoReporter getTestsetReporter() + { + return testsetReporter; + } + + private boolean shouldReportToConsole() + { + return isUseFile() ? isPrintSummary() : isRedirectTestOutputToFile() || isBriefOrPlainFormat(); + } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java index e403433951..16cb6c863c 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireDependencyResolver.java @@ -19,6 +19,7 @@ * under the License. */ +import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; @@ -26,24 +27,32 @@ import java.util.Set; import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; -import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; +import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.OverConstrainedVersionException; import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.project.ProjectBuildingRequest; import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.shared.artifact.filter.resolve.ScopeFilter; +import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult; +import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver; +import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import static java.util.Collections.singletonList; -import static org.apache.maven.artifact.Artifact.SCOPE_TEST; -import static org.apache.maven.artifact.versioning.VersionRange.createFromVersion; +import static java.util.Arrays.asList; +import static org.apache.maven.artifact.Artifact.SCOPE_COMPILE; +import static org.apache.maven.artifact.Artifact.SCOPE_COMPILE_PLUS_RUNTIME; +import static org.apache.maven.artifact.Artifact.SCOPE_RUNTIME; +import static org.apache.maven.artifact.ArtifactUtils.artifactMapByVersionlessId; import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec; /** @@ -73,26 +82,31 @@ final class SurefireDependencyResolver private final RepositorySystem repositorySystem; - private final ArtifactFactory artifactFactory; - private final ConsoleLogger log; private final ArtifactRepository localRepository; - private final List remoteRepositories; + private final List pluginRemoteRepositories; + + private final List projectRemoteRepositories; private final String pluginName; - SurefireDependencyResolver( RepositorySystem repositorySystem, ArtifactFactory artifactFactory, ConsoleLogger log, - ArtifactRepository localRepository, - List remoteRepositories, String pluginName ) + private final DependencyResolver depencencyResolver; + + SurefireDependencyResolver( RepositorySystem repositorySystem, ConsoleLogger log, + ArtifactRepository localRepository, + List pluginRemoteRepositories, + List projectRemoteRepositories, String pluginName, + DependencyResolver depencencyResolver ) { this.repositorySystem = repositorySystem; - this.artifactFactory = artifactFactory; this.log = log; this.localRepository = localRepository; - this.remoteRepositories = remoteRepositories; + this.pluginRemoteRepositories = pluginRemoteRepositories; + this.projectRemoteRepositories = projectRemoteRepositories; this.pluginName = pluginName; + this.depencencyResolver = depencencyResolver; } static boolean isWithinVersionSpec( @Nullable Artifact artifact, @Nonnull String versionSpec ) @@ -119,33 +133,57 @@ static boolean isWithinVersionSpec( @Nullable Artifact artifact, @Nonnull String } } - ArtifactResolutionResult resolveArtifact( Artifact providerArtifact ) + Set resolvePluginDependencies( ProjectBuildingRequest request, Collection pluginDependencies ) + throws MojoExecutionException + { + try + { + Iterable resolvedPluginDependencies = depencencyResolver.resolveDependencies( request, + pluginDependencies, null, ScopeFilter.including( SCOPE_COMPILE, SCOPE_RUNTIME ) ); + + Set resolved = new LinkedHashSet<>(); + for ( ArtifactResult resolvedPluginDependency : resolvedPluginDependencies ) + { + resolved.add( resolvedPluginDependency.getArtifact() ); + } + return resolved; + } + catch ( DependencyResolverException e ) + { + throw new MojoExecutionException( e.getLocalizedMessage(), e ); + } + } + + ArtifactResolutionResult resolvePluginArtifact( Artifact artifact ) { - return resolveArtifact( providerArtifact, null ); + return resolveArtifact( artifact, pluginRemoteRepositories ); } - private ArtifactResolutionResult resolveArtifact( Artifact providerArtifact, @Nullable Artifact excludeArtifact ) + ArtifactResolutionResult resolveProjectArtifact( Artifact artifact ) + { + return resolveArtifact( artifact, projectRemoteRepositories ); + } + + private ArtifactResolutionResult resolveArtifact( Artifact artifact, List repositories ) { ArtifactResolutionRequest request = new ArtifactResolutionRequest() - .setArtifact( providerArtifact ) - .setRemoteRepositories( remoteRepositories ) - .setLocalRepository( localRepository ) - .setResolveTransitively( true ); - if ( excludeArtifact != null ) - { - String pattern = excludeArtifact.getGroupId() + ":" + excludeArtifact.getArtifactId(); - request.setCollectionFilter( new ExcludesArtifactFilter( singletonList( pattern ) ) ); - } + .setArtifact( artifact ) + .setLocalRepository( localRepository ) + .setResolveTransitively( true ) + .setCollectionFilter( new RuntimeArtifactFilter() ) + .setRemoteRepositories( repositories ); + return repositorySystem.resolve( request ); } @Nonnull Set getProviderClasspath( String providerArtifactId, String providerVersion ) { - Artifact providerArtifact = artifactFactory.createDependencyArtifact( PROVIDER_GROUP_ID, - providerArtifactId, createFromVersion( providerVersion ), "jar", null, SCOPE_TEST ); + Dependency provider = toProviderDependency( providerArtifactId, providerVersion ); + + Artifact providerArtifact = repositorySystem.createDependencyArtifact( provider ); - ArtifactResolutionResult result = resolveArtifact( providerArtifact ); + ArtifactResolutionResult result = resolvePluginArtifact( providerArtifact ); if ( log.isDebugEnabled() ) { @@ -160,26 +198,27 @@ Set getProviderClasspath( String providerArtifactId, String providerVe return orderProviderArtifacts( result.getArtifacts() ); } + @Nonnull + Map getProviderClasspathAsMap( String providerArtifactId, String providerVersion ) + { + return artifactMapByVersionlessId( getProviderClasspath( providerArtifactId, providerVersion ) ); + } + Set addProviderToClasspath( Map pluginArtifactMap, Artifact mojoPluginArtifact, - Artifact surefireCommon, Artifact surefireApi, Artifact surefireLoggerApi ) + Artifact surefireApi, Artifact surefireLoggerApi ) { Set providerArtifacts = new LinkedHashSet<>(); - ArtifactResolutionResult artifactResolutionResult = resolveArtifact( mojoPluginArtifact ); + ArtifactResolutionResult artifactResolutionResult = resolvePluginArtifact( mojoPluginArtifact ); for ( Artifact artifact : pluginArtifactMap.values() ) { if ( !artifactResolutionResult.getArtifacts().contains( artifact ) ) { providerArtifacts.add( artifact ); - for ( Artifact dependency : resolveArtifact( artifact ).getArtifacts() ) + for ( Artifact dependency : resolvePluginArtifact( artifact ).getArtifacts() ) { String groupId = dependency.getGroupId(); String artifactId = dependency.getArtifactId(); - if ( groupId.equals( surefireCommon.getGroupId() ) - && artifactId.equals( surefireCommon.getArtifactId() ) ) - { - providerArtifacts.add( surefireCommon ); - } - else if ( groupId.equals( surefireApi.getGroupId() ) + if ( groupId.equals( surefireApi.getGroupId() ) && artifactId.equals( surefireApi.getArtifactId() ) ) { providerArtifacts.add( surefireApi ); @@ -214,4 +253,27 @@ private static Set orderProviderArtifacts( Set providerArtif orderedProviderArtifacts.addAll( providerArtifacts ); return orderedProviderArtifacts; } + + private static Dependency toProviderDependency( String providerArtifactId, String providerVersion ) + { + Dependency dependency = new Dependency(); + dependency.setGroupId( PROVIDER_GROUP_ID ); + dependency.setArtifactId( providerArtifactId ); + dependency.setVersion( providerVersion ); + dependency.setType( "jar" ); + return dependency; + } + + static class RuntimeArtifactFilter implements ArtifactFilter + { + private static final Collection SCOPES = + asList( SCOPE_COMPILE, SCOPE_COMPILE_PLUS_RUNTIME, SCOPE_RUNTIME ); + + @Override + public boolean include( Artifact artifact ) + { + String scope = artifact.getScope(); + return !artifact.isOptional() && ( scope == null || SCOPES.contains( scope ) ); + } + } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/TestClassPath.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/TestClassPath.java index ee8fadbde6..3a37816c0c 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/TestClassPath.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/TestClassPath.java @@ -20,14 +20,13 @@ */ import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.surefire.booter.Classpath; import java.io.File; import java.util.ArrayList; -import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Set; +import java.util.Map; import static java.util.Collections.addAll; import static org.apache.maven.shared.utils.StringUtils.split; @@ -38,45 +37,26 @@ final class TestClassPath private final File classesDirectory; private final File testClassesDirectory; private final String[] additionalClasspathElements; - private final ConsoleLogger logger; TestClassPath( Iterable artifacts, File classesDirectory, File testClassesDirectory, - String[] additionalClasspathElements, - ConsoleLogger logger ) + String[] additionalClasspathElements ) { this.artifacts = artifacts; this.classesDirectory = classesDirectory; this.testClassesDirectory = testClassesDirectory; this.additionalClasspathElements = additionalClasspathElements; - this.logger = logger; } - void avoidArtifactDuplicates( Set providerArtifacts ) + Map getTestDependencies() { + Map artifactMapping = new LinkedHashMap<>(); for ( Artifact artifact : artifacts ) { - Iterator it = providerArtifacts.iterator(); - while ( it.hasNext() ) - { - Artifact providerArtifact = it.next(); - String classifier1 = providerArtifact.getClassifier(); - String classifier2 = artifact.getClassifier(); - if ( providerArtifact.getGroupId().equals( artifact.getGroupId() ) - && providerArtifact.getArtifactId().equals( artifact.getArtifactId() ) - && providerArtifact.getType().equals( artifact.getType() ) - && ( classifier1 == null ? classifier2 == null : classifier1.equals( classifier2 ) ) ) - { - it.remove(); - if ( logger.isDebugEnabled() ) - { - logger.debug( "Removed artifact " + providerArtifact + " from provider. " - + "Already appears in test classpath." ); - } - } - } + artifactMapping.put( artifact.getGroupId() + ":" + artifact.getArtifactId(), artifact ); } + return artifactMapping; } Classpath toClasspath() diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java index 6c57ebc315..692f486bde 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/AbstractClasspathForkConfiguration.java @@ -44,6 +44,7 @@ abstract class AbstractClasspathForkConfiguration @Nonnull Properties modelProperties, @Nullable String argLine, @Nonnull Map environmentVariables, + @Nonnull String[] excludedEnvironmentVariables, boolean debug, int forkCount, boolean reuseForks, @@ -51,7 +52,7 @@ abstract class AbstractClasspathForkConfiguration @Nonnull ConsoleLogger log ) { super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine, - environmentVariables, debug, forkCount, reuseForks, pluginPlatform, log ); + environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log ); } @Override diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java index fe72fceefa..7eacb7485b 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java @@ -23,6 +23,7 @@ import org.apache.maven.surefire.booter.AbstractPathConfiguration; import org.apache.maven.surefire.booter.ClassLoaderConfiguration; import org.apache.maven.surefire.booter.KeyValueSource; +import org.apache.maven.surefire.booter.ProcessCheckerType; import org.apache.maven.surefire.booter.ProviderConfiguration; import org.apache.maven.surefire.booter.StartupConfiguration; import org.apache.maven.surefire.cli.CommandLineOption; @@ -53,6 +54,7 @@ import static org.apache.maven.surefire.booter.BooterConstants.ISTRIMSTACKTRACE; import static org.apache.maven.surefire.booter.BooterConstants.MAIN_CLI_OPTIONS; import static org.apache.maven.surefire.booter.BooterConstants.PLUGIN_PID; +import static org.apache.maven.surefire.booter.BooterConstants.PROCESS_CHECKER; import static org.apache.maven.surefire.booter.BooterConstants.PROVIDER_CONFIGURATION; import static org.apache.maven.surefire.booter.BooterConstants.REPORTSDIRECTORY; import static org.apache.maven.surefire.booter.BooterConstants.REQUESTEDTEST; @@ -98,8 +100,8 @@ class BooterSerializer /** * Does not modify sourceProperties */ - File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterConfiguration, - StartupConfiguration providerConfiguration, Object testSet, boolean readTestsFromInStream, + File serialize( KeyValueSource sourceProperties, ProviderConfiguration providerConfiguration, + StartupConfiguration startupConfiguration, Object testSet, boolean readTestsFromInStream, Long pid, int forkNumber ) throws IOException { @@ -107,13 +109,15 @@ File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterCon properties.setProperty( PLUGIN_PID, pid ); - AbstractPathConfiguration cp = providerConfiguration.getClasspathConfiguration(); + AbstractPathConfiguration cp = startupConfiguration.getClasspathConfiguration(); properties.setClasspath( CLASSPATH, cp.getTestClasspath() ); properties.setClasspath( SUREFIRE_CLASSPATH, cp.getProviderClasspath() ); properties.setProperty( ENABLE_ASSERTIONS, toString( cp.isEnableAssertions() ) ); properties.setProperty( CHILD_DELEGATION, toString( cp.isChildDelegation() ) ); + ProcessCheckerType processChecker = startupConfiguration.getProcessChecker(); + properties.setNullableProperty( PROCESS_CHECKER, processChecker == null ? null : processChecker.getType() ); - TestArtifactInfo testNg = booterConfiguration.getTestArtifact(); + TestArtifactInfo testNg = providerConfiguration.getTestArtifact(); if ( testNg != null ) { properties.setProperty( TESTARTIFACT_VERSION, testNg.getVersion() ); @@ -123,7 +127,7 @@ File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterCon properties.setProperty( FORKTESTSET_PREFER_TESTS_FROM_IN_STREAM, readTestsFromInStream ); properties.setNullableProperty( FORKTESTSET, getTypeEncoded( testSet ) ); - TestRequest testSuiteDefinition = booterConfiguration.getTestSuiteDefinition(); + TestRequest testSuiteDefinition = providerConfiguration.getTestSuiteDefinition(); if ( testSuiteDefinition != null ) { properties.setProperty( SOURCE_DIRECTORY, testSuiteDefinition.getTestSourceDirectory() ); @@ -141,7 +145,7 @@ File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterCon properties.setNullableProperty( RERUN_FAILING_TESTS_COUNT, toString( rerunFailingTestsCount ) ); } - DirectoryScannerParameters directoryScannerParameters = booterConfiguration.getDirScannerParams(); + DirectoryScannerParameters directoryScannerParameters = providerConfiguration.getDirScannerParams(); if ( directoryScannerParameters != null ) { properties.setProperty( FAILIFNOTESTS, toString( directoryScannerParameters.isFailIfNoTests() ) ); @@ -151,31 +155,31 @@ File serialize( KeyValueSource sourceProperties, ProviderConfiguration booterCon properties.setProperty( TEST_CLASSES_DIRECTORY, directoryScannerParameters.getTestClassesDirectory() ); } - final RunOrderParameters runOrderParameters = booterConfiguration.getRunOrderParameters(); + final RunOrderParameters runOrderParameters = providerConfiguration.getRunOrderParameters(); if ( runOrderParameters != null ) { properties.setProperty( RUN_ORDER, RunOrder.asString( runOrderParameters.getRunOrder() ) ); properties.setProperty( RUN_STATISTICS_FILE, runOrderParameters.getRunStatisticsFile() ); } - ReporterConfiguration reporterConfiguration = booterConfiguration.getReporterConfiguration(); + ReporterConfiguration reporterConfiguration = providerConfiguration.getReporterConfiguration(); boolean rep = reporterConfiguration.isTrimStackTrace(); File reportsDirectory = replaceForkThreadsInPath( reporterConfiguration.getReportsDirectory(), forkNumber ); properties.setProperty( ISTRIMSTACKTRACE, rep ); properties.setProperty( REPORTSDIRECTORY, reportsDirectory ); - ClassLoaderConfiguration classLoaderConfig = providerConfiguration.getClassLoaderConfiguration(); + ClassLoaderConfiguration classLoaderConfig = startupConfiguration.getClassLoaderConfiguration(); properties.setProperty( USESYSTEMCLASSLOADER, toString( classLoaderConfig.isUseSystemClassLoader() ) ); properties.setProperty( USEMANIFESTONLYJAR, toString( classLoaderConfig.isUseManifestOnlyJar() ) ); - properties.setProperty( FAILIFNOTESTS, toString( booterConfiguration.isFailIfNoTests() ) ); - properties.setProperty( PROVIDER_CONFIGURATION, providerConfiguration.getProviderClassName() ); - properties.setProperty( FAIL_FAST_COUNT, toString( booterConfiguration.getSkipAfterFailureCount() ) ); - properties.setProperty( SHUTDOWN, booterConfiguration.getShutdown().name() ); - List mainCliOptions = booterConfiguration.getMainCliOptions(); + properties.setProperty( FAILIFNOTESTS, toString( providerConfiguration.isFailIfNoTests() ) ); + properties.setProperty( PROVIDER_CONFIGURATION, startupConfiguration.getProviderClassName() ); + properties.setProperty( FAIL_FAST_COUNT, toString( providerConfiguration.getSkipAfterFailureCount() ) ); + properties.setProperty( SHUTDOWN, providerConfiguration.getShutdown().name() ); + List mainCliOptions = providerConfiguration.getMainCliOptions(); if ( mainCliOptions != null ) { properties.addList( mainCliOptions, MAIN_CLI_OPTIONS ); } - properties.setNullableProperty( SYSTEM_EXIT_TIMEOUT, toString( booterConfiguration.getSystemExitTimeout() ) ); + properties.setNullableProperty( SYSTEM_EXIT_TIMEOUT, toString( providerConfiguration.getSystemExitTimeout() ) ); File surefireTmpDir = forkConfiguration.getTempDirectory(); boolean debug = forkConfiguration.isDebug(); diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java index cf6c67e8a7..72aab989cc 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ClasspathForkConfiguration.java @@ -44,12 +44,14 @@ public final class ClasspathForkConfiguration public ClasspathForkConfiguration( @Nonnull Classpath bootClasspath, @Nonnull File tempDirectory, @Nullable String debugLine, @Nonnull File workingDirectory, @Nonnull Properties modelProperties, @Nullable String argLine, - @Nonnull Map environmentVariables, boolean debug, int forkCount, + @Nonnull Map environmentVariables, + @Nonnull String[] excludedEnvironmentVariables, + boolean debug, int forkCount, boolean reuseForks, @Nonnull Platform pluginPlatform, @Nonnull ConsoleLogger log ) { super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine, - environmentVariables, debug, forkCount, reuseForks, pluginPlatform, log ); + environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log ); } @Override diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java index fa99451234..4ab44355ef 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfiguration.java @@ -59,6 +59,7 @@ public abstract class DefaultForkConfiguration @Nonnull private final Properties modelProperties; @Nullable private final String argLine; @Nonnull private final Map environmentVariables; + @Nonnull private final String[] excludedEnvironmentVariables; private final boolean debug; private final int forkCount; private final boolean reuseForks; @@ -73,6 +74,7 @@ protected DefaultForkConfiguration( @Nonnull Classpath booterClasspath, @Nonnull Properties modelProperties, @Nullable String argLine, @Nonnull Map environmentVariables, + @Nonnull String[] excludedEnvironmentVariables, boolean debug, int forkCount, boolean reuseForks, @@ -86,6 +88,7 @@ protected DefaultForkConfiguration( @Nonnull Classpath booterClasspath, this.modelProperties = modelProperties; this.argLine = argLine; this.environmentVariables = toImmutable( environmentVariables ); + this.excludedEnvironmentVariables = excludedEnvironmentVariables; this.debug = debug; this.forkCount = forkCount; this.reuseForks = reuseForks; @@ -119,7 +122,8 @@ public OutputStreamFlushableCommandline createCommandLine( @Nonnull StartupConfi @Nonnull File dumpLogDirectory ) throws SurefireBooterForkException { - OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline(); + OutputStreamFlushableCommandline cli = + new OutputStreamFlushableCommandline( getExcludedEnvironmentVariables() ); cli.setWorkingDirectory( getWorkingDirectory( forkNumber ).getAbsolutePath() ); @@ -289,6 +293,13 @@ protected Map getEnvironmentVariables() return environmentVariables; } + @Nonnull + @Override + protected String[] getExcludedEnvironmentVariables() + { + return excludedEnvironmentVariables; + } + @Override protected boolean isDebug() { diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java index d45d13d55a..92bebd0656 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkConfiguration.java @@ -45,6 +45,7 @@ public abstract class ForkConfiguration @Nonnull protected abstract Properties getModelProperties(); @Nullable protected abstract String getArgLine(); @Nonnull protected abstract Map getEnvironmentVariables(); + @Nonnull protected abstract String[] getExcludedEnvironmentVariables(); protected abstract boolean isDebug(); protected abstract int getForkCount(); protected abstract boolean isReuseForks(); diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java index 2d3cc42845..2570977606 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ForkStarter.java @@ -92,12 +92,14 @@ import static org.apache.maven.shared.utils.cli.ShutdownHookUtils.addShutDownHook; import static org.apache.maven.shared.utils.cli.ShutdownHookUtils.removeShutdownHook; import static org.apache.maven.surefire.booter.SystemPropertyManager.writePropertiesFile; +import static org.apache.maven.surefire.cli.CommandLineOption.SHOW_ERRORS; import static org.apache.maven.surefire.suite.RunResult.SUCCESS; import static org.apache.maven.surefire.suite.RunResult.failure; import static org.apache.maven.surefire.suite.RunResult.timeout; import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero; import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThread; import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory; +import static org.apache.maven.surefire.util.internal.StringUtils.NL; /** * Starts the fork or runs in-process. @@ -650,11 +652,29 @@ else if ( result == null || result != SUCCESS ) if ( forkClient.isErrorInFork() ) { StackTraceWriter errorInFork = forkClient.getErrorInFork(); - // noinspection ThrowFromFinallyBlock + String errorInForkMessage = + errorInFork == null ? null : errorInFork.getThrowable().getLocalizedMessage(); + boolean showStackTrace = providerConfiguration.getMainCliOptions().contains( SHOW_ERRORS ); + String stackTrace = errorInForkMessage; + if ( showStackTrace ) + { + if ( errorInFork != null ) + { + if ( stackTrace == null ) + { + stackTrace = ""; + } + else + { + stackTrace += NL; + } + stackTrace += errorInFork.writeTrimmedTraceToString(); + } + } + //noinspection ThrowFromFinallyBlock throw new SurefireBooterForkException( "There was an error in the forked process" + detail - + '\n' - + errorInFork.getThrowable().getLocalizedMessage(), cause ); + + ( stackTrace == null ? "" : stackTrace ), cause ); } if ( !forkClient.isSaidGoodBye() ) { @@ -759,7 +779,7 @@ private static ScheduledExecutorService createTimeoutCheckScheduler() private ScheduledFuture triggerPingTimerForShutdown( final TestLessInputStreamBuilder builder ) { - return pingThreadScheduler.scheduleAtFixedRate( new Runnable() + return pingThreadScheduler.scheduleWithFixedDelay( new Runnable() { @Override public void run() @@ -771,7 +791,7 @@ public void run() private ScheduledFuture triggerPingTimerForShutdown( final Iterable streams ) { - return pingThreadScheduler.scheduleAtFixedRate( new Runnable() + return pingThreadScheduler.scheduleWithFixedDelay( new Runnable() { @Override public void run() @@ -786,7 +806,7 @@ public void run() private ScheduledFuture triggerTimeoutCheck() { - return timeoutCheckScheduler.scheduleAtFixedRate( new Runnable() + return timeoutCheckScheduler.scheduleWithFixedDelay( new Runnable() { @Override public void run() diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java index 62fa4c19b3..78e915af07 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfiguration.java @@ -19,6 +19,9 @@ * under the License. */ +import org.apache.commons.compress.archivers.zip.Zip64Mode; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.OutputStreamFlushableCommandline; import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; @@ -28,23 +31,28 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; import java.util.jar.Manifest; +import java.util.zip.Deflater; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.file.Files.isDirectory; import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath; +import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.ClasspathElementUri.absolute; +import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.ClasspathElementUri.relative; import static org.apache.maven.surefire.util.internal.StringUtils.NL; /** @@ -58,12 +66,14 @@ public final class JarManifestForkConfiguration public JarManifestForkConfiguration( @Nonnull Classpath bootClasspath, @Nonnull File tempDirectory, @Nullable String debugLine, @Nonnull File workingDirectory, @Nonnull Properties modelProperties, @Nullable String argLine, - @Nonnull Map environmentVariables, boolean debug, + @Nonnull Map environmentVariables, + @Nonnull String[] excludedEnvironmentVariables, + boolean debug, int forkCount, boolean reuseForks, @Nonnull Platform pluginPlatform, @Nonnull ConsoleLogger log ) { super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine, - environmentVariables, debug, forkCount, reuseForks, pluginPlatform, log ); + environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log ); } @Override @@ -105,12 +115,15 @@ private File createJar( @Nonnull List classPath, @Nonnull String startCl file.deleteOnExit(); } Path parent = file.getParentFile().toPath(); - FileOutputStream fos = new FileOutputStream( file ); - try ( JarOutputStream jos = new JarOutputStream( fos ) ) + OutputStream fos = new BufferedOutputStream( new FileOutputStream( file ), 64 * 1024 ); + + try ( ZipArchiveOutputStream zos = new ZipArchiveOutputStream( fos ) ) { - jos.setLevel( JarOutputStream.STORED ); - JarEntry je = new JarEntry( "META-INF/MANIFEST.MF" ); - jos.putNextEntry( je ); + zos.setUseZip64( Zip64Mode.Never ); + zos.setLevel( Deflater.NO_COMPRESSION ); + + ZipArchiveEntry ze = new ZipArchiveEntry( "META-INF/MANIFEST.MF" ); + zos.putArchiveEntry( ze ); Manifest man = new Manifest(); @@ -142,10 +155,9 @@ private File createJar( @Nonnull List classPath, @Nonnull String startCl man.getMainAttributes().putValue( "Class-Path", cp.toString().trim() ); man.getMainAttributes().putValue( "Main-Class", startClassName ); - man.write( jos ); + man.write( zos ); - jos.closeEntry(); - jos.flush(); + zos.closeArchiveEntry(); return file; } @@ -168,14 +180,11 @@ static ClasspathElementUri toClasspathElementUri( @Nonnull Path parent, @Nonnull Path classPathElement, @Nonnull File dumpLogDirectory, boolean dumpError ) - throws IOException { try { - String relativeUriPath = relativize( parent, classPathElement ) - .replace( '\\', '/' ); - - return new ClasspathElementUri( new URI( null, relativeUriPath, null ) ); + String relativePath = relativize( parent, classPathElement ); + return relative( escapeUri( relativePath, UTF_8 ) ); } catch ( IllegalArgumentException e ) { @@ -190,15 +199,7 @@ static ClasspathElementUri toClasspathElementUri( @Nonnull Path parent, .dumpStreamText( error, dumpLogDirectory ); } - return new ClasspathElementUri( toAbsoluteUri( classPathElement ) ); - } - catch ( URISyntaxException e ) - { - // This is really unexpected, so fail - throw new IOException( "Could not create a relative path " - + classPathElement - + " against " - + parent, e ); + return absolute( toAbsoluteUri( classPathElement ) ); } } @@ -207,16 +208,37 @@ static final class ClasspathElementUri final String uri; final boolean absolute; - ClasspathElementUri( String uri ) + private ClasspathElementUri( String uri, boolean absolute ) { this.uri = uri; - absolute = true; + this.absolute = absolute; } - ClasspathElementUri( URI uri ) + static ClasspathElementUri absolute( String uri ) + { + return new ClasspathElementUri( uri, true ); + } + + static ClasspathElementUri relative( String uri ) + { + return new ClasspathElementUri( uri, false ); + } + } + + static String escapeUri( String input, Charset encoding ) + { + try + { + String uriFormEncoded = URLEncoder.encode( input, encoding.name() ); + + String uriPathEncoded = uriFormEncoded.replaceAll( "\\+", "%20" ); + uriPathEncoded = uriPathEncoded.replaceAll( "%2F|%5C", "/" ); + + return uriPathEncoded; + } + catch ( UnsupportedEncodingException e ) { - this.uri = uri.toASCIIString(); - absolute = false; + throw new IllegalStateException( "avoided by using Charset" ); } } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java index 48e74d9e8a..af38bc5141 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/ModularClasspathForkConfiguration.java @@ -28,15 +28,11 @@ import org.apache.maven.surefire.booter.ModularClasspathConfiguration; import org.apache.maven.surefire.booter.StartupConfiguration; import org.apache.maven.surefire.booter.SurefireBooterForkException; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ModuleVisitor; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.File; -import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.util.Collection; @@ -50,7 +46,6 @@ import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath; import static org.apache.maven.shared.utils.StringUtils.replace; import static org.apache.maven.surefire.util.internal.StringUtils.NL; -import static org.objectweb.asm.Opcodes.ASM7; /** * @author Tibor Digana (tibor17) @@ -67,6 +62,7 @@ public ModularClasspathForkConfiguration( @Nonnull Classpath bootClasspath, @Nonnull Properties modelProperties, @Nullable String argLine, @Nonnull Map environmentVariables, + @Nonnull String[] excludedEnvironmentVariables, boolean debug, @Nonnegative int forkCount, boolean reuseForks, @@ -74,7 +70,7 @@ public ModularClasspathForkConfiguration( @Nonnull Classpath bootClasspath, @Nonnull ConsoleLogger log ) { super( bootClasspath, tempDirectory, debugLine, workingDirectory, modelProperties, argLine, - environmentVariables, debug, forkCount, reuseForks, pluginPlatform, log ); + environmentVariables, excludedEnvironmentVariables, debug, forkCount, reuseForks, pluginPlatform, log ); } @Override @@ -91,13 +87,13 @@ protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli, ModularClasspath modularClasspath = modularClasspathConfiguration.getModularClasspath(); - File descriptor = modularClasspath.getModuleDescriptor(); + String moduleName = modularClasspath.getModuleNameFromDescriptor(); List modulePath = modularClasspath.getModulePath(); Collection packages = modularClasspath.getPackages(); File patchFile = modularClasspath.getPatchFile(); List classpath = toCompleteClasspath( config ); - File argsFile = createArgsFile( descriptor, modulePath, classpath, packages, patchFile, startClass ); + File argsFile = createArgsFile( moduleName, modulePath, classpath, packages, patchFile, startClass ); cli.createArg().setValue( "@" + escapeToPlatformPath( argsFile.getAbsolutePath() ) ); } @@ -111,7 +107,7 @@ protected void resolveClasspath( @Nonnull OutputStreamFlushableCommandline cli, } @Nonnull - File createArgsFile( @Nonnull File moduleDescriptor, @Nonnull List modulePath, + File createArgsFile( @Nonnull String moduleName, @Nonnull List modulePath, @Nonnull List classPath, @Nonnull Collection packages, @Nonnull File patchFile, @Nonnull String startClassName ) throws IOException @@ -168,8 +164,6 @@ File createArgsFile( @Nonnull File moduleDescriptor, @Nonnull List modul .append( NL ); } - final String moduleName = toModuleName( moduleDescriptor ); - args.append( "--patch-module" ) .append( NL ) .append( moduleName ) @@ -217,27 +211,4 @@ File createArgsFile( @Nonnull File moduleDescriptor, @Nonnull List modul return surefireArgs; } } - - @Nonnull - String toModuleName( @Nonnull File moduleDescriptor ) throws IOException - { - if ( !moduleDescriptor.isFile() ) - { - throw new IOException( "No such Jigsaw module-descriptor exists " + moduleDescriptor.getAbsolutePath() ); - } - - final StringBuilder sb = new StringBuilder(); - new ClassReader( new FileInputStream( moduleDescriptor ) ).accept( new ClassVisitor( ASM7 ) - { - @Override - public ModuleVisitor visitModule( String name, int access, String version ) - { - sb.setLength( 0 ); - sb.append( name ); - return super.visitModule( name, access, version ); - } - }, 0 ); - - return sb.toString(); - } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushReceiver.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushReceiver.java new file mode 100644 index 0000000000..131661d205 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushReceiver.java @@ -0,0 +1,47 @@ +package org.apache.maven.plugin.surefire.booterclient.lazytestprovider; + +/* + * 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.IOException; +import java.io.OutputStream; + +/** + * Facade flushing {@link OutputStream} and isolating the stream in client. + */ +final class OutputStreamFlushReceiver + implements FlushReceiver +{ + private final OutputStream outputStream; + + /** + * Wraps an output stream in order to delegate a flush. + */ + OutputStreamFlushReceiver( OutputStream outputStream ) + { + this.outputStream = outputStream; + } + + @Override + public void flush() + throws IOException + { + outputStream.flush(); + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushableCommandline.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushableCommandline.java index eb1ab5b61a..e22b8df2ca 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushableCommandline.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushableCommandline.java @@ -19,9 +19,13 @@ * under the License. */ -import java.io.IOException; -import java.io.OutputStream; +import java.util.Collection; +import java.util.Collections; +import java.util.Properties; +import java.util.concurrent.ConcurrentLinkedDeque; + import org.apache.maven.shared.utils.cli.CommandLineException; +import org.apache.maven.shared.utils.cli.CommandLineUtils; import org.apache.maven.shared.utils.cli.Commandline; /** @@ -35,29 +39,37 @@ public class OutputStreamFlushableCommandline extends Commandline implements FlushReceiverProvider { + private final Collection excludedEnvironmentVariables; + private volatile FlushReceiver flushReceiver; + /** - * Wraps an output stream in order to delegate a flush. + * for testing purposes only */ - private final class OutputStreamFlushReceiver - implements FlushReceiver + public OutputStreamFlushableCommandline() { - private final OutputStream outputStream; + this( new String[0] ); + } - private OutputStreamFlushReceiver( OutputStream outputStream ) - { - this.outputStream = outputStream; - } + public OutputStreamFlushableCommandline( String[] excludedEnvironmentVariables ) + { + this.excludedEnvironmentVariables = new ConcurrentLinkedDeque<>(); + Collections.addAll( this.excludedEnvironmentVariables, excludedEnvironmentVariables ); + } + + @Override + public final void addSystemEnvironment() + { + Properties systemEnvVars = CommandLineUtils.getSystemEnvVars(); - @Override - public void flush() - throws IOException + for ( String key : systemEnvVars.stringPropertyNames() ) { - outputStream.flush(); + if ( !excludedEnvironmentVariables.contains( key ) ) + { + addEnvironment( key, systemEnvVars.getProperty( key ) ); + } } } - private volatile FlushReceiver flushReceiver; - @Override public Process execute() throws CommandLineException @@ -77,5 +89,4 @@ public FlushReceiver getFlushReceiver() { return flushReceiver; } - -} \ No newline at end of file +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java index 436566f0dc..f2a934f28c 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClient.java @@ -26,6 +26,7 @@ import org.apache.maven.surefire.report.ConsoleOutputReceiver; import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.RunListener; +import org.apache.maven.surefire.report.RunMode; import org.apache.maven.surefire.report.StackTraceWriter; import org.apache.maven.surefire.report.TestSetReportEntry; @@ -33,44 +34,21 @@ import java.io.File; import java.io.IOException; import java.io.StringReader; -import java.nio.ByteBuffer; -import java.util.Collections; import java.util.Map; import java.util.Queue; import java.util.Set; -import java.util.StringTokenizer; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -import static java.lang.Integer.decode; import static java.lang.System.currentTimeMillis; import static java.util.Collections.unmodifiableMap; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_BYE; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_CONSOLE; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_DEBUG; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_ERROR; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_NEXT_TEST; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_STDERR; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_STDOUT; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_STOP_ON_NEXT_TEST; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_SYSPROPS; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TESTSET_COMPLETED; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TESTSET_STARTING; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TEST_ASSUMPTIONFAILURE; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TEST_ERROR; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TEST_FAILED; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TEST_SKIPPED; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TEST_STARTING; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_TEST_SUCCEEDED; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_WARNING; import static org.apache.maven.surefire.booter.Shutdown.KILL; import static org.apache.maven.surefire.report.CategorizedReportEntry.reportEntry; +import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank; -import static org.apache.maven.surefire.util.internal.StringUtils.unescapeBytes; -import static org.apache.maven.surefire.util.internal.StringUtils.unescapeString; // todo move to the same package with ForkStarter @@ -95,11 +73,13 @@ public class ForkClient private final Queue testsInProgress = new ConcurrentLinkedQueue<>(); /** - * {@code testSetStartedAt} is set to non-zero after received - * {@link org.apache.maven.surefire.booter.ForkingRunListener#BOOTERCODE_TESTSET_STARTING test-set}. + * testSetStartedAt is set to non-zero after received + * {@link org.apache.maven.surefire.booter.ForkedChannelEncoder#testSetStarting(ReportEntry, boolean)}. */ private final AtomicLong testSetStartedAt = new AtomicLong( START_TIME_ZERO ); + private final ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + private final ConsoleLogger log; /** @@ -112,6 +92,8 @@ public class ForkClient /** * Used by single Thread started by {@link ThreadedStreamConsumer} and therefore does not need to be volatile. */ + private final ForkedChannelDecoderErrorHandler errorHandler; + private RunListener testSetReporter; /** @@ -129,8 +111,228 @@ public ForkClient( DefaultReporterFactory defaultReporterFactory, NotifiableTest this.log = log; this.printedErrorStream = printedErrorStream; this.forkNumber = forkNumber; + decoder.setTestSetStartingListener( new TestSetStartingListener() ); + decoder.setTestSetCompletedListener( new TestSetCompletedListener() ); + decoder.setTestStartingListener( new TestStartingListener() ); + decoder.setTestSucceededListener( new TestSucceededListener() ); + decoder.setTestFailedListener( new TestFailedListener() ); + decoder.setTestSkippedListener( new TestSkippedListener() ); + decoder.setTestErrorListener( new TestErrorListener() ); + decoder.setTestAssumptionFailureListener( new TestAssumptionFailureListener() ); + decoder.setSystemPropertiesListener( new SystemPropertiesListener() ); + decoder.setStdOutListener( new StdOutListener() ); + decoder.setStdErrListener( new StdErrListener() ); + decoder.setConsoleInfoListener( new ConsoleListener() ); + decoder.setAcquireNextTestListener( new AcquireNextTestListener() ); + decoder.setConsoleErrorListener( new ErrorListener() ); + decoder.setByeListener( new ByeListener() ); + decoder.setStopOnNextTestListener( new StopOnNextTestListener() ); + decoder.setConsoleDebugListener( new DebugListener() ); + decoder.setConsoleWarningListener( new WarningListener() ); + errorHandler = new ErrorHandler(); + } + + private final class ErrorHandler implements ForkedChannelDecoderErrorHandler + { + @Override + public void handledError( String line, Throwable e ) + { + logStreamWarning( line, e ); + } + } + + private final class TestSetStartingListener + implements ForkedProcessReportEventListener + { + @Override + public void handle( RunMode runMode, TestSetReportEntry reportEntry ) + { + getTestSetReporter().testSetStarting( reportEntry ); + setCurrentStartTime(); + } + } + + private final class TestSetCompletedListener + implements ForkedProcessReportEventListener + { + @Override + public void handle( RunMode runMode, TestSetReportEntry reportEntry ) + { + testsInProgress.clear(); + TestSetReportEntry entry = reportEntry( reportEntry.getSourceName(), reportEntry.getSourceText(), + reportEntry.getName(), reportEntry.getNameText(), + reportEntry.getGroup(), reportEntry.getStackTraceWriter(), reportEntry.getElapsed(), + reportEntry.getMessage(), getTestVmSystemProperties() ); + getTestSetReporter().testSetCompleted( entry ); + } + } + + private final class TestStartingListener implements ForkedProcessReportEventListener + { + @Override + public void handle( RunMode runMode, ReportEntry reportEntry ) + { + testsInProgress.offer( reportEntry.getSourceName() ); + getTestSetReporter().testStarting( reportEntry ); + } + } + + private final class TestSucceededListener implements ForkedProcessReportEventListener + { + @Override + public void handle( RunMode runMode, ReportEntry reportEntry ) + { + testsInProgress.remove( reportEntry.getSourceName() ); + getTestSetReporter().testSucceeded( reportEntry ); + } + } + + private final class TestFailedListener implements ForkedProcessReportEventListener + { + @Override + public void handle( RunMode runMode, ReportEntry reportEntry ) + { + testsInProgress.remove( reportEntry.getSourceName() ); + getTestSetReporter().testFailed( reportEntry ); + } + } + + private final class TestSkippedListener implements ForkedProcessReportEventListener + { + @Override + public void handle( RunMode runMode, ReportEntry reportEntry ) + { + testsInProgress.remove( reportEntry.getSourceName() ); + getTestSetReporter().testSkipped( reportEntry ); + } + } + + private final class TestErrorListener implements ForkedProcessReportEventListener + { + @Override + public void handle( RunMode runMode, ReportEntry reportEntry ) + { + testsInProgress.remove( reportEntry.getSourceName() ); + getTestSetReporter().testError( reportEntry ); + } + } + + private final class TestAssumptionFailureListener implements ForkedProcessReportEventListener + { + @Override + public void handle( RunMode runMode, ReportEntry reportEntry ) + { + testsInProgress.remove( reportEntry.getSourceName() ); + getTestSetReporter().testAssumptionFailure( reportEntry ); + } + } + + private final class SystemPropertiesListener implements ForkedProcessPropertyEventListener + { + @Override + public void handle( RunMode runMode, String key, String value ) + { + testVmSystemProperties.put( key, value ); + } + } + + private final class StdOutListener implements ForkedProcessStandardOutErrEventListener + { + @Override + public void handle( RunMode runMode, String output, boolean newLine ) + { + writeTestOutput( output, newLine, true ); + } + } + + private final class StdErrListener implements ForkedProcessStandardOutErrEventListener + { + @Override + public void handle( RunMode runMode, String output, boolean newLine ) + { + writeTestOutput( output, newLine, false ); + } + } + + private final class ConsoleListener implements ForkedProcessStringEventListener + { + @Override + public void handle( String msg ) + { + getOrCreateConsoleLogger() + .info( msg ); + } + } + + private final class AcquireNextTestListener implements ForkedProcessEventListener + { + @Override + public void handle() + { + notifiableTestStream.provideNewTest(); + } + } + + private class ErrorListener implements ForkedProcessStackTraceEventListener + { + @Override + public void handle( String msg, String smartStackTrace, String stackTrace ) + { + if ( errorInFork == null ) + { + errorInFork = deserializeStackTraceWriter( msg, smartStackTrace, stackTrace ); + if ( msg != null ) + { + getOrCreateConsoleLogger() + .error( msg ); + } + } + dumpToLoFile( msg, null ); + } + } + + private final class ByeListener implements ForkedProcessEventListener + { + @Override + public void handle() + { + saidGoodBye = true; + notifiableTestStream.acknowledgeByeEventReceived(); + } + } + + private final class StopOnNextTestListener implements ForkedProcessEventListener + { + @Override + public void handle() + { + stopOnNextTest(); + } + } + + private final class DebugListener implements ForkedProcessStringEventListener + { + @Override + public void handle( String msg ) + { + getOrCreateConsoleLogger() + .debug( msg ); + } + } + + private final class WarningListener implements ForkedProcessStringEventListener + { + @Override + public void handle( String msg ) + { + getOrCreateConsoleLogger() + .warning( msg ); + } } + /** + * Overridden by a subclass, see {@link org.apache.maven.plugin.surefire.booterclient.ForkStarter}. + */ protected void stopOnNextTest() { } @@ -204,125 +406,24 @@ private RunListener getTestSetReporter() private void processLine( String event ) { - final OperationalData op; - try - { - op = new OperationalData( event ); - } - catch ( RuntimeException e ) - { - logStreamWarning( e, event ); - return; - } - final String remaining = op.getData(); - switch ( op.getOperationId() ) - { - case BOOTERCODE_TESTSET_STARTING: - getTestSetReporter().testSetStarting( createReportEntry( remaining ) ); - setCurrentStartTime(); - break; - case BOOTERCODE_TESTSET_COMPLETED: - testsInProgress.clear(); - - getTestSetReporter().testSetCompleted( createReportEntry( remaining, testVmSystemProperties ) ); - break; - case BOOTERCODE_TEST_STARTING: - ReportEntry reportEntry = createReportEntry( remaining ); - testsInProgress.offer( reportEntry.getSourceName() ); - - getTestSetReporter().testStarting( createReportEntry( remaining ) ); - break; - case BOOTERCODE_TEST_SUCCEEDED: - reportEntry = createReportEntry( remaining ); - testsInProgress.remove( reportEntry.getSourceName() ); - - getTestSetReporter().testSucceeded( createReportEntry( remaining ) ); - break; - case BOOTERCODE_TEST_FAILED: - reportEntry = createReportEntry( remaining ); - testsInProgress.remove( reportEntry.getSourceName() ); - - getTestSetReporter().testFailed( createReportEntry( remaining ) ); - break; - case BOOTERCODE_TEST_SKIPPED: - reportEntry = createReportEntry( remaining ); - testsInProgress.remove( reportEntry.getSourceName() ); - - getTestSetReporter().testSkipped( createReportEntry( remaining ) ); - break; - case BOOTERCODE_TEST_ERROR: - reportEntry = createReportEntry( remaining ); - testsInProgress.remove( reportEntry.getSourceName() ); - - getTestSetReporter().testError( createReportEntry( remaining ) ); - break; - case BOOTERCODE_TEST_ASSUMPTIONFAILURE: - reportEntry = createReportEntry( remaining ); - testsInProgress.remove( reportEntry.getSourceName() ); - - getTestSetReporter().testAssumptionFailure( createReportEntry( remaining ) ); - break; - case BOOTERCODE_SYSPROPS: - int keyEnd = remaining.indexOf( "," ); - StringBuilder key = new StringBuilder(); - StringBuilder value = new StringBuilder(); - unescapeString( key, remaining.substring( 0, keyEnd ) ); - unescapeString( value, remaining.substring( keyEnd + 1 ) ); - testVmSystemProperties.put( key.toString(), value.toString() ); - break; - case BOOTERCODE_STDOUT: - writeTestOutput( remaining, true ); - break; - case BOOTERCODE_STDERR: - writeTestOutput( remaining, false ); - break; - case BOOTERCODE_CONSOLE: - getOrCreateConsoleLogger() - .info( createConsoleMessage( remaining ) ); - break; - case BOOTERCODE_NEXT_TEST: - notifiableTestStream.provideNewTest(); - break; - case BOOTERCODE_ERROR: - errorInFork = deserializeStackTraceWriter( new StringTokenizer( remaining, "," ) ); - break; - case BOOTERCODE_BYE: - saidGoodBye = true; - notifiableTestStream.acknowledgeByeEventReceived(); - break; - case BOOTERCODE_STOP_ON_NEXT_TEST: - stopOnNextTest(); - break; - case BOOTERCODE_DEBUG: - getOrCreateConsoleLogger() - .debug( createConsoleMessage( remaining ) ); - break; - case BOOTERCODE_WARNING: - getOrCreateConsoleLogger() - .warning( createConsoleMessage( remaining ) ); - break; - default: - logStreamWarning( event ); - } + decoder.handleEvent( event, errorHandler ); } - private void logStreamWarning( String event ) + private File dumpToLoFile( String msg, Throwable e ) { - logStreamWarning( null, event ); + File reportsDir = defaultReporterFactory.getReportsDirectory(); + InPluginProcessDumpSingleton util = InPluginProcessDumpSingleton.getSingleton(); + return e == null + ? util.dumpStreamText( msg, reportsDir, forkNumber ) + : util.dumpStreamException( e, msg, reportsDir, forkNumber ); } - private void logStreamWarning( Throwable e, String event ) + private void logStreamWarning( String event, Throwable e ) { if ( event == null || !event.contains( PRINTABLE_JVM_NATIVE_STREAM ) ) { String msg = "Corrupted STDOUT by directly writing to native stream in forked JVM " + forkNumber + "."; - - InPluginProcessDumpSingleton util = InPluginProcessDumpSingleton.getSingleton(); - File reportsDir = defaultReporterFactory.getReportsDirectory(); - File dump = - e == null - ? util.dumpStreamText( msg + " Stream '" + event + "'.", reportsDir, forkNumber ) - : util.dumpStreamException( e, msg + " Stream '" + event + "'.", reportsDir, forkNumber ); + File dump = dumpToLoFile( msg + " Stream '" + event + "'.", e ); if ( printedErrorStream.compareAndSet( false, true ) ) { @@ -352,91 +453,29 @@ else if ( log.isInfoEnabled() ) } } - private void writeTestOutput( String remaining, boolean isStdout ) + private void writeTestOutput( String output, boolean newLine, boolean isStdout ) { - int csNameEnd = remaining.indexOf( ',' ); - String charsetName = remaining.substring( 0, csNameEnd ); - String byteEncoded = remaining.substring( csNameEnd + 1 ); - ByteBuffer unescaped = unescapeBytes( byteEncoded, charsetName ); - - if ( unescaped.hasArray() ) - { - byte[] convertedBytes = unescaped.array(); - getOrCreateConsoleOutputReceiver() - .writeTestOutput( convertedBytes, unescaped.position(), unescaped.remaining(), isStdout ); - } - else - { - byte[] convertedBytes = new byte[unescaped.remaining()]; - unescaped.get( convertedBytes, 0, unescaped.remaining() ); - getOrCreateConsoleOutputReceiver() - .writeTestOutput( convertedBytes, 0, convertedBytes.length, isStdout ); - } + getOrCreateConsoleOutputReceiver() + .writeTestOutput( output, newLine, isStdout ); } public final void consumeMultiLineContent( String s ) throws IOException { - BufferedReader stringReader = new BufferedReader( new StringReader( s ) ); - for ( String s1 = stringReader.readLine(); s1 != null; s1 = stringReader.readLine() ) + if ( isBlank( s ) ) { - consumeLine( s1 ); + logStreamWarning( s, null ); } - } - - private String createConsoleMessage( String remaining ) - { - return unescape( remaining ); - } - - private TestSetReportEntry createReportEntry( String untokenized ) - { - return createReportEntry( untokenized, Collections.emptyMap() ); - } - - private TestSetReportEntry createReportEntry( String untokenized, Map systemProperties ) - { - StringTokenizer tokens = new StringTokenizer( untokenized, "," ); - try - { - String source = nullableCsv( tokens.nextToken() ); - String name = nullableCsv( tokens.nextToken() ); - String group = nullableCsv( tokens.nextToken() ); - String message = nullableCsv( tokens.nextToken() ); - String elapsedStr = tokens.nextToken(); - Integer elapsed = "null".equals( elapsedStr ) ? null : decode( elapsedStr ); - final StackTraceWriter stackTraceWriter = - tokens.hasMoreTokens() ? deserializeStackTraceWriter( tokens ) : null; - - return reportEntry( source, name, group, stackTraceWriter, elapsed, message, systemProperties ); - } - catch ( RuntimeException e ) + else { - throw new RuntimeException( untokenized, e ); + BufferedReader stringReader = new BufferedReader( new StringReader( s ) ); + for ( String s1 = stringReader.readLine(); s1 != null; s1 = stringReader.readLine() ) + { + consumeLine( s1 ); + } } } - private StackTraceWriter deserializeStackTraceWriter( StringTokenizer tokens ) - { - String stackTraceMessage = nullableCsv( tokens.nextToken() ); - String smartStackTrace = nullableCsv( tokens.nextToken() ); - String stackTrace = tokens.hasMoreTokens() ? nullableCsv( tokens.nextToken() ) : null; - boolean hasTrace = stackTrace != null; - return hasTrace ? new DeserializedStacktraceWriter( stackTraceMessage, smartStackTrace, stackTrace ) : null; - } - - private String nullableCsv( String source ) - { - return "null".equals( source ) ? null : unescape( source ); - } - - private String unescape( String source ) - { - StringBuilder stringBuffer = new StringBuilder( source.length() ); - unescapeString( stringBuffer, source ); - return stringBuffer.toString(); - } - public final Map getTestVmSystemProperties() { return unmodifiableMap( testVmSystemProperties ); @@ -493,32 +532,10 @@ public boolean hasTestsInProgress() return !testsInProgress.isEmpty(); } - private static final class OperationalData + private StackTraceWriter deserializeStackTraceWriter( String stackTraceMessage, + String smartStackTrace, String stackTrace ) { - private final byte operationId; - private final String data; - - OperationalData( String event ) - { - operationId = (byte) event.charAt( 0 ); - int comma = event.indexOf( ",", 3 ); - if ( comma < 0 ) - { - throw new IllegalArgumentException( "Stream stdin corrupted. Expected comma after third character " - + "in command '" + event + "'." ); - } - int rest = event.indexOf( ",", comma ); - data = event.substring( rest + 1 ); - } - - byte getOperationId() - { - return operationId; - } - - String getData() - { - return data; - } + boolean hasTrace = stackTrace != null; + return hasTrace ? new DeserializedStacktraceWriter( stackTraceMessage, smartStackTrace, stackTrace ) : null; } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoder.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoder.java new file mode 100644 index 0000000000..b7950d0ba3 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoder.java @@ -0,0 +1,352 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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.commons.codec.binary.Base64; +import org.apache.maven.surefire.booter.ForkedProcessEvent; +import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.RunMode; +import org.apache.maven.surefire.report.StackTraceWriter; + +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.MAGIC_NUMBER; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STDERR; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STDERR_NEW_LINE; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STDOUT; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STDOUT_NEW_LINE; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_BYE; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_CONSOLE_DEBUG; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_CONSOLE_INFO; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_CONSOLE_WARNING; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_NEXT_TEST; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STOP_ON_NEXT_TEST; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_ASSUMPTIONFAILURE; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_ERROR; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_FAILED; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_SKIPPED; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_STARTING; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_SUCCEEDED; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TESTSET_COMPLETED; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TESTSET_STARTING; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.EVENTS; +import static org.apache.maven.surefire.report.CategorizedReportEntry.reportEntry; +import static org.apache.maven.surefire.report.RunMode.MODES; +import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; +import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank; +import static java.util.Objects.requireNonNull; + +/** + * magic number : run mode : opcode [: opcode specific data]* + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public final class ForkedChannelDecoder +{ + private static final Base64 BASE64 = new Base64(); + + private volatile ForkedProcessPropertyEventListener propertyEventListener; + private volatile ForkedProcessStackTraceEventListener consoleErrorEventListener; + private volatile ForkedProcessExitErrorListener exitErrorEventListener; + + private final ConcurrentMap> reportEventListeners = + new ConcurrentHashMap<>(); + + private final ConcurrentMap stdOutErrEventListeners = + new ConcurrentHashMap<>(); + + private final ConcurrentMap consoleEventListeners = + new ConcurrentHashMap<>(); + + private final ConcurrentMap controlEventListeners = + new ConcurrentHashMap<>(); + + public void setSystemPropertiesListener( ForkedProcessPropertyEventListener listener ) + { + propertyEventListener = requireNonNull( listener ); + } + + public void setTestSetStartingListener( ForkedProcessReportEventListener listener ) + { + reportEventListeners.put( BOOTERCODE_TESTSET_STARTING, requireNonNull( listener ) ); + } + + public void setTestSetCompletedListener( ForkedProcessReportEventListener listener ) + { + reportEventListeners.put( BOOTERCODE_TESTSET_COMPLETED, requireNonNull( listener ) ); + } + + public void setTestStartingListener( ForkedProcessReportEventListener listener ) + { + reportEventListeners.put( BOOTERCODE_TEST_STARTING, requireNonNull( listener ) ); + } + + public void setTestSucceededListener( ForkedProcessReportEventListener listener ) + { + reportEventListeners.put( BOOTERCODE_TEST_SUCCEEDED, requireNonNull( listener ) ); + } + + public void setTestFailedListener( ForkedProcessReportEventListener listener ) + { + reportEventListeners.put( BOOTERCODE_TEST_FAILED, requireNonNull( listener ) ); + } + + public void setTestSkippedListener( ForkedProcessReportEventListener listener ) + { + reportEventListeners.put( BOOTERCODE_TEST_SKIPPED, requireNonNull( listener ) ); + } + + public void setTestErrorListener( ForkedProcessReportEventListener listener ) + { + reportEventListeners.put( BOOTERCODE_TEST_ERROR, requireNonNull( listener ) ); + } + + public void setTestAssumptionFailureListener( ForkedProcessReportEventListener listener ) + { + reportEventListeners.put( BOOTERCODE_TEST_ASSUMPTIONFAILURE, requireNonNull( listener ) ); + } + + public void setStdOutListener( ForkedProcessStandardOutErrEventListener listener ) + { + stdOutErrEventListeners.put( BOOTERCODE_STDOUT, requireNonNull( listener ) ); + stdOutErrEventListeners.put( BOOTERCODE_STDOUT_NEW_LINE, requireNonNull( listener ) ); + } + + public void setStdErrListener( ForkedProcessStandardOutErrEventListener listener ) + { + stdOutErrEventListeners.put( BOOTERCODE_STDERR, requireNonNull( listener ) ); + stdOutErrEventListeners.put( BOOTERCODE_STDERR_NEW_LINE, requireNonNull( listener ) ); + } + + public void setConsoleInfoListener( ForkedProcessStringEventListener listener ) + { + consoleEventListeners.put( BOOTERCODE_CONSOLE_INFO, requireNonNull( listener ) ); + } + + public void setConsoleErrorListener( ForkedProcessStackTraceEventListener listener ) + { + consoleErrorEventListener = requireNonNull( listener ); + } + + public void setConsoleDebugListener( ForkedProcessStringEventListener listener ) + { + consoleEventListeners.put( BOOTERCODE_CONSOLE_DEBUG, requireNonNull( listener ) ); + } + + public void setConsoleWarningListener( ForkedProcessStringEventListener listener ) + { + consoleEventListeners.put( BOOTERCODE_CONSOLE_WARNING, requireNonNull( listener ) ); + } + + public void setByeListener( ForkedProcessEventListener listener ) + { + controlEventListeners.put( BOOTERCODE_BYE, requireNonNull( listener ) ); + } + + public void setStopOnNextTestListener( ForkedProcessEventListener listener ) + { + controlEventListeners.put( BOOTERCODE_STOP_ON_NEXT_TEST, requireNonNull( listener ) ); + } + + public void setAcquireNextTestListener( ForkedProcessEventListener listener ) + { + controlEventListeners.put( BOOTERCODE_NEXT_TEST, requireNonNull( listener ) ); + } + + public void setExitErrorEventListener( ForkedProcessExitErrorListener listener ) + { + exitErrorEventListener = requireNonNull( listener ); + } + + public void handleEvent( String line, ForkedChannelDecoderErrorHandler errorHandler ) + { + if ( line == null || !line.startsWith( MAGIC_NUMBER ) ) + { + errorHandler.handledError( line, null ); + return; + } + + StringTokenizer tokenizer = new StringTokenizer( line.substring( MAGIC_NUMBER.length() ), ":" ); + String opcode = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + ForkedProcessEvent event = opcode == null ? null : EVENTS.get( opcode ); + if ( event == null ) + { + errorHandler.handledError( line, null ); + return; + } + + try + { + if ( event.isControlCategory() ) + { + ForkedProcessEventListener listener = controlEventListeners.get( event ); + if ( listener != null ) + { + listener.handle(); + } + } + else if ( event.isConsoleCategory() ) + { + ForkedProcessStringEventListener listener = consoleEventListeners.get( event ); + Charset encoding = tokenizer.hasMoreTokens() ? Charset.forName( tokenizer.nextToken() ) : null; + if ( listener != null && encoding != null ) + { + String msg = tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : ""; + listener.handle( msg ); + } + } + else if ( event.isConsoleErrorCategory() ) + { + Charset encoding = tokenizer.hasMoreTokens() ? Charset.forName( tokenizer.nextToken() ) : null; + if ( consoleErrorEventListener != null && encoding != null ) + { + String msg = tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : null; + String smartStackTrace = + tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : null; + String stackTrace = tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : null; + consoleErrorEventListener.handle( msg, smartStackTrace, stackTrace ); + } + } + else if ( event.isStandardStreamCategory() ) + { + ForkedProcessStandardOutErrEventListener listener = stdOutErrEventListeners.get( event ); + RunMode mode = tokenizer.hasMoreTokens() ? MODES.get( tokenizer.nextToken() ) : null; + Charset encoding = tokenizer.hasMoreTokens() ? Charset.forName( tokenizer.nextToken() ) : null; + if ( listener != null && encoding != null && mode != null ) + { + boolean newLine = event == BOOTERCODE_STDOUT_NEW_LINE || event == BOOTERCODE_STDERR_NEW_LINE; + String output = tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : ""; + listener.handle( mode, output, newLine ); + } + } + else if ( event.isSysPropCategory() ) + { + RunMode mode = tokenizer.hasMoreTokens() ? MODES.get( tokenizer.nextToken() ) : null; + Charset encoding = tokenizer.hasMoreTokens() ? Charset.forName( tokenizer.nextToken() ) : null; + String key = tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : ""; + if ( propertyEventListener != null && isNotBlank( key ) ) + { + String value = tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : ""; + propertyEventListener.handle( mode, key, value ); + } + } + else if ( event.isTestCategory() ) + { + ForkedProcessReportEventListener listener = reportEventListeners.get( event ); + RunMode mode = tokenizer.hasMoreTokens() ? MODES.get( tokenizer.nextToken() ) : null; + Charset encoding = tokenizer.hasMoreTokens() ? Charset.forName( tokenizer.nextToken() ) : null; + if ( listener != null && encoding != null && mode != null ) + { + String sourceName = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String sourceText = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String name = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String nameText = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String group = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String message = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String elapsed = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String traceMessage = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String smartTrimmedStackTrace = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + String stackTrace = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; + ReportEntry reportEntry = toReportEntry( encoding, sourceName, sourceText, name, nameText, + group, message, elapsed, traceMessage, smartTrimmedStackTrace, stackTrace ); + listener.handle( mode, reportEntry ); + } + } + else if ( event.isJvmExitError() ) + { + if ( exitErrorEventListener != null ) + { + Charset encoding = tokenizer.hasMoreTokens() ? Charset.forName( tokenizer.nextToken() ) : null; + String message = tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : ""; + String smartTrimmedStackTrace = + tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : ""; + String stackTrace = tokenizer.hasMoreTokens() ? decode( tokenizer.nextToken(), encoding ) : ""; + exitErrorEventListener.handle( message, smartTrimmedStackTrace, stackTrace ); + } + } + } + catch ( IllegalArgumentException e ) + { + errorHandler.handledError( line, e ); + } + } + + static ReportEntry toReportEntry( Charset encoding, + // ReportEntry: + String encSource, String encSourceText, String encName, String encNameText, + String encGroup, String encMessage, String encTimeElapsed, + // StackTraceWriter: + String encTraceMessage, String encSmartTrimmedStackTrace, String encStackTrace ) + throws NumberFormatException + { + if ( encoding == null ) + { + // corrupted or incomplete stream + return null; + } + + String source = decode( encSource, encoding ); + String sourceText = decode( encSourceText, encoding ); + String name = decode( encName, encoding ); + String nameText = decode( encNameText, encoding ); + String group = decode( encGroup, encoding ); + StackTraceWriter stackTraceWriter = + decodeTrace( encoding, encTraceMessage, encSmartTrimmedStackTrace, encStackTrace ); + Integer elapsed = decodeToInteger( encTimeElapsed ); + String message = decode( encMessage, encoding ); + return reportEntry( source, sourceText, name, nameText, + group, stackTraceWriter, elapsed, message, Collections.emptyMap() ); + } + + static String decode( String line, Charset encoding ) + { + // ForkedChannelEncoder is encoding the stream with US_ASCII + return line == null || "-".equals( line ) + ? null + : new String( BASE64.decode( line.getBytes( US_ASCII ) ), encoding ); + } + + static Integer decodeToInteger( String line ) + { + return line == null || "-".equals( line ) ? null : Integer.decode( line ); + } + + private static StackTraceWriter decodeTrace( Charset encoding, String encTraceMessage, + String encSmartTrimmedStackTrace, String encStackTrace ) + { + if ( isBlank( encStackTrace ) || "-".equals( encStackTrace ) ) + { + return null; + } + else + { + String traceMessage = decode( encTraceMessage, encoding ); + String stackTrace = decode( encStackTrace, encoding ); + String smartTrimmedStackTrace = decode( encSmartTrimmedStackTrace, encoding ); + return new DeserializedStacktraceWriter( traceMessage, smartTrimmedStackTrace, stackTrace ); + } + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoderErrorHandler.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoderErrorHandler.java new file mode 100644 index 0000000000..8faa8035a2 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoderErrorHandler.java @@ -0,0 +1,29 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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. + */ + +/** + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public interface ForkedChannelDecoderErrorHandler +{ + void handledError( String line, Throwable e ); +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessEventListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessEventListener.java new file mode 100644 index 0000000000..61482958ae --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessEventListener.java @@ -0,0 +1,29 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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. + */ + +/** + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public interface ForkedProcessEventListener +{ + void handle(); +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessExitErrorListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessExitErrorListener.java new file mode 100644 index 0000000000..b14c38c11e --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessExitErrorListener.java @@ -0,0 +1,29 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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. + */ + +/** + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public interface ForkedProcessExitErrorListener +{ + void handle( String exceptionMessage, String smartTrimmedStackTrace, String stackTrace ); +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessPropertyEventListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessPropertyEventListener.java new file mode 100644 index 0000000000..9ef3e0923c --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessPropertyEventListener.java @@ -0,0 +1,31 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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.report.RunMode; + +/** + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public interface ForkedProcessPropertyEventListener +{ + void handle( RunMode runMode, String key, String value ); +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessReportEventListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessReportEventListener.java new file mode 100644 index 0000000000..06054df61c --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessReportEventListener.java @@ -0,0 +1,33 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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.report.ReportEntry; +import org.apache.maven.surefire.report.RunMode; + +/** + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + * @param report entry type + */ +public interface ForkedProcessReportEventListener +{ + void handle( RunMode runMode, T reportEntry ); +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStackTraceEventListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStackTraceEventListener.java new file mode 100644 index 0000000000..f54cc409cd --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStackTraceEventListener.java @@ -0,0 +1,29 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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. + */ + +/** + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public interface ForkedProcessStackTraceEventListener +{ + void handle( String msg, String smartStackTrace, String stackTrace ); +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStandardOutErrEventListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStandardOutErrEventListener.java new file mode 100644 index 0000000000..b60d6ed4f8 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStandardOutErrEventListener.java @@ -0,0 +1,31 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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.report.RunMode; + +/** + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public interface ForkedProcessStandardOutErrEventListener +{ + void handle( RunMode runMode, String output, boolean newLine ); +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStringEventListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStringEventListener.java new file mode 100644 index 0000000000..9bd863aa3c --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedProcessStringEventListener.java @@ -0,0 +1,29 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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. + */ + +/** + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public interface ForkedProcessStringEventListener +{ + void handle( String msg ); +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ThreadedStreamConsumer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ThreadedStreamConsumer.java index dad88fd6cc..388f16db33 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ThreadedStreamConsumer.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/output/ThreadedStreamConsumer.java @@ -40,7 +40,7 @@ public final class ThreadedStreamConsumer { private static final String END_ITEM = ""; - private static final int ITEM_LIMIT_BEFORE_SLEEP = 10 * 1000; + private static final int ITEM_LIMIT_BEFORE_SLEEP = 10_000; private final BlockingQueue items = new ArrayBlockingQueue<>( ITEM_LIMIT_BEFORE_SLEEP ); diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/DefaultStatelessReportMojoConfiguration.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/DefaultStatelessReportMojoConfiguration.java new file mode 100644 index 0000000000..0eb6b52f9d --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/DefaultStatelessReportMojoConfiguration.java @@ -0,0 +1,58 @@ +package org.apache.maven.plugin.surefire.extensions; + +/* + * 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.plugin.surefire.report.WrappedReportEntry; +import org.apache.maven.surefire.extensions.StatelessReportMojoConfiguration; + +import java.io.File; +import java.util.Deque; +import java.util.Map; + +/** + * Why Deprecated: The field {@code testClassMethodRunHistory} makes + * {@link org.apache.maven.plugin.surefire.report.StatelessXmlReporter} stateful and overloads reporter by permanently + * overriding XML using re-run feature. To fix this issue, the providers should use more events for re-run feature and + * events bounding provider's execution. After provider's execution is finished, this reporter should be announced + * only once per test class. All test report entries should be cached in + * {@link org.apache.maven.plugin.surefire.report.TestSetRunListener} keeping it already stateful. + */ +@Deprecated +public class DefaultStatelessReportMojoConfiguration + extends StatelessReportMojoConfiguration +{ + private final Map> testClassMethodRunHistory; + + public DefaultStatelessReportMojoConfiguration( File reportsDirectory, + String reportNameSuffix, + boolean trimStackTrace, + int rerunFailingTestsCount, + String xsdSchemaLocation, + Map> testClassMethodRunHistory ) + { + super( reportsDirectory, reportNameSuffix, trimStackTrace, rerunFailingTestsCount, xsdSchemaLocation ); + this.testClassMethodRunHistory = testClassMethodRunHistory; + } + + public Map> getTestClassMethodRunHistory() + { + return testClassMethodRunHistory; + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireConsoleOutputReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireConsoleOutputReporter.java new file mode 100644 index 0000000000..e4ac7a6809 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireConsoleOutputReporter.java @@ -0,0 +1,86 @@ +package org.apache.maven.plugin.surefire.extensions; + +/* + * 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.plugin.surefire.report.ConsoleOutputFileReporter; +import org.apache.maven.plugin.surefire.report.DirectConsoleOutput; +import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener; +import org.apache.maven.surefire.extensions.ConsoleOutputReporter; +import org.apache.maven.surefire.util.ReflectionUtils; + +import java.io.File; +import java.io.PrintStream; + +/** + * Default implementation for extension of console logger. + * Signatures can be changed between major, minor versions or milestones. + *
+ * Builds {@link ConsoleOutputReportEventListener listeners}. + * The listeners handle test set events. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class SurefireConsoleOutputReporter + extends ConsoleOutputReporter +{ + @Override + public ConsoleOutputReportEventListener createListener( File reportsDirectory, String reportNameSuffix, + Integer forkNumber ) + { + return new ConsoleOutputFileReporter( reportsDirectory, reportNameSuffix, false, forkNumber, getEncoding() ); + } + + @Override + public ConsoleOutputReportEventListener createListener( PrintStream out, PrintStream err ) + { + return new DirectConsoleOutput( out, err ); + } + + @Override + public Object clone( ClassLoader target ) + { + try + { + Class cls = ReflectionUtils.reloadClass( target, this ); + Object clone = cls.newInstance(); + + cls.getMethod( "setDisable", boolean.class ) + .invoke( clone, isDisable() ); + cls.getMethod( "setEncoding", String.class ) + .invoke( clone, getEncoding() ); + + return clone; + } + catch ( ReflectiveOperationException e ) + { + throw new IllegalStateException( e.getLocalizedMessage() ); + } + } + + @Override + public String toString() + { + return "SurefireConsoleOutputReporter{" + + "disable=" + isDisable() + + ", encoding=" + getEncoding() + + '}'; + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessReporter.java new file mode 100644 index 0000000000..e907bfd184 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessReporter.java @@ -0,0 +1,98 @@ +package org.apache.maven.plugin.surefire.extensions; + +/* + * 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.plugin.surefire.report.StatelessXmlReporter; +import org.apache.maven.plugin.surefire.report.TestSetStats; +import org.apache.maven.plugin.surefire.report.WrappedReportEntry; +import org.apache.maven.surefire.extensions.StatelessReportEventListener; +import org.apache.maven.surefire.extensions.StatelessReporter; +import org.apache.maven.surefire.util.ReflectionUtils; + +/** + * Default implementation for extension of {@link StatelessXmlReporter} in plugin. + * Signatures can be changed between major, minor versions or milestones. + *
+ * This is a builder of {@link StatelessReportEventListener listener}. + * The listener handles testSetCompleted event. + * + * author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class SurefireStatelessReporter + extends StatelessReporter +{ + /** + * Activated in the injection point of MOJO. + */ + public SurefireStatelessReporter() + { + this( false, "3.0" ); + } + + /** + * Activated if null injection point in MOJO. + * @param disable {@code true} to disable performing the report + * @param version (xsd 3.0) version of the schema + */ + public SurefireStatelessReporter( boolean disable, String version ) + { + setDisable( disable ); + setVersion( version ); + } + + @Override + public StatelessReportEventListener createListener( + DefaultStatelessReportMojoConfiguration configuration ) + { + return new StatelessXmlReporter( configuration.getReportsDirectory(), + configuration.getReportNameSuffix(), + configuration.isTrimStackTrace(), + configuration.getRerunFailingTestsCount(), + configuration.getTestClassMethodRunHistory(), + configuration.getXsdSchemaLocation(), + getVersion(), + false, + false, + false, + false ); + } + + @Override + public Object clone( ClassLoader target ) + { + try + { + Class cls = ReflectionUtils.reloadClass( target, this ); + Object clone = cls.newInstance(); + + cls.getMethod( "setDisable", boolean.class ) + .invoke( clone, isDisable() ); + cls.getMethod( "setVersion", String.class ) + .invoke( clone, getVersion() ); + + return clone; + } + catch ( ReflectiveOperationException e ) + { + throw new IllegalStateException( e.getLocalizedMessage() ); + } + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessTestsetInfoReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessTestsetInfoReporter.java new file mode 100644 index 0000000000..73a099c4d8 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/SurefireStatelessTestsetInfoReporter.java @@ -0,0 +1,87 @@ +package org.apache.maven.plugin.surefire.extensions; + +/* + * 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.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.plugin.surefire.report.ConsoleReporter; +import org.apache.maven.plugin.surefire.report.FileReporter; +import org.apache.maven.plugin.surefire.report.TestSetStats; +import org.apache.maven.plugin.surefire.report.WrappedReportEntry; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoReporter; +import org.apache.maven.surefire.util.ReflectionUtils; + +import java.io.File; +import java.nio.charset.Charset; + +/** + * Default implementation for extension of + * {@link StatelessTestsetInfoFileReportEventListener test-set event listener for stateless file and console reporter} + * in plugin. Signatures can be changed between major, minor versions or milestones. + *
+ * Builds {@link StatelessTestsetInfoFileReportEventListener listeners}. + * The listener handles testSetCompleted event. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class SurefireStatelessTestsetInfoReporter + extends StatelessTestsetInfoReporter +{ + @Override + public StatelessTestsetInfoConsoleReportEventListener createListener( + ConsoleLogger logger ) + { + return new ConsoleReporter( logger, false, false ); + } + + @Override + public StatelessTestsetInfoFileReportEventListener createListener( + File reportsDirectory, String reportNameSuffix, Charset encoding ) + { + return new FileReporter( reportsDirectory, reportNameSuffix, encoding, false, false, false ); + } + + @Override + public Object clone( ClassLoader target ) + { + try + { + Class cls = ReflectionUtils.reloadClass( target, this ); + Object clone = cls.newInstance(); + + cls.getMethod( "setDisable", boolean.class ) + .invoke( clone, isDisable() ); + + return clone; + } + catch ( ReflectiveOperationException e ) + { + throw new IllegalStateException( e.getLocalizedMessage() ); + } + } + + @Override + public String toString() + { + return "SurefireStatelessTestsetInfoReporter{disable=" + isDisable() + "}"; + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5ConsoleOutputReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5ConsoleOutputReporter.java new file mode 100644 index 0000000000..f5802b7b08 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5ConsoleOutputReporter.java @@ -0,0 +1,92 @@ +package org.apache.maven.plugin.surefire.extensions.junit5; + +/* + * 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.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.report.ConsoleOutputFileReporter; +import org.apache.maven.plugin.surefire.report.StatelessXmlReporter; +import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener; + +import java.io.File; + +/** + * The extension of {@link StatelessXmlReporter logger} for JUnit5. + * Selectively enables report files upon JUnit5 annotation DisplayName. + * + * author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class JUnit5ConsoleOutputReporter + extends SurefireConsoleOutputReporter +{ + /** + * {@code false} by default. + *
+ * This action takes effect only in JUnit5 provider together with a test class annotated DisplayName. + */ + private boolean usePhrasedFileName; + + public boolean isUsePhrasedFileName() + { + return usePhrasedFileName; + } + + public void setUsePhrasedFileName( boolean usePhrasedFileName ) + { + this.usePhrasedFileName = usePhrasedFileName; + } + + @Override + public ConsoleOutputReportEventListener createListener( File reportsDirectory, String reportNameSuffix, + Integer forkNumber ) + { + return new ConsoleOutputFileReporter( reportsDirectory, reportNameSuffix, isUsePhrasedFileName(), forkNumber, + getEncoding() ); + } + + @Override + public Object clone( ClassLoader target ) + { + try + { + Object clone = super.clone( target ); + + Class cls = clone.getClass(); + cls.getMethod( "setUsePhrasedFileName", boolean.class ) + .invoke( clone, isUsePhrasedFileName() ); + + return clone; + } + catch ( ReflectiveOperationException e ) + { + throw new IllegalStateException( e.getLocalizedMessage() ); + } + } + + @Override + public String toString() + { + return "JUnit5ConsoleOutputReporter{" + + "disable=" + isDisable() + + ", encoding=" + getEncoding() + + ", usePhrasedFileName=" + isUsePhrasedFileName() + + '}'; + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoReporter.java new file mode 100644 index 0000000000..3c1b76ba52 --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoReporter.java @@ -0,0 +1,148 @@ +package org.apache.maven.plugin.surefire.extensions.junit5; + +/* + * 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.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.plugin.surefire.report.ConsoleReporter; +import org.apache.maven.plugin.surefire.report.FileReporter; +import org.apache.maven.plugin.surefire.report.TestSetStats; +import org.apache.maven.plugin.surefire.report.WrappedReportEntry; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener; + +import java.io.File; +import java.nio.charset.Charset; + +/** + * Extension of {@link StatelessTestsetInfoConsoleReportEventListener file and console reporter of test-set} for JUnit5. + * Signatures can be changed between major, minor versions or milestones. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class JUnit5StatelessTestsetInfoReporter + extends SurefireStatelessTestsetInfoReporter +{ + /** + * {@code false} by default. + *
+ * This action takes effect only in JUnit5 provider together with a test class annotated DisplayName. + */ + private boolean usePhrasedFileName; + + /** + * Phrased class name of test case in the console log (see xxx) + * Running xxx or file report log Test set: xxx. + * {@code false} by default. + *
+ * This action takes effect only in JUnit5 provider together with a test class annotated DisplayName. + */ + private boolean usePhrasedClassNameInRunning; + + /** + * Phrased class name of test case in the log (see xxx) + * Tests run: ., Failures: ., Errors: ., Skipped: ., Time elapsed: . s, - in xxx. + * {@code false} by default. + *
+ * This action takes effect only in JUnit5 provider together with a test class annotated DisplayName. + */ + private boolean usePhrasedClassNameInTestCaseSummary; + + public boolean isUsePhrasedFileName() + { + return usePhrasedFileName; + } + + public void setUsePhrasedFileName( boolean usePhrasedFileName ) + { + this.usePhrasedFileName = usePhrasedFileName; + } + + public boolean isUsePhrasedClassNameInRunning() + { + return usePhrasedClassNameInRunning; + } + + public void setUsePhrasedClassNameInRunning( boolean usePhrasedClassNameInRunning ) + { + this.usePhrasedClassNameInRunning = usePhrasedClassNameInRunning; + } + + public boolean isUsePhrasedClassNameInTestCaseSummary() + { + return usePhrasedClassNameInTestCaseSummary; + } + + public void setUsePhrasedClassNameInTestCaseSummary( boolean usePhrasedClassNameInTestCaseSummary ) + { + this.usePhrasedClassNameInTestCaseSummary = usePhrasedClassNameInTestCaseSummary; + } + + @Override + public StatelessTestsetInfoConsoleReportEventListener createListener( + ConsoleLogger logger ) + { + return new ConsoleReporter( logger, isUsePhrasedClassNameInRunning(), + isUsePhrasedClassNameInTestCaseSummary() ); + } + + @Override + public StatelessTestsetInfoFileReportEventListener createListener( + File reportsDirectory, String reportNameSuffix, Charset encoding ) + { + return new FileReporter( reportsDirectory, reportNameSuffix, encoding, isUsePhrasedFileName(), + isUsePhrasedClassNameInRunning(), isUsePhrasedClassNameInTestCaseSummary() ); + } + + @Override + public Object clone( ClassLoader target ) + { + try + { + Object clone = super.clone( target ); + + Class cls = clone.getClass(); + cls.getMethod( "setUsePhrasedFileName", boolean.class ) + .invoke( clone, isUsePhrasedFileName() ); + cls.getMethod( "setUsePhrasedClassNameInTestCaseSummary", boolean.class ) + .invoke( clone, isUsePhrasedFileName() ); + cls.getMethod( "setUsePhrasedClassNameInRunning", boolean.class ) + .invoke( clone, isUsePhrasedFileName() ); + + return clone; + } + catch ( ReflectiveOperationException e ) + { + throw new IllegalStateException( e.getLocalizedMessage() ); + } + } + + @Override + public String toString() + { + return "JUnit5StatelessTestsetInfoReporter{" + + "disable=" + isDisable() + + ", usePhrasedFileName=" + isUsePhrasedFileName() + + ", usePhrasedClassNameInRunning=" + isUsePhrasedClassNameInRunning() + + ", usePhrasedClassNameInTestCaseSummary=" + isUsePhrasedClassNameInTestCaseSummary() + + "}"; + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5Xml30StatelessReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5Xml30StatelessReporter.java new file mode 100644 index 0000000000..83dca7da9d --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5Xml30StatelessReporter.java @@ -0,0 +1,161 @@ +package org.apache.maven.plugin.surefire.extensions.junit5; + +/* + * 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.plugin.surefire.extensions.DefaultStatelessReportMojoConfiguration; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.report.StatelessXmlReporter; +import org.apache.maven.plugin.surefire.report.TestSetStats; +import org.apache.maven.plugin.surefire.report.WrappedReportEntry; +import org.apache.maven.surefire.extensions.StatelessReportEventListener; + +/** + * The extension of {@link StatelessXmlReporter xml reporter} based on XSD version 3.0 for JUnit5. + * Selectively enables phrased classes, methods and report files upon JUnit5 annotation DisplayName. + * + * author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class JUnit5Xml30StatelessReporter + extends SurefireStatelessReporter +{ + /** + * {@code false} by default. + *
+ * This action takes effect only in JUnit5 provider together with a test class annotated DisplayName. + */ + private boolean usePhrasedFileName; + + /** + * {@code false} by default. + *
+ * This action takes effect only in JUnit5 provider together with a test class annotated DisplayName. + */ + private boolean usePhrasedTestSuiteClassName; + + /** + * {@code false} by default. + *
+ * This action takes effect only in JUnit5 provider together with a test class annotated DisplayName. + */ + private boolean usePhrasedTestCaseClassName; + + /** + * {@code false} by default. + *
+ * This action takes effect only in JUnit5 provider together with a test method annotated DisplayName. + */ + private boolean usePhrasedTestCaseMethodName; + + public boolean getUsePhrasedFileName() + { + return usePhrasedFileName; + } + + public void setUsePhrasedFileName( boolean usePhrasedFileName ) + { + this.usePhrasedFileName = usePhrasedFileName; + } + + public boolean getUsePhrasedTestSuiteClassName() + { + return usePhrasedTestSuiteClassName; + } + + public void setUsePhrasedTestSuiteClassName( boolean usePhrasedTestSuiteClassName ) + { + this.usePhrasedTestSuiteClassName = usePhrasedTestSuiteClassName; + } + + public boolean getUsePhrasedTestCaseClassName() + { + return usePhrasedTestCaseClassName; + } + + public void setUsePhrasedTestCaseClassName( boolean usePhrasedTestCaseClassName ) + { + this.usePhrasedTestCaseClassName = usePhrasedTestCaseClassName; + } + + public boolean getUsePhrasedTestCaseMethodName() + { + return usePhrasedTestCaseMethodName; + } + + public void setUsePhrasedTestCaseMethodName( boolean usePhrasedTestCaseMethodName ) + { + this.usePhrasedTestCaseMethodName = usePhrasedTestCaseMethodName; + } + + @Override + public StatelessReportEventListener createListener( + DefaultStatelessReportMojoConfiguration configuration ) + { + return new StatelessXmlReporter( configuration.getReportsDirectory(), + configuration.getReportNameSuffix(), + configuration.isTrimStackTrace(), + configuration.getRerunFailingTestsCount(), + configuration.getTestClassMethodRunHistory(), + configuration.getXsdSchemaLocation(), + getVersion(), + getUsePhrasedFileName(), + getUsePhrasedTestSuiteClassName(), + getUsePhrasedTestCaseClassName(), + getUsePhrasedTestCaseMethodName() ); + } + + @Override + public Object clone( ClassLoader target ) + { + try + { + Object clone = super.clone( target ); + + Class cls = clone.getClass(); + cls.getMethod( "setUsePhrasedFileName", boolean.class ) + .invoke( clone, getUsePhrasedFileName() ); + cls.getMethod( "setUsePhrasedTestSuiteClassName", boolean.class ) + .invoke( clone, getUsePhrasedTestSuiteClassName() ); + cls.getMethod( "setUsePhrasedTestCaseClassName", boolean.class ) + .invoke( clone, getUsePhrasedTestCaseClassName() ); + cls.getMethod( "setUsePhrasedTestCaseMethodName", boolean.class ) + .invoke( clone, getUsePhrasedTestCaseMethodName() ); + + return clone; + } + catch ( ReflectiveOperationException e ) + { + throw new IllegalStateException( e.getLocalizedMessage() ); + } + } + + @Override + public String toString() + { + return "JUnit5Xml30StatelessReporter{" + + "version=" + getVersion() + + ", disable=" + isDisable() + + ", usePhrasedFileName=" + getUsePhrasedFileName() + + ", usePhrasedTestSuiteClassName=" + getUsePhrasedTestSuiteClassName() + + ", usePhrasedTestCaseClassName=" + getUsePhrasedTestCaseClassName() + + ", usePhrasedTestCaseMethodName=" + getUsePhrasedTestCaseMethodName() + + '}'; + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java index 0ea0a78e90..3bc3f2cd77 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleOutputFileReporter.java @@ -21,16 +21,19 @@ import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton; import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.TestSetReportEntry; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FilterOutputStream; import java.io.IOException; +import java.nio.charset.Charset; import java.util.concurrent.atomic.AtomicStampedReference; import java.util.concurrent.locks.ReentrantLock; import static org.apache.maven.plugin.surefire.report.FileReporter.getReportFile; +import static org.apache.maven.surefire.util.internal.StringUtils.NL; /** * Surefire output consumer proxy that writes test output to a {@link java.io.File} for each test suite. @@ -41,14 +44,16 @@ public class ConsoleOutputFileReporter implements TestcycleConsoleOutputReceiver { - private static final int STREAM_BUFFER_SIZE = 16 * 1024; + private static final int STREAM_BUFFER_SIZE = 64 * 1024; private static final int OPEN = 0; private static final int CLOSED_TO_REOPEN = 1; private static final int CLOSED = 2; private final File reportsDirectory; private final String reportNameSuffix; + private final boolean usePhrasedFileName; private final Integer forkNumber; + private final String encoding; private final AtomicStampedReference fileOutputStream = new AtomicStampedReference<>( null, OPEN ); @@ -57,15 +62,18 @@ public class ConsoleOutputFileReporter private volatile String reportEntryName; - public ConsoleOutputFileReporter( File reportsDirectory, String reportNameSuffix, Integer forkNumber ) + public ConsoleOutputFileReporter( File reportsDirectory, String reportNameSuffix, boolean usePhrasedFileName, + Integer forkNumber, String encoding ) { this.reportsDirectory = reportsDirectory; this.reportNameSuffix = reportNameSuffix; + this.usePhrasedFileName = usePhrasedFileName; this.forkNumber = forkNumber; + this.encoding = encoding; } @Override - public void testSetStarting( ReportEntry reportEntry ) + public void testSetStarting( TestSetReportEntry reportEntry ) { lock.lock(); try @@ -79,7 +87,7 @@ public void testSetStarting( ReportEntry reportEntry ) } @Override - public void testSetCompleted( ReportEntry report ) + public void testSetCompleted( TestSetReportEntry report ) { } @@ -99,7 +107,7 @@ public void close() } @Override - public void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) + public void writeTestOutput( String output, boolean newLine, boolean stdout ) { lock.lock(); try @@ -121,12 +129,23 @@ public void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) os = new BufferedOutputStream( new FileOutputStream( file ), STREAM_BUFFER_SIZE ); fileOutputStream.set( os, OPEN ); } - os.write( buf, off, len ); + + if ( output == null ) + { + output = "null"; + } + Charset charset = Charset.forName( encoding ); + os.write( output.getBytes( charset ) ); + if ( newLine ) + { + os.write( NL.getBytes( charset ) ); + } } } catch ( IOException e ) { dumpException( e ); + // todo use UncheckedIOException in Java 8 throw new RuntimeException( e ); } finally @@ -150,7 +169,7 @@ private void closeNullReportFile( ReportEntry reportEntry ) finally { // prepare -output.txt report file - reportEntryName = reportEntry.getName(); + reportEntryName = usePhrasedFileName ? reportEntry.getSourceText() : reportEntry.getSourceName(); } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java index 36f311bdf5..0bee6879d7 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleReporter.java @@ -23,8 +23,9 @@ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.shared.utils.logging.MessageBuilder; -import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.plugin.surefire.log.api.Level; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; +import org.apache.maven.surefire.report.TestSetReportEntry; import static org.apache.maven.plugin.surefire.log.api.Level.resolveLevel; import static org.apache.maven.plugin.surefire.report.TestSetStats.concatenateWithTestGroup; @@ -37,31 +38,33 @@ * @author Kristian Rosenvold */ public class ConsoleReporter + extends StatelessTestsetInfoConsoleReportEventListener { public static final String BRIEF = "brief"; - public static final String PLAIN = "plain"; - private static final String TEST_SET_STARTING_PREFIX = "Running "; - private final ConsoleLogger logger; - - public ConsoleReporter( ConsoleLogger logger ) - { - this.logger = logger; - } + private final boolean usePhrasedClassNameInRunning; + private final boolean usePhrasedClassNameInTestCaseSummary; - public ConsoleLogger getConsoleLogger() + public ConsoleReporter( ConsoleLogger logger, + boolean usePhrasedClassNameInRunning, boolean usePhrasedClassNameInTestCaseSummary ) { - return logger; + super( logger ); + this.usePhrasedClassNameInRunning = usePhrasedClassNameInRunning; + this.usePhrasedClassNameInTestCaseSummary = usePhrasedClassNameInTestCaseSummary; } - public void testSetStarting( ReportEntry report ) + @Override + public void testSetStarting( TestSetReportEntry report ) { - MessageBuilder builder = buffer(); - logger.info( concatenateWithTestGroup( builder.a( TEST_SET_STARTING_PREFIX ), report ) ); + MessageBuilder builder = buffer().a( TEST_SET_STARTING_PREFIX ); + String runningTestCase = concatenateWithTestGroup( builder, report, usePhrasedClassNameInRunning ); + getConsoleLogger() + .info( runningTestCase ); } + @Override public void testSetCompleted( WrappedReportEntry report, TestSetStats testSetStats, List testResults ) { boolean success = testSetStats.getCompletedCount() > 0; @@ -71,13 +74,14 @@ public void testSetCompleted( WrappedReportEntry report, TestSetStats testSetSta boolean flakes = testSetStats.getSkipped() > 0; Level level = resolveLevel( success, failures, errors, skipped, flakes ); - println( testSetStats.getColoredTestSetSummary( report ), level ); + println( testSetStats.getColoredTestSetSummary( report, usePhrasedClassNameInTestCaseSummary ), level ); for ( String testResult : testResults ) { println( testResult, level ); } } + @Override public void reset() { } @@ -87,13 +91,16 @@ private void println( String message, Level level ) switch ( level ) { case FAILURE: - logger.error( message ); + getConsoleLogger() + .error( message ); break; case UNSTABLE: - logger.warning( message ); + getConsoleLogger() + .warning( message ); break; default: - logger.info( message ); + getConsoleLogger() + .info( message ); } } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java index e622c6d186..ed93a659c5 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactory.java @@ -24,6 +24,10 @@ import org.apache.maven.plugin.surefire.log.api.Level; import org.apache.maven.plugin.surefire.runorder.StatisticsReporter; import org.apache.maven.shared.utils.logging.MessageBuilder; +import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener; +import org.apache.maven.surefire.extensions.StatelessReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener; import org.apache.maven.surefire.report.ReporterFactory; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.RunStatistics; @@ -113,26 +117,32 @@ public File getReportsDirectory() return reportConfiguration.getReportsDirectory(); } - private ConsoleReporter createConsoleReporter() + private StatelessTestsetInfoConsoleReportEventListener createConsoleReporter() { - return shouldReportToConsole() ? new ConsoleReporter( consoleLogger ) : NullConsoleReporter.INSTANCE; + StatelessTestsetInfoConsoleReportEventListener consoleReporter = + reportConfiguration.instantiateConsoleReporter( consoleLogger ); + return useNonNull( consoleReporter, NullConsoleReporter.INSTANCE ); } - private FileReporter createFileReporter() + private StatelessTestsetInfoFileReportEventListener createFileReporter() { - FileReporter fileReporter = reportConfiguration.instantiateFileReporter( forkNumber ); + StatelessTestsetInfoFileReportEventListener fileReporter = + reportConfiguration.instantiateFileReporter( forkNumber ); return useNonNull( fileReporter, NullFileReporter.INSTANCE ); } - private StatelessXmlReporter createSimpleXMLReporter() + private StatelessReportEventListener createSimpleXMLReporter() { - StatelessXmlReporter xmlReporter = reportConfiguration.instantiateStatelessXmlReporter( forkNumber ); + StatelessReportEventListener xmlReporter = + reportConfiguration.instantiateStatelessXmlReporter( forkNumber ); return useNonNull( xmlReporter, NullStatelessXmlReporter.INSTANCE ); } - private TestcycleConsoleOutputReceiver createConsoleOutputReceiver() + private ConsoleOutputReportEventListener createConsoleOutputReceiver() { - return reportConfiguration.instantiateConsoleOutputFileReporter( forkNumber ); + ConsoleOutputReportEventListener outputReporter = + reportConfiguration.instantiateConsoleOutputFileReporter( forkNumber ); + return useNonNull( outputReporter, NullConsoleOutputReceiver.INSTANCE ); } private StatisticsReporter createStatisticsReporter() @@ -141,13 +151,6 @@ private StatisticsReporter createStatisticsReporter() return useNonNull( statisticsReporter, NullStatisticsReporter.INSTANCE ); } - private boolean shouldReportToConsole() - { - return reportConfiguration.isUseFile() - ? reportConfiguration.isPrintSummary() - : reportConfiguration.isRedirectTestOutputToFile() || reportConfiguration.isBriefOrPlainFormat(); - } - public void mergeFromOtherFactories( Collection factories ) { for ( DefaultReporterFactory factory : factories ) @@ -175,10 +178,13 @@ public RunResult close() public void runStarting() { - log( "" ); - log( "-------------------------------------------------------" ); - log( " T E S T S" ); - log( "-------------------------------------------------------" ); + if ( reportConfiguration.isPrintSummary() ) + { + log( "" ); + log( "-------------------------------------------------------" ); + log( " T E S T S" ); + log( "-------------------------------------------------------" ); + } } private void runCompleted() @@ -192,14 +198,17 @@ private void runCompleted() boolean printedFailures = printTestFailures( failure ); boolean printedErrors = printTestFailures( error ); boolean printedFlakes = printTestFailures( flake ); - if ( printedFailures | printedErrors | printedFlakes ) + if ( reportConfiguration.isPrintSummary() ) { + if ( printedFailures | printedErrors | printedFlakes ) + { + log( "" ); + } + boolean hasSuccessful = globalStats.getCompletedCount() > 0; + boolean hasSkipped = globalStats.getSkipped() > 0; + log( globalStats.getSummary(), hasSuccessful, printedFailures, printedErrors, hasSkipped, printedFlakes ); log( "" ); } - boolean hasSuccessful = globalStats.getCompletedCount() > 0; - boolean hasSkipped = globalStats.getSkipped() > 0; - log( globalStats.getSummary(), hasSuccessful, printedFailures, printedErrors, hasSkipped, printedFlakes ); - log( "" ); } public RunStatistics getGlobalRunStatistics() @@ -266,7 +275,7 @@ else if ( seenSuccess ) * Merge all the TestMethodStats in each TestRunListeners and put results into flakyTests, failedTests and * errorTests, indexed by test class and method name. Update globalStatistics based on the result of the merge. */ - void mergeTestHistoryResult() + private void mergeTestHistoryResult() { globalStats = new RunStatistics(); flakyTests = new TreeMap<>(); @@ -382,7 +391,6 @@ boolean printTestFailures( TestResultType type ) for ( Map.Entry> entry : testStats.entrySet() ) { - printed = true; List testMethodStats = entry.getValue(); if ( testMethodStats.size() == 1 ) { diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java index 056e903532..7ef2d82be4 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/DirectConsoleOutput.java @@ -19,15 +19,10 @@ * under the License. */ -import java.io.PrintStream; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; +import org.apache.maven.surefire.report.TestSetReportEntry; -import org.apache.maven.surefire.report.ReportEntry; +import java.io.PrintStream; -import static java.nio.ByteBuffer.wrap; -import static java.nio.charset.Charset.defaultCharset; import static java.util.Objects.requireNonNull; /** @@ -41,44 +36,37 @@ public class DirectConsoleOutput implements TestcycleConsoleOutputReceiver { - private static final Charset STANDARD_CHARSET = defaultCharset(); - - private final PrintStream sout; + private final PrintStream out; - private final PrintStream serr; + private final PrintStream err; - public DirectConsoleOutput( PrintStream sout, PrintStream serr ) + public DirectConsoleOutput( PrintStream out, PrintStream err ) { - this.sout = requireNonNull( sout ); - this.serr = requireNonNull( serr ); + this.out = requireNonNull( out ); + this.err = requireNonNull( err ); } @Override - public void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) + public void writeTestOutput( String output, boolean newLine, boolean stdout ) { - PrintStream stream = stdout ? sout : serr; - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized ( stream ) + PrintStream stream = stdout ? out : err; + if ( newLine ) + { + stream.println( output ); + } + else { - try - { - CharBuffer decode = STANDARD_CHARSET.newDecoder().decode( wrap( buf, off, len ) ); - stream.append( decode ); - } - catch ( CharacterCodingException e ) - { - stream.write( buf, off, len ); - } + stream.print( output ); } } @Override - public void testSetStarting( ReportEntry reportEntry ) + public void testSetStarting( TestSetReportEntry reportEntry ) { } @Override - public void testSetCompleted( ReportEntry report ) + public void testSetCompleted( TestSetReportEntry report ) { } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java index 290c252014..2301e34818 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/FileReporter.java @@ -19,16 +19,15 @@ * under the License. */ -import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener; import org.apache.maven.surefire.report.ReporterException; import java.io.BufferedWriter; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.Writer; import java.nio.charset.Charset; import java.util.List; @@ -42,64 +41,71 @@ * @author Kristian Rosenvold */ public class FileReporter + extends StatelessTestsetInfoFileReportEventListener { - private final File reportsDirectory; - private final String reportNameSuffix; - private final Charset encoding; + private final boolean usePhrasedFileName; + private final boolean usePhrasedClassNameInRunning; + private final boolean usePhrasedClassNameInTestCaseSummary; - public FileReporter( File reportsDirectory, String reportNameSuffix, Charset encoding ) + public FileReporter( File reportsDirectory, String reportNameSuffix, Charset encoding, boolean usePhrasedFileName, + boolean usePhrasedClassNameInRunning, boolean usePhrasedClassNameInTestCaseSummary ) { - this.reportsDirectory = reportsDirectory; - this.reportNameSuffix = reportNameSuffix; - this.encoding = encoding; + super( reportsDirectory, reportNameSuffix, encoding ); + this.usePhrasedFileName = usePhrasedFileName; + this.usePhrasedClassNameInRunning = usePhrasedClassNameInRunning; + this.usePhrasedClassNameInTestCaseSummary = usePhrasedClassNameInTestCaseSummary; } - private PrintWriter testSetStarting( ReportEntry report ) + static File getReportFile( File reportsDirectory, String reportEntryName, String reportNameSuffix, + String fileExtension ) { - File reportFile = getReportFile( reportsDirectory, report.getName(), reportNameSuffix, ".txt" ); + String fileName = + reportEntryName + ( isNotBlank( reportNameSuffix ) ? "-" + reportNameSuffix : "" ) + fileExtension; + return new File( reportsDirectory, stripIllegalFilenameChars( fileName ) ); + } + + @Override + public void testSetCompleted( WrappedReportEntry report, TestSetStats testSetStats, List testResults ) + { + File reportFile = getReportFile( getReportsDirectory(), + usePhrasedFileName ? report.getReportSourceName() : report.getSourceName(), + getReportNameSuffix(), + ".txt" ); File reportDir = reportFile.getParentFile(); // noinspection ResultOfMethodCallIgnored reportDir.mkdirs(); - try + try ( BufferedWriter writer = createFileReporterWriter( reportFile, getEncoding() ) ) { - Writer encodedStream = new OutputStreamWriter( new FileOutputStream( reportFile ), encoding ); - - PrintWriter writer = new PrintWriter( new BufferedWriter( encodedStream, 16 * 1024 ) ); - - writer.println( "-------------------------------------------------------------------------------" ); + writer.write( "-------------------------------------------------------------------------------" ); + writer.newLine(); - writer.println( "Test set: " + report.getName() ); + String tesSet = usePhrasedClassNameInRunning ? report.getReportSourceName() : report.getSourceName(); + writer.write( "Test set: " + tesSet ); + writer.newLine(); - writer.println( "-------------------------------------------------------------------------------" ); + writer.write( "-------------------------------------------------------------------------------" ); + writer.newLine(); - return writer; + writer.write( testSetStats.getTestSetSummary( report, usePhrasedClassNameInTestCaseSummary ) ); + writer.newLine(); + for ( String testResult : testResults ) + { + writer.write( testResult ); + writer.newLine(); + } } catch ( IOException e ) { - throw new ReporterException( "Unable to create file for report: " + e.getMessage(), e ); + throw new ReporterException( "Unable to create file for report: " + e.getLocalizedMessage(), e ); } } - static File getReportFile( File reportsDirectory, String reportEntryName, String reportNameSuffix, - String fileExtension ) + private static BufferedWriter createFileReporterWriter( File reportFile, Charset encoding ) + throws FileNotFoundException { - String fileName = - reportEntryName + ( isNotBlank( reportNameSuffix ) ? "-" + reportNameSuffix : "" ) + fileExtension; - return new File( reportsDirectory, stripIllegalFilenameChars( fileName ) ); - } - - public void testSetCompleted( WrappedReportEntry report, TestSetStats testSetStats, List testResults ) - { - try ( PrintWriter writer = testSetStarting( report ) ) - { - writer.println( testSetStats.getTestSetSummary( report ) ); - for ( String testResult : testResults ) - { - writer.println( testResult ); - } - } + return new BufferedWriter( new OutputStreamWriter( new FileOutputStream( reportFile ), encoding ), 64 * 1024 ); } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleOutputReceiver.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleOutputReceiver.java new file mode 100644 index 0000000000..a826b6760f --- /dev/null +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleOutputReceiver.java @@ -0,0 +1,63 @@ +package org.apache.maven.plugin.surefire.report; + +/* + * 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.report.TestSetReportEntry; + +/** + * TestcycleConsoleOutputReceiver doing nothing rather than using null. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class NullConsoleOutputReceiver + implements TestcycleConsoleOutputReceiver +{ + + static final NullConsoleOutputReceiver INSTANCE = new NullConsoleOutputReceiver(); + + private NullConsoleOutputReceiver() + { + } + + @Override + public void testSetStarting( TestSetReportEntry reportEntry ) + { + + } + + @Override + public void testSetCompleted( TestSetReportEntry report ) + { + + } + + @Override + public void close() + { + + } + + @Override + public void writeTestOutput( String output, boolean newLine, boolean stdout ) + { + + } +} diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleReporter.java index af68d1e01d..f33fca1456 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullConsoleReporter.java @@ -22,7 +22,7 @@ import java.util.List; import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger; -import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.TestSetReportEntry; /** * ConsoleReporter doing nothing rather than using null. @@ -38,11 +38,11 @@ class NullConsoleReporter private NullConsoleReporter() { - super( new NullConsoleLogger() ); + super( new NullConsoleLogger(), false, false ); } @Override - public void testSetStarting( ReportEntry report ) + public void testSetStarting( TestSetReportEntry report ) { } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullFileReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullFileReporter.java index df1bf9df9e..be217ebfe8 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullFileReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullFileReporter.java @@ -35,7 +35,7 @@ class NullFileReporter private NullFileReporter() { - super( null, null, null ); + super( null, null, null, false, false, false ); } @Override diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullStatelessXmlReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullStatelessXmlReporter.java index 7f5d202146..d43369dd8f 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullStatelessXmlReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/NullStatelessXmlReporter.java @@ -33,7 +33,7 @@ class NullStatelessXmlReporter private NullStatelessXmlReporter() { - super( null, null, false, 0, null, null ); + super( null, null, false, 0, null, null, null, false, false, false, false ); } @Override diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java index b89c4e9b02..fcb066ebbe 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporter.java @@ -22,7 +22,7 @@ import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton; import org.apache.maven.shared.utils.xml.PrettyPrintXMLWriter; import org.apache.maven.shared.utils.xml.XMLWriter; -import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.extensions.StatelessReportEventListener; import org.apache.maven.surefire.report.ReporterException; import org.apache.maven.surefire.report.SafeThrowable; @@ -34,12 +34,13 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.ArrayList; -import java.util.Collections; +import java.util.Deque; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentLinkedDeque; import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType; @@ -81,8 +82,9 @@ * @see Ant's format enhancement proposal * (not yet implemented by Ant 1.8.2) */ -@Deprecated // this is no more stateless due to existence of testClassMethodRunHistoryMap since of 2.19. Rename to StatefulXmlReporter in 3.0. +//todo this is no more stateless due to existence of testClassMethodRunHistoryMap since of 2.19. public class StatelessXmlReporter + implements StatelessReportEventListener { private final File reportsDirectory; @@ -94,14 +96,25 @@ public class StatelessXmlReporter private final String xsdSchemaLocation; + private final String xsdVersion; + // Map between test class name and a map between test method name // and the list of runs for each test method - private final Map>> testClassMethodRunHistoryMap; + private final Map> testClassMethodRunHistoryMap; + + private final boolean phrasedFileName; + + private final boolean phrasedSuiteName; + + private final boolean phrasedClassName; + + private final boolean phrasedMethodName; public StatelessXmlReporter( File reportsDirectory, String reportNameSuffix, boolean trimStackTrace, int rerunFailingTestsCount, - Map>> testClassMethodRunHistoryMap, - String xsdSchemaLocation ) + Map> testClassMethodRunHistoryMap, + String xsdSchemaLocation, String xsdVersion, boolean phrasedFileName, + boolean phrasedSuiteName, boolean phrasedClassName, boolean phrasedMethodName ) { this.reportsDirectory = reportsDirectory; this.reportNameSuffix = reportNameSuffix; @@ -109,19 +122,18 @@ public StatelessXmlReporter( File reportsDirectory, String reportNameSuffix, boo this.rerunFailingTestsCount = rerunFailingTestsCount; this.testClassMethodRunHistoryMap = testClassMethodRunHistoryMap; this.xsdSchemaLocation = xsdSchemaLocation; + this.xsdVersion = xsdVersion; + this.phrasedFileName = phrasedFileName; + this.phrasedSuiteName = phrasedSuiteName; + this.phrasedClassName = phrasedClassName; + this.phrasedMethodName = phrasedMethodName; } + @Override public void testSetCompleted( WrappedReportEntry testSetReportEntry, TestSetStats testSetStats ) { - String testClassName = testSetReportEntry.getName(); - - Map> methodRunHistoryMap = getAddMethodRunHistoryMap( testClassName ); - - // Update testClassMethodRunHistoryMap - for ( WrappedReportEntry methodEntry : testSetStats.getReportEntries() ) - { - getAddMethodEntryList( methodRunHistoryMap, methodEntry ); - } + Map>> classMethodStatistics = + arrangeMethodStatistics( testSetReportEntry, testSetStats ); OutputStream outputStream = getOutputStream( testSetReportEntry ); try ( OutputStreamWriter fw = getWriter( outputStream ) ) @@ -129,111 +141,18 @@ public void testSetCompleted( WrappedReportEntry testSetReportEntry, TestSetStat XMLWriter ppw = new PrettyPrintXMLWriter( fw ); ppw.setEncoding( UTF_8.name() ); - createTestSuiteElement( ppw, testSetReportEntry, testSetStats, testSetReportEntry.elapsedTimeAsString() ); + createTestSuiteElement( ppw, testSetReportEntry, testSetStats ); // TestSuite showProperties( ppw, testSetReportEntry.getSystemProperties() ); - // Iterate through all the test methods in the test class - for ( Entry> entry : methodRunHistoryMap.entrySet() ) + for ( Entry>> statistics : classMethodStatistics.entrySet() ) { - List methodEntryList = entry.getValue(); - if ( methodEntryList == null ) + for ( Entry> thisMethodRuns : statistics.getValue().entrySet() ) { - throw new IllegalStateException( "Get null test method run history" ); - } - - if ( !methodEntryList.isEmpty() ) - { - if ( rerunFailingTestsCount > 0 ) - { - switch ( getTestResultType( methodEntryList ) ) - { - case success: - for ( WrappedReportEntry methodEntry : methodEntryList ) - { - if ( methodEntry.getReportEntryType() == SUCCESS ) - { - startTestElement( ppw, methodEntry, reportNameSuffix, - methodEntryList.get( 0 ).elapsedTimeAsString() ); - ppw.endElement(); - } - } - break; - case error: - case failure: - // When rerunFailingTestsCount is set to larger than 0 - startTestElement( ppw, methodEntryList.get( 0 ), reportNameSuffix, - methodEntryList.get( 0 ).elapsedTimeAsString() ); - boolean firstRun = true; - for ( WrappedReportEntry singleRunEntry : methodEntryList ) - { - if ( firstRun ) - { - firstRun = false; - getTestProblems( fw, ppw, singleRunEntry, trimStackTrace, outputStream, - singleRunEntry.getReportEntryType().getXmlTag(), false ); - createOutErrElements( fw, ppw, singleRunEntry, outputStream ); - } - else - { - getTestProblems( fw, ppw, singleRunEntry, trimStackTrace, outputStream, - singleRunEntry.getReportEntryType().getRerunXmlTag(), true ); - } - } - ppw.endElement(); - break; - case flake: - String runtime = ""; - // Get the run time of the first successful run - for ( WrappedReportEntry singleRunEntry : methodEntryList ) - { - if ( singleRunEntry.getReportEntryType() == SUCCESS ) - { - runtime = singleRunEntry.elapsedTimeAsString(); - break; - } - } - startTestElement( ppw, methodEntryList.get( 0 ), reportNameSuffix, runtime ); - for ( WrappedReportEntry singleRunEntry : methodEntryList ) - { - if ( singleRunEntry.getReportEntryType() != SUCCESS ) - { - getTestProblems( fw, ppw, singleRunEntry, trimStackTrace, outputStream, - singleRunEntry.getReportEntryType().getFlakyXmlTag(), true ); - } - } - ppw.endElement(); - - break; - case skipped: - startTestElement( ppw, methodEntryList.get( 0 ), reportNameSuffix, - methodEntryList.get( 0 ).elapsedTimeAsString() ); - getTestProblems( fw, ppw, methodEntryList.get( 0 ), trimStackTrace, outputStream, - methodEntryList.get( 0 ).getReportEntryType().getXmlTag(), false ); - ppw.endElement(); - break; - default: - throw new IllegalStateException( "Get unknown test result type" ); - } - } - else - { - // rerunFailingTestsCount is smaller than 1, but for some reasons a test could be run - // for more than once - for ( WrappedReportEntry methodEntry : methodEntryList ) - { - startTestElement( ppw, methodEntry, reportNameSuffix, methodEntry.elapsedTimeAsString() ); - if ( methodEntry.getReportEntryType() != SUCCESS ) - { - getTestProblems( fw, ppw, methodEntry, trimStackTrace, outputStream, - methodEntry.getReportEntryType().getXmlTag(), false ); - createOutErrElements( fw, ppw, methodEntry, outputStream ); - } - ppw.endElement(); - } - } + serializeTestClass( outputStream, fw, ppw, thisMethodRuns.getValue() ); } } + ppw.endElement(); // TestSuite } catch ( Exception e ) @@ -246,6 +165,143 @@ public void testSetCompleted( WrappedReportEntry testSetReportEntry, TestSetStat } } + private Map>> arrangeMethodStatistics( + WrappedReportEntry testSetReportEntry, TestSetStats testSetStats ) + { + Map>> classMethodStatistics = new LinkedHashMap<>(); + for ( WrappedReportEntry methodEntry : aggregateCacheFromMultipleReruns( testSetReportEntry, testSetStats ) ) + { + String testClassName = methodEntry.getSourceName(); + Map> stats = classMethodStatistics.get( testClassName ); + if ( stats == null ) + { + stats = new LinkedHashMap<>(); + classMethodStatistics.put( testClassName, stats ); + } + String methodName = methodEntry.getName(); + List methodRuns = stats.get( methodName ); + if ( methodRuns == null ) + { + methodRuns = new ArrayList<>(); + stats.put( methodName, methodRuns ); + } + methodRuns.add( methodEntry ); + } + return classMethodStatistics; + } + + private Deque aggregateCacheFromMultipleReruns( WrappedReportEntry testSetReportEntry, + TestSetStats testSetStats ) + { + String suiteClassName = testSetReportEntry.getSourceName(); + Deque methodRunHistory = getAddMethodRunHistoryMap( suiteClassName ); + methodRunHistory.addAll( testSetStats.getReportEntries() ); + return methodRunHistory; + } + + private void serializeTestClass( OutputStream outputStream, OutputStreamWriter fw, XMLWriter ppw, + List methodEntries ) + { + if ( rerunFailingTestsCount > 0 ) + { + serializeTestClassWithRerun( outputStream, fw, ppw, methodEntries ); + } + else + { + // rerunFailingTestsCount is smaller than 1, but for some reasons a test could be run + // for more than once + serializeTestClassWithoutRerun( outputStream, fw, ppw, methodEntries ); + } + } + + private void serializeTestClassWithoutRerun( OutputStream outputStream, OutputStreamWriter fw, XMLWriter ppw, + List methodEntries ) + { + for ( WrappedReportEntry methodEntry : methodEntries ) + { + startTestElement( ppw, methodEntry ); + if ( methodEntry.getReportEntryType() != SUCCESS ) + { + getTestProblems( fw, ppw, methodEntry, trimStackTrace, outputStream, + methodEntry.getReportEntryType().getXmlTag(), false ); + createOutErrElements( fw, ppw, methodEntry, outputStream ); + } + ppw.endElement(); + } + } + + private void serializeTestClassWithRerun( OutputStream outputStream, OutputStreamWriter fw, XMLWriter ppw, + List methodEntries ) + { + WrappedReportEntry firstMethodEntry = methodEntries.get( 0 ); + switch ( getTestResultType( methodEntries ) ) + { + case success: + for ( WrappedReportEntry methodEntry : methodEntries ) + { + if ( methodEntry.getReportEntryType() == SUCCESS ) + { + startTestElement( ppw, methodEntry ); + ppw.endElement(); + } + } + break; + case error: + case failure: + // When rerunFailingTestsCount is set to larger than 0 + startTestElement( ppw, firstMethodEntry ); + boolean firstRun = true; + for ( WrappedReportEntry singleRunEntry : methodEntries ) + { + if ( firstRun ) + { + firstRun = false; + getTestProblems( fw, ppw, singleRunEntry, trimStackTrace, outputStream, + singleRunEntry.getReportEntryType().getXmlTag(), false ); + createOutErrElements( fw, ppw, singleRunEntry, outputStream ); + } + else + { + getTestProblems( fw, ppw, singleRunEntry, trimStackTrace, outputStream, + singleRunEntry.getReportEntryType().getRerunXmlTag(), true ); + } + } + ppw.endElement(); + break; + case flake: + WrappedReportEntry successful = null; + // Get the run time of the first successful run + for ( WrappedReportEntry singleRunEntry : methodEntries ) + { + if ( singleRunEntry.getReportEntryType() == SUCCESS ) + { + successful = singleRunEntry; + break; + } + } + WrappedReportEntry firstOrSuccessful = successful == null ? methodEntries.get( 0 ) : successful; + startTestElement( ppw, firstOrSuccessful ); + for ( WrappedReportEntry singleRunEntry : methodEntries ) + { + if ( singleRunEntry.getReportEntryType() != SUCCESS ) + { + getTestProblems( fw, ppw, singleRunEntry, trimStackTrace, outputStream, + singleRunEntry.getReportEntryType().getFlakyXmlTag(), true ); + } + } + ppw.endElement(); + break; + case skipped: + startTestElement( ppw, firstMethodEntry ); + getTestProblems( fw, ppw, firstMethodEntry, trimStackTrace, outputStream, + firstMethodEntry.getReportEntryType().getXmlTag(), false ); + ppw.endElement(); + break; + default: + throw new IllegalStateException( "Get unknown test result type" ); + } + } + /** * Clean testClassMethodRunHistoryMap */ @@ -271,20 +327,20 @@ private TestResultType getTestResultType( List methodEntryLi return DefaultReporterFactory.getTestResultType( testResultTypeList, rerunFailingTestsCount ); } - private Map> getAddMethodRunHistoryMap( String testClassName ) + private Deque getAddMethodRunHistoryMap( String testClassName ) { - Map> methodRunHistoryMap = testClassMethodRunHistoryMap.get( testClassName ); - if ( methodRunHistoryMap == null ) + Deque methodRunHistory = testClassMethodRunHistoryMap.get( testClassName ); + if ( methodRunHistory == null ) { - methodRunHistoryMap = Collections.synchronizedMap( new LinkedHashMap>() ); - testClassMethodRunHistoryMap.put( testClassName, methodRunHistoryMap ); + methodRunHistory = new ConcurrentLinkedDeque<>(); + testClassMethodRunHistoryMap.put( testClassName == null ? "null" : testClassName, methodRunHistory ); } - return methodRunHistoryMap; + return methodRunHistory; } private OutputStream getOutputStream( WrappedReportEntry testSetReportEntry ) { - File reportFile = getReportFile( testSetReportEntry, reportsDirectory, reportNameSuffix ); + File reportFile = getReportFile( testSetReportEntry ); File reportDir = reportFile.getParentFile(); @@ -293,7 +349,7 @@ private OutputStream getOutputStream( WrappedReportEntry testSetReportEntry ) try { - return new BufferedOutputStream( new FileOutputStream( reportFile ), 16 * 1024 ); + return new BufferedOutputStream( new FileOutputStream( reportFile ), 64 * 1024 ); } catch ( Exception e ) { @@ -306,65 +362,52 @@ private static OutputStreamWriter getWriter( OutputStream fos ) return new OutputStreamWriter( fos, UTF_8 ); } - private static void getAddMethodEntryList( Map> methodRunHistoryMap, - WrappedReportEntry methodEntry ) + private File getReportFile( WrappedReportEntry report ) { - List methodEntryList = methodRunHistoryMap.get( methodEntry.getName() ); - if ( methodEntryList == null ) - { - methodEntryList = new ArrayList<>(); - methodRunHistoryMap.put( methodEntry.getName(), methodEntryList ); - } - methodEntryList.add( methodEntry ); - } - - private static File getReportFile( ReportEntry report, File reportsDirectory, String reportNameSuffix ) - { - String reportName = "TEST-" + report.getName(); + String reportName = "TEST-" + ( phrasedFileName ? report.getReportSourceName() : report.getSourceName() ); String customizedReportName = isBlank( reportNameSuffix ) ? reportName : reportName + "-" + reportNameSuffix; return new File( reportsDirectory, stripIllegalFilenameChars( customizedReportName + ".xml" ) ); } - private static void startTestElement( XMLWriter ppw, WrappedReportEntry report, String reportNameSuffix, - String timeAsString ) + private void startTestElement( XMLWriter ppw, WrappedReportEntry report ) { ppw.startElement( "testcase" ); - ppw.addAttribute( "name", report.getReportName() ); + String name = phrasedMethodName ? report.getReportName() : report.getName(); + ppw.addAttribute( "name", name == null ? "" : extraEscapeAttribute( name ) ); + if ( report.getGroup() != null ) { ppw.addAttribute( "group", report.getGroup() ); } - if ( report.getSourceName() != null ) + + String className = phrasedClassName ? report.getReportSourceName( reportNameSuffix ) + : report.getSourceName( reportNameSuffix ); + if ( className != null ) { - if ( reportNameSuffix != null && !reportNameSuffix.isEmpty() ) - { - ppw.addAttribute( "classname", report.getSourceName() + "(" + reportNameSuffix + ")" ); - } - else - { - ppw.addAttribute( "classname", report.getSourceName() ); - } + ppw.addAttribute( "classname", extraEscapeAttribute( className ) ); } - ppw.addAttribute( "time", timeAsString ); + + ppw.addAttribute( "time", report.elapsedTimeAsString() ); } - private void createTestSuiteElement( XMLWriter ppw, WrappedReportEntry report, TestSetStats testSetStats, - String timeAsString ) + private void createTestSuiteElement( XMLWriter ppw, WrappedReportEntry report, TestSetStats testSetStats ) { ppw.startElement( "testsuite" ); ppw.addAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); ppw.addAttribute( "xsi:noNamespaceSchemaLocation", xsdSchemaLocation ); - ppw.addAttribute( "version", "3.0" ); + ppw.addAttribute( "version", xsdVersion ); - ppw.addAttribute( "name", report.getReportName( reportNameSuffix ) ); + String reportName = phrasedSuiteName ? report.getReportSourceName( reportNameSuffix ) + : report.getSourceName( reportNameSuffix ); + ppw.addAttribute( "name", reportName == null ? "" : extraEscapeAttribute( reportName ) ); if ( report.getGroup() != null ) { ppw.addAttribute( "group", report.getGroup() ); } - ppw.addAttribute( "time", timeAsString ); + ppw.addAttribute( "time", report.elapsedTimeAsString() ); ppw.addAttribute( "tests", String.valueOf( testSetStats.getCompletedCount() ) ); @@ -385,7 +428,7 @@ private static void getTestProblems( OutputStreamWriter outputStreamWriter, XMLW if ( report.getMessage() != null && !report.getMessage().isEmpty() ) { - ppw.addAttribute( "message", extraEscape( report.getMessage(), true ) ); + ppw.addAttribute( "message", extraEscapeAttribute( report.getMessage() ) ); } if ( report.getStackTraceWriter() != null ) @@ -416,7 +459,7 @@ private static void getTestProblems( OutputStreamWriter outputStreamWriter, XMLW ppw.startElement( "stackTrace" ); } - ppw.writeText( extraEscape( stackTrace, false ) ); + extraEscapeElementValue( stackTrace, outputStreamWriter, ppw, fw ); if ( hasNestedElements ) { @@ -491,7 +534,7 @@ private static void showProperties( XMLWriter xmlWriter, Map sys xmlWriter.addAttribute( "name", key ); - xmlWriter.addAttribute( "value", extraEscape( value, true ) ); + xmlWriter.addAttribute( "value", extraEscapeAttribute( value ) ); xmlWriter.endElement(); } @@ -499,16 +542,47 @@ private static void showProperties( XMLWriter xmlWriter, Map sys } /** - * Handle stuff that may pop up in java that is not legal in xml + * Handle stuff that may pop up in java that is not legal in xml. + * + * @param message The string + * @return The escaped string or returns itself if all characters are legal + */ + private static String extraEscapeAttribute( String message ) + { + // Someday convert to xml 1.1 which handles everything but 0 inside string + return containsEscapesIllegalXml10( message ) ? escapeXml( message, true ) : message; + } + + /** + * Writes escaped string or the message within CDATA if all characters are legal. * * @param message The string - * @param attribute true if the escaped value is inside an attribute - * @return The escaped string */ - private static String extraEscape( String message, boolean attribute ) + private static void extraEscapeElementValue( String message, OutputStreamWriter outputStreamWriter, + XMLWriter xmlWriter, OutputStream fw ) { // Someday convert to xml 1.1 which handles everything but 0 inside string - return containsEscapesIllegalXml10( message ) ? escapeXml( message, attribute ) : message; + if ( containsEscapesIllegalXml10( message ) ) + { + xmlWriter.writeText( escapeXml( message, false ) ); + } + else + { + try + { + EncodingOutputStream eos = new EncodingOutputStream( fw ); + xmlWriter.writeText( "" ); // Cheat sax to emit element + outputStreamWriter.flush(); + eos.getUnderlying().write( ByteConstantsHolder.CDATA_START_BYTES ); + eos.write( message.getBytes( UTF_8 ) ); + eos.getUnderlying().write( ByteConstantsHolder.CDATA_END_BYTES ); + eos.flush(); + } + catch ( IOException e ) + { + throw new ReporterException( "When writing xml element", e ); + } + } } private static final class EncodingOutputStream @@ -585,6 +659,13 @@ private static boolean isIllegalEscape( int c ) return c >= 0 && c < 32 && c != '\n' && c != '\r' && c != '\t'; } + /** + * escape for XML 1.0 + * + * @param text The string + * @param attribute true if the escaped value is inside an attribute + * @return The escaped string + */ private static String escapeXml( String text, boolean attribute ) { StringBuilder sb = new StringBuilder( text.length() * 2 ); diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java index 995d687348..2adbac4b5b 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetRunListener.java @@ -27,15 +27,22 @@ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.plugin.surefire.runorder.StatisticsReporter; +import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener; +import org.apache.maven.surefire.extensions.StatelessReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener; import org.apache.maven.surefire.report.ConsoleOutputReceiver; import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.RunListener; +import org.apache.maven.surefire.report.RunMode; import org.apache.maven.surefire.report.TestSetReportEntry; import static org.apache.maven.plugin.surefire.report.ReportEntryType.ERROR; import static org.apache.maven.plugin.surefire.report.ReportEntryType.FAILURE; import static org.apache.maven.plugin.surefire.report.ReportEntryType.SKIPPED; import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS; +import static org.apache.maven.surefire.report.RunMode.NORMAL_RUN; +import static java.util.Objects.requireNonNull; /** * Reports data for a single test set. @@ -50,15 +57,15 @@ public class TestSetRunListener private final TestSetStats detailsForThis; - private final TestcycleConsoleOutputReceiver consoleOutputReceiver; + private final ConsoleOutputReportEventListener consoleOutputReceiver; private final boolean briefOrPlainFormat; - private final StatelessXmlReporter simpleXMLReporter; + private final StatelessReportEventListener simpleXMLReporter; - private final ConsoleReporter consoleReporter; + private final StatelessTestsetInfoConsoleReportEventListener consoleReporter; - private final FileReporter fileReporter; + private final StatelessTestsetInfoFileReportEventListener fileReporter; private final StatisticsReporter statisticsReporter; @@ -66,10 +73,15 @@ public class TestSetRunListener private Utf8RecodingDeferredFileOutputStream testStdErr = initDeferred( "stderr" ); + private volatile RunMode runMode = NORMAL_RUN; + @SuppressWarnings( "checkstyle:parameternumber" ) - public TestSetRunListener( ConsoleReporter consoleReporter, FileReporter fileReporter, - StatelessXmlReporter simpleXMLReporter, - TestcycleConsoleOutputReceiver consoleOutputReceiver, + public TestSetRunListener( StatelessTestsetInfoConsoleReportEventListener + consoleReporter, + StatelessTestsetInfoFileReportEventListener + fileReporter, + StatelessReportEventListener simpleXMLReporter, + ConsoleOutputReportEventListener consoleOutputReceiver, StatisticsReporter statisticsReporter, boolean trimStackTrace, boolean isPlainFormat, boolean briefOrPlainFormat ) { @@ -133,7 +145,7 @@ public void error( String message ) @Override public void error( String message, Throwable t ) { - consoleReporter.getConsoleLogger().error( message, t ); + consoleReporter.getConsoleLogger().error( trimTrailingNewLine( message ), t ); } @Override @@ -143,13 +155,13 @@ public void error( Throwable t ) } @Override - public synchronized void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) + public void writeTestOutput( String output, boolean newLine, boolean stdout ) { try { - Utf8RecodingDeferredFileOutputStream os = stdout ? testStdOut : testStdErr; - os.write( buf, off, len ); - consoleOutputReceiver.writeTestOutput( buf, off, len, stdout ); + Utf8RecodingDeferredFileOutputStream stream = stdout ? testStdOut : testStdErr; + stream.write( output, newLine ); + consoleOutputReceiver.writeTestOutput( output, newLine, stdout ); } catch ( IOException e ) { @@ -247,6 +259,13 @@ public void testExecutionSkippedByUser() { } + public RunMode markAs( RunMode currentRunMode ) + { + RunMode runMode = this.runMode; + this.runMode = requireNonNull( currentRunMode ); + return runMode; + } + @Override public void testAssumptionFailure( ReportEntry report ) { diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java index 8698159ba1..3e360c1e96 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestSetStats.java @@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; +import static org.apache.maven.surefire.report.CategorizedReportEntry.GROUP_PREFIX; /** * Maintains per-thread test result state. Not thread safe. @@ -169,7 +170,7 @@ private void incrementCompletedCount() completedCount += 1; } - public String getTestSetSummary( WrappedReportEntry reportEntry ) + public String getTestSetSummary( WrappedReportEntry reportEntry, boolean phrasedClassName ) { String summary = TESTS_RUN + completedCount + COMMA @@ -186,12 +187,13 @@ public String getTestSetSummary( WrappedReportEntry reportEntry ) summary += FAILURE_MARKER; } - summary += IN_MARKER + reportEntry.getNameWithGroup(); + summary += IN_MARKER; + summary += phrasedClassName ? reportEntry.getReportNameWithGroup() : reportEntry.getNameWithGroup(); return summary; } - public String getColoredTestSetSummary( WrappedReportEntry reportEntry ) + public String getColoredTestSetSummary( WrappedReportEntry reportEntry, boolean phrasedClassName ) { final boolean isSuccessful = failures == 0 && errors == 0 && skipped == 0; final boolean isFailure = failures > 0; @@ -255,7 +257,7 @@ public String getColoredTestSetSummary( WrappedReportEntry reportEntry ) builder.failure( FAILURE_MARKER ); } builder.a( IN_MARKER ); - return concatenateWithTestGroup( builder, reportEntry ); + return concatenateWithTestGroup( builder, reportEntry, phrasedClassName ); } public List getTestResults() @@ -269,7 +271,7 @@ public List getTestResults() } else if ( plainFormat && testResult.isSkipped() ) { - result.add( testResult.getName() + " skipped" ); + result.add( testResult.getSourceName() + " skipped" ); } else if ( plainFormat && testResult.isSucceeded() ) { @@ -287,20 +289,29 @@ public Collection getReportEntries() /** * Append the test set message for a report. - * e.g. "org.foo.BarTest ( of group )" + * e.g. "org.foo.BarTest ( of group )" or phrased text "test class description ( of group )". * * @param builder MessageBuilder with preceded text inside * @param report report whose test set is starting * @return the message */ - static String concatenateWithTestGroup( MessageBuilder builder, ReportEntry report ) + static String concatenateWithTestGroup( MessageBuilder builder, ReportEntry report, boolean phrasedClassName ) { - final String testClass = report.getNameWithGroup(); - int delimiter = testClass.lastIndexOf( '.' ); - String pkg = testClass.substring( 0, 1 + delimiter ); - String cls = testClass.substring( 1 + delimiter ); - return builder.a( pkg ) - .strong( cls ) - .toString(); + if ( phrasedClassName ) + { + return builder.strong( report.getReportNameWithGroup() ) + .toString(); + } + else + { + String testClass = report.getNameWithGroup(); + int indexOfGroup = testClass.indexOf( GROUP_PREFIX ); + int delimiter = testClass.lastIndexOf( '.', indexOfGroup == -1 ? testClass.length() : indexOfGroup ); + String pkg = testClass.substring( 0, 1 + delimiter ); + String cls = testClass.substring( 1 + delimiter ); + return builder.a( pkg ) + .strong( cls ) + .toString(); + } } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestcycleConsoleOutputReceiver.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestcycleConsoleOutputReceiver.java index f1b5b5a397..cdd4b3a4a0 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestcycleConsoleOutputReceiver.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/TestcycleConsoleOutputReceiver.java @@ -19,18 +19,19 @@ * under the License. */ +import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener; import org.apache.maven.surefire.report.ConsoleOutputReceiver; -import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.TestSetReportEntry; /** * @author Kristian Rosenvold */ public interface TestcycleConsoleOutputReceiver - extends ConsoleOutputReceiver + extends ConsoleOutputReceiver, ConsoleOutputReportEventListener { - void testSetStarting( ReportEntry reportEntry ); + void testSetStarting( TestSetReportEntry reportEntry ); - void testSetCompleted( ReportEntry report ); + void testSetCompleted( TestSetReportEntry report ); void close(); } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/Utf8RecodingDeferredFileOutputStream.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/Utf8RecodingDeferredFileOutputStream.java index 8b496cdf2a..c3eda011d9 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/Utf8RecodingDeferredFileOutputStream.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/Utf8RecodingDeferredFileOutputStream.java @@ -23,11 +23,9 @@ import java.io.IOException; import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.maven.surefire.util.internal.StringUtils.NL; /** * A deferred file output stream decorator that recodes the bytes written into the stream from the VM default encoding @@ -44,10 +42,10 @@ class Utf8RecodingDeferredFileOutputStream @SuppressWarnings( "checkstyle:magicnumber" ) Utf8RecodingDeferredFileOutputStream( String channel ) { - this.deferredFileOutputStream = new DeferredFileOutputStream( 1000000, channel, "deferred", null ); + deferredFileOutputStream = new DeferredFileOutputStream( 1000000, channel, "deferred", null ); } - public synchronized void write( byte[] buf, int off, int len ) + public synchronized void write( String output, boolean newLine ) throws IOException { if ( closed ) @@ -55,28 +53,15 @@ public synchronized void write( byte[] buf, int off, int len ) return; } - if ( !Charset.defaultCharset().equals( UTF_8 ) ) + if ( output == null ) { - CharBuffer decodedFromDefaultCharset = Charset.defaultCharset().decode( ByteBuffer.wrap( buf, off, len ) ); - ByteBuffer utf8Encoded = UTF_8.encode( decodedFromDefaultCharset ); - - if ( utf8Encoded.hasArray() ) - { - byte[] convertedBytes = utf8Encoded.array(); - - deferredFileOutputStream.write( convertedBytes, utf8Encoded.position(), utf8Encoded.remaining() ); - } - else - { - byte[] convertedBytes = new byte[utf8Encoded.remaining()]; - utf8Encoded.get( convertedBytes, 0, utf8Encoded.remaining() ); - - deferredFileOutputStream.write( convertedBytes, 0, convertedBytes.length ); - } + output = "null"; } - else + + deferredFileOutputStream.write( output.getBytes( UTF_8 ) ); + if ( newLine ) { - deferredFileOutputStream.write( buf, off, len ); + deferredFileOutputStream.write( NL.getBytes( UTF_8 ) ); } } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java index 3426e3a252..102eea44a3 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/report/WrappedReportEntry.java @@ -29,6 +29,7 @@ import static java.util.Collections.unmodifiableMap; import static org.apache.maven.plugin.surefire.report.ReporterUtils.formatElapsedTime; import static org.apache.maven.surefire.util.internal.StringUtils.NL; +import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; /** * @author Kristian Rosenvold @@ -74,6 +75,12 @@ public Integer getElapsed() return elapsed; } + @Override + public int getElapsed( int fallback ) + { + return elapsed == null ? fallback : elapsed; + } + public ReportEntryType getReportEntryType() { return reportEntryType; @@ -95,15 +102,27 @@ public String getSourceName() return original.getSourceName(); } + @Override + public String getSourceText() + { + return original.getSourceText(); + } + @Override public String getName() { return original.getName(); } + @Override + public String getNameText() + { + return original.getNameText(); + } + public String getClassMethodName() { - return getSourceName() + "." + getName(); + return original.getSourceName() + "." + original.getName(); } @Override @@ -135,15 +154,28 @@ public String elapsedTimeAsString() return formatElapsedTime( getElapsed() ); } - public String getReportName() + String getReportSourceName() + { + String sourceName = getSourceName(); + String sourceText = getSourceText(); + return isBlank( sourceText ) ? sourceName : sourceText; + } + + String getReportSourceName( String suffix ) { - final int i = getName().lastIndexOf( "(" ); - return i > 0 ? getName().substring( 0, i ) : getName(); + return isBlank( suffix ) ? getReportSourceName() : getReportSourceName() + "(" + suffix + ")"; } - public String getReportName( String suffix ) + String getSourceName( String suffix ) { - return suffix != null && !suffix.isEmpty() ? getReportName() + "(" + suffix + ")" : getReportName(); + return isBlank( suffix ) ? getSourceName() : getSourceName() + "(" + suffix + ")"; + } + + String getReportName() + { + String name = getName(); + String nameText = getNameText(); + return isBlank( nameText ) ? name : nameText; } public String getOutput( boolean trimStackTrace ) @@ -160,7 +192,8 @@ public String getElapsedTimeVerbose() public String getElapsedTimeSummary() { - return getName() + " " + getElapsedTimeVerbose(); + String description = getName() == null ? getSourceName() : getClassMethodName(); + return description + " " + getElapsedTimeVerbose(); } public boolean isErrorOrFailure() @@ -185,6 +218,12 @@ public String getNameWithGroup() return original.getNameWithGroup(); } + @Override + public String getReportNameWithGroup() + { + return original.getReportNameWithGroup(); + } + @Override public Map getSystemProperties() { diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java index a53db0241d..fb5450b31f 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/runorder/StatisticsReporter.java @@ -20,7 +20,8 @@ */ import java.io.File; -import java.io.FileNotFoundException; +import java.io.IOException; + import org.apache.maven.surefire.report.ReportEntry; import static org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMap.fromFile; @@ -41,11 +42,11 @@ public StatisticsReporter( File dataFile ) this( dataFile, fromFile( dataFile ), new RunEntryStatisticsMap() ); } - protected StatisticsReporter( File dataFile, RunEntryStatisticsMap existing, RunEntryStatisticsMap newRestuls ) + protected StatisticsReporter( File dataFile, RunEntryStatisticsMap existing, RunEntryStatisticsMap newResults ) { this.dataFile = dataFile; this.existing = existing; - this.newResults = newRestuls; + this.newResults = newResults; } public synchronized void testSetCompleted() @@ -54,7 +55,7 @@ public synchronized void testSetCompleted() { newResults.serialize( dataFile ); } - catch ( FileNotFoundException e ) + catch ( IOException e ) { throw new RuntimeException( e ); } diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java index 34e8e7fcc8..7ddcfbe00f 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java @@ -19,12 +19,17 @@ * under the License. */ -import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertJarFileResourceToJavaClassName; -import static org.apache.maven.plugin.surefire.util.ScannerUtil.isJavaClassFile; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.shared.artifact.filter.PatternIncludesArtifactFilter; +import org.apache.maven.surefire.testset.TestFilter; +import org.apache.maven.surefire.testset.TestListResolver; +import org.apache.maven.surefire.util.DefaultScanResult; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.List; @@ -32,11 +37,8 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.surefire.testset.TestFilter; -import org.apache.maven.surefire.testset.TestListResolver; -import org.apache.maven.surefire.util.DefaultScanResult; +import static org.apache.maven.plugin.surefire.util.ScannerUtil.convertJarFileResourceToJavaClassName; +import static org.apache.maven.plugin.surefire.util.ScannerUtil.isJavaClassFile; /** * Scans dependencies looking for tests. @@ -93,28 +95,29 @@ private static void scanArtifact( File artifact, TestFilter filt } } - public static List filter( List artifacts, List groupArtifactIds ) + /** + * + * @param artifacts a list to filter + * @param artifactPatterns a list of strings in the form + *
groupId[:artifactId[:type[:classifier][:version]]]
+ * @return list of items from artifacts that match any of the filters in groupArtifactIds, + * empty if none match + */ + public static List filter( List artifacts, List artifactPatterns ) { - List matches = new ArrayList<>(); - if ( groupArtifactIds == null || artifacts == null ) + if ( artifactPatterns == null || artifacts == null || artifacts.isEmpty() ) { - return matches; + return Collections.emptyList(); } + + PatternIncludesArtifactFilter artifactFilter = new PatternIncludesArtifactFilter( artifactPatterns ); + + List matches = new ArrayList<>(); for ( Artifact artifact : artifacts ) { - for ( String groups : groupArtifactIds ) + if ( artifactFilter.include( artifact ) ) { - String[] groupArtifact = groups.split( ":" ); - if ( groupArtifact.length != 2 ) - { - throw new IllegalArgumentException( "dependencyToScan argument should be in format" - + " 'groupid:artifactid': " + groups ); - } - if ( artifact.getGroupId().matches( groupArtifact[0] ) - && artifact.getArtifactId().matches( groupArtifact[1] ) ) - { - matches.add( artifact ); - } + matches.add( artifact ); } } return matches; diff --git a/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java b/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java index 29aa8dcbb5..7c911ecbd9 100644 --- a/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java +++ b/maven-surefire-common/src/main/java/org/apache/maven/surefire/report/RunStatistics.java @@ -19,13 +19,12 @@ * under the License. */ -import org.apache.maven.plugin.surefire.report.TestSetStats; import org.apache.maven.surefire.suite.RunResult; /** * @author Kristian Rosenvold */ -public class RunStatistics +public final class RunStatistics { private int completedCount; @@ -37,16 +36,6 @@ public class RunStatistics private int flakes; - public synchronized boolean hadFailures() - { - return failures > 0; - } - - public synchronized boolean hadErrors() - { - return errors > 0; - } - public synchronized int getCompletedCount() { return completedCount; @@ -72,14 +61,6 @@ public synchronized int getFlakes() return flakes; } - public synchronized void add( TestSetStats testSetStats ) - { - this.completedCount += testSetStats.getCompletedCount(); - this.errors += testSetStats.getErrors(); - this.failures += testSetStats.getFailures(); - this.skipped += testSetStats.getSkipped(); - } - public synchronized void set( int completedCount, int errors, int failures, int skipped, int flakes ) { this.completedCount = completedCount; 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 17cd9307b5..9d1fcf80e7 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 @@ -30,6 +30,7 @@ import org.apache.maven.surefire.booter.StartupConfiguration; import org.apache.maven.surefire.suite.RunResult; import org.apache.maven.surefire.util.DefaultScanResult; +import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor; import org.codehaus.plexus.languages.java.jpms.LocationManager; import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest; import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult; @@ -39,12 +40,14 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.io.File; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.List; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -63,7 +66,6 @@ import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.spy; -import static org.powermock.api.mockito.PowerMockito.verifyPrivate; import static org.powermock.api.mockito.PowerMockito.verifyStatic; import static org.powermock.reflect.Whitebox.invokeMethod; @@ -72,6 +74,7 @@ */ @RunWith( PowerMockRunner.class ) @PrepareForTest( { AbstractSurefireMojo.class, ResolvePathsRequest.class } ) +@PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } ) public class AbstractSurefireMojoJava7PlusTest { @Mock @@ -80,7 +83,11 @@ public class AbstractSurefireMojoJava7PlusTest @Mock private LocationManager locationManager; + @Mock + private JavaModuleDescriptor descriptor; + @Test + @SuppressWarnings( "checkstyle:linelength" ) public void shouldHaveStartupConfigForModularClasspath() throws Exception { @@ -111,7 +118,7 @@ public void shouldHaveStartupConfigForModularClasspath() TestClassPath testClasspath = new TestClassPath( asList( modular, nonModular, junit, hamcrest ), classesDir, testClassesDir, - null, null ); + null ); doReturn( testClasspath ).when( mojo, "generateTestClasspath" ); doReturn( 1 ).when( mojo, "getEffectiveForkCount" ); @@ -139,8 +146,11 @@ public void shouldHaveStartupConfigForModularClasspath() when( req.setJdkHome( anyString() ) ).thenReturn( req ); when( req.setMainModuleDescriptor( eq( moduleInfo.getAbsolutePath() ) ) ).thenReturn( req ); + when( descriptor.name() ).thenReturn( "abc" ); + @SuppressWarnings( "unchecked" ) ResolvePathsResult res = mock( ResolvePathsResult.class ); + when( res.getMainModuleDescriptor() ).thenReturn( descriptor ); when( res.getClasspathElements() ).thenReturn( asList( "non-modular.jar", "junit.jar", "hamcrest.jar" ) ); Map mod = new LinkedHashMap<>(); mod.put( "modular.jar", null ); @@ -154,13 +164,35 @@ public void shouldHaveStartupConfigForModularClasspath() 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 ext = new DefaultArtifact( "org.apache.maven.surefire", "surefire-extensions-api", v5, "runtime", + "jar", "", handler ); + ext.setFile( mockFile( "surefire-extensions-api.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 artifacts = new HashMap<>(); + artifacts.put( "org.apache.maven.surefire:maven-surefire-common", common ); + artifacts.put( "org.apache.maven.surefire:surefire-extensions-api", ext ); + 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, - "" ); + "", testClasspath ); verify( mojo, times( 1 ) ).effectiveIsEnableAssertions(); verify( mojo, times( 1 ) ).isChildDelegation(); - verifyPrivate( mojo, times( 1 ) ).invoke( "generateTestClasspath" ); verify( mojo, times( 1 ) ).getEffectiveForkCount(); verify( mojo, times( 1 ) ).getTestClassesDirectory(); verify( scanResult, times( 1 ) ).getClasses(); @@ -178,14 +210,17 @@ public void shouldHaveStartupConfigForModularClasspath() assertThat( argument2.getValue().getMessage() ) .isEqualTo( "low version" ); ArgumentCaptor argument = ArgumentCaptor.forClass( String.class ); - verify( logger, times( 6 ) ).debug( argument.capture() ); + verify( logger, times( 9 ) ).debug( argument.capture() ); assertThat( argument.getAllValues() ) - .containsExactly( "test classpath: non-modular.jar junit.jar hamcrest.jar", + .containsExactly( "main module descriptor name: abc", + "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-extensions-api.jar surefire-api.jar surefire-logger-api.jar", + "in-process(compact) classpath: surefire-provider.jar maven-surefire-common.jar surefire-extensions-api.jar surefire-api.jar surefire-logger-api.jar" ); assertThat( conf ).isNotNull(); @@ -202,13 +237,12 @@ public void shouldHaveStartupConfigForModularClasspath() .isEqualTo( new Classpath( singleton( "surefire-provider.jar" ) ) ); assertThat( conf.getClasspathConfiguration() ).isInstanceOf( ModularClasspathConfiguration.class ); ModularClasspathConfiguration mcc = ( ModularClasspathConfiguration ) conf.getClasspathConfiguration(); - assertThat( mcc.getModularClasspath().getModuleDescriptor() ).isEqualTo( moduleInfo ); + assertThat( mcc.getModularClasspath().getModuleNameFromDescriptor() ).isEqualTo( "abc" ); assertThat( mcc.getModularClasspath().getPackages() ).containsOnly( "org.apache" ); assertThat( mcc.getModularClasspath().getPatchFile().getAbsolutePath() ) .isEqualTo( "test-classes" ); assertThat( mcc.getModularClasspath().getModulePath() ) .containsExactly( "modular.jar", "classes" ); - assertThat( ( Object ) mcc.getTestClasspath() ).isEqualTo( new Classpath( res.getClasspathElements() ) ); } private static File mockFile( String absolutePath ) @@ -218,6 +252,9 @@ private static File mockFile( String absolutePath ) return f; } + /** + * + */ public static class Mojo extends AbstractSurefireMojo { @@ -522,6 +559,12 @@ protected boolean hasSuiteXmlFiles() return false; } + @Override + protected String[] getExcludedEnvironmentVariables() + { + return new String[0]; + } + @Override public File[] getSuiteXmlFiles() { @@ -582,6 +625,12 @@ protected void setUseModulePath( boolean useModulePath ) } + @Override + protected String getEnableProcessChecker() + { + return null; + } + @Override protected Artifact getMojoArtifact() { diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java index a6fc7085bf..c768e498ef 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/AbstractSurefireMojoTest.java @@ -22,18 +22,38 @@ import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.handler.ArtifactHandler; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Plugin; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.surefire.AbstractSurefireMojo.JUnitPlatformProviderInfo; import org.apache.maven.plugin.surefire.log.PluginConsoleLogger; import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter; +import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult; +import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver; import org.apache.maven.surefire.booter.ClassLoaderConfiguration; import org.apache.maven.surefire.booter.Classpath; import org.apache.maven.surefire.booter.StartupConfiguration; import org.apache.maven.surefire.suite.RunResult; import org.codehaus.plexus.logging.Logger; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -41,8 +61,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -50,13 +72,18 @@ import static java.io.File.separatorChar; import static java.util.Arrays.asList; +import static java.util.Collections.emptySet; import static java.util.Collections.singleton; +import static java.util.Collections.singletonMap; import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS; import static org.apache.maven.artifact.versioning.VersionRange.createFromVersion; import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec; import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.MapAssert.entry; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; @@ -72,13 +99,59 @@ */ @RunWith( PowerMockRunner.class ) @PrepareForTest( AbstractSurefireMojo.class ) +@PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } ) public class AbstractSurefireMojoTest { + @Rule + public final ExpectedException e = ExpectedException.none(); + @Mock private ArtifactHandler handler; private final Mojo mojo = new Mojo(); + @Test + public void shouldShowArray() throws Exception + { + Logger logger = mock( Logger.class ); + when( logger.isDebugEnabled() ).thenReturn( true ); + doNothing().when( logger ).debug( anyString() ); + + AbstractSurefireMojo mojo = spy( this.mojo ); + + when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) ); + + Object[] array = { "ABC", "XYZ" }; + invokeMethod( mojo, "showArray", array, "prefix" ); + + ArgumentCaptor argument = ArgumentCaptor.forClass( String.class ); + verify( logger, times( 2 ) ).debug( argument.capture() ); + assertThat( argument.getAllValues() ) + .containsExactly( "Setting prefix [ABC]", "Setting prefix [XYZ]" ); + } + + @Test + public void shouldShowMap() throws Exception + { + Logger logger = mock( Logger.class ); + when( logger.isDebugEnabled() ).thenReturn( true ); + doNothing().when( logger ).debug( anyString() ); + + AbstractSurefireMojo mojo = spy( this.mojo ); + + when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) ); + + Map map = new LinkedHashMap<>(); + map.put( "ABC", "123" ); + map.put( "XYZ", "987" ); + invokeMethod( mojo, "showMap", map, "prefix" ); + + ArgumentCaptor argument = ArgumentCaptor.forClass( String.class ); + verify( logger, times( 2 ) ).debug( argument.capture() ); + assertThat( argument.getAllValues() ) + .containsExactly( "Setting prefix [ABC]=[123]", "Setting prefix [XYZ]=[987]" ); + } + @Test public void shouldRetainInPluginArtifacts() throws Exception { @@ -209,6 +282,7 @@ public void shouldGenerateTestClasspath() throws Exception } @Test + @SuppressWarnings( "checkstyle:linelength" ) public void shouldHaveStartupConfigForNonModularClasspath() throws Exception { @@ -218,6 +292,10 @@ public void shouldHaveStartupConfigForNonModularClasspath() createFromVersion( "1" ), "runtime", "jar", "", handler ); common.setFile( mockFile( "maven-surefire-common.jar" ) ); + Artifact ext = new DefaultArtifact( "org.apache.maven.surefire", "surefire-extensions-api", + createFromVersion( "1" ), "runtime", "jar", "", handler ); + ext.setFile( mockFile( "surefire-extensions-api.jar" ) ); + Artifact api = new DefaultArtifact( "org.apache.maven.surefire", "surefire-api", createFromVersion( "1" ), "runtime", "jar", "", handler ); api.setFile( mockFile( "surefire-api.jar" ) ); @@ -228,6 +306,7 @@ public void shouldHaveStartupConfigForNonModularClasspath() Map providerArtifactsMap = new HashMap<>(); providerArtifactsMap.put( "org.apache.maven.surefire:maven-surefire-common", common ); + providerArtifactsMap.put( "org.apache.maven.surefire:surefire-extensions-api", ext ); providerArtifactsMap.put( "org.apache.maven.surefire:surefire-api", api ); providerArtifactsMap.put( "org.apache.maven.surefire:surefire-logger-api", loggerApi ); @@ -247,7 +326,7 @@ public void shouldHaveStartupConfigForNonModularClasspath() File classesDir = mockFile( "classes" ); File testClassesDir = mockFile( "test-classes" ); TestClassPath testClasspath = - new TestClassPath( asList( junit, hamcrest ), classesDir, testClassesDir, null, null ); + new TestClassPath( asList( junit, hamcrest ), classesDir, testClassesDir, null ); doReturn( testClasspath ).when( mojo, "generateTestClasspath" ); doReturn( 1 ).when( mojo, "getEffectiveForkCount" ); @@ -267,11 +346,10 @@ public void shouldHaveStartupConfigForNonModularClasspath() when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) ); StartupConfiguration conf = invokeMethod( mojo, "newStartupConfigWithClasspath", - classLoaderConfiguration, providerArtifacts, "org.asf.Provider" ); + classLoaderConfiguration, providerArtifacts, "org.asf.Provider", testClasspath ); verify( mojo, times( 1 ) ).effectiveIsEnableAssertions(); verify( mojo, times( 1 ) ).isChildDelegation(); - verifyPrivate( mojo, times( 1 ) ).invoke( "generateTestClasspath" ); verify( mojo, times( 1 ) ).getEffectiveForkCount(); ArgumentCaptor argument = ArgumentCaptor.forClass( String.class ); verify( logger, times( 6 ) ).debug( argument.capture() ); @@ -280,8 +358,8 @@ public void shouldHaveStartupConfigForNonModularClasspath() "provider classpath: surefire-provider.jar", "test(compact) classpath: test-classes classes junit.jar hamcrest.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" + "in-process classpath: surefire-provider.jar maven-surefire-common.jar surefire-extensions-api.jar surefire-api.jar surefire-logger-api.jar", + "in-process(compact) classpath: surefire-provider.jar maven-surefire-common.jar surefire-extensions-api.jar surefire-api.jar surefire-logger-api.jar" ); assertThat( conf.getClassLoaderConfiguration() ) @@ -311,6 +389,70 @@ public void shouldHaveStartupConfigForNonModularClasspath() .isEqualTo( "org.asf.Provider" ); } + @Test + public void providerClasspathCachingIsNotSharedAcrossMojoInstances() throws Exception + { + ProviderInfo providerInfo = mock( ProviderInfo.class ); + when( providerInfo.getProviderName() ).thenReturn( "test-provider" ); + Artifact provider = new DefaultArtifact( "com.example", "provider", createFromVersion( "1" ), "runtime", + "jar", "", handler ); + provider.setFile( mockFile( "original-test-provider.jar" ) ); + HashSet providerClasspath = new HashSet<>( asList( provider ) ); + when( providerInfo.getProviderClasspath() ).thenReturn( providerClasspath ); + + StartupConfiguration startupConfiguration = startupConfigurationForProvider( providerInfo ); + assertThat( startupConfiguration.getClasspathConfiguration().getProviderClasspath().getClassPath() ) + .containsExactly( "original-test-provider.jar" ); + + provider.setFile( mockFile( "modified-test-provider.jar" ) ); + startupConfiguration = startupConfigurationForProvider( providerInfo ); + assertThat( startupConfiguration.getClasspathConfiguration().getProviderClasspath().getClassPath() ) + .containsExactly( "modified-test-provider.jar" ); + } + + private StartupConfiguration startupConfigurationForProvider( ProviderInfo providerInfo ) throws Exception + { + AbstractSurefireMojo mojo = spy( new Mojo() ); + + Logger logger = mock( Logger.class ); + when( logger.isDebugEnabled() ).thenReturn( true ); + doNothing().when( logger ).debug( anyString() ); + when( mojo.getConsoleLogger() ).thenReturn( new PluginConsoleLogger( logger ) ); + + File classesDir = mockFile( "classes" ); + File testClassesDir = mockFile( "test-classes" ); + TestClassPath testClassPath = + new TestClassPath( new ArrayList(), classesDir, testClassesDir, new String[0] ); + + Artifact common = new DefaultArtifact( "org.apache.maven.surefire", "maven-surefire-common", + createFromVersion( "1" ), "runtime", "jar", "", handler ); + common.setFile( mockFile( "maven-surefire-common.jar" ) ); + + Artifact ext = new DefaultArtifact( "org.apache.maven.surefire", "surefire-extensions-api", + createFromVersion( "1" ), "runtime", "jar", "", handler ); + ext.setFile( mockFile( "surefire-extensions-api.jar" ) ); + + Artifact api = new DefaultArtifact( "org.apache.maven.surefire", "surefire-api", + createFromVersion( "1" ), "runtime", "jar", "", handler ); + api.setFile( mockFile( "surefire-api.jar" ) ); + + Artifact loggerApi = new DefaultArtifact( "org.apache.maven.surefire", "surefire-logger-api", + createFromVersion( "1" ), "runtime", "jar", "", handler ); + loggerApi.setFile( mockFile( "surefire-logger-api.jar" ) ); + + Map providerArtifactsMap = new HashMap<>(); + providerArtifactsMap.put( "org.apache.maven.surefire:maven-surefire-common", common ); + providerArtifactsMap.put( "org.apache.maven.surefire:surefire-extensions-api", ext ); + providerArtifactsMap.put( "org.apache.maven.surefire:surefire-api", api ); + providerArtifactsMap.put( "org.apache.maven.surefire:surefire-logger-api", loggerApi ); + + when( mojo.getPluginArtifactMap() ).thenReturn( providerArtifactsMap ); + + doReturn( 1 ).when( mojo, "getEffectiveForkCount" ); + + return invokeMethod( mojo, "createStartupConfiguration", providerInfo, false, null, null, null, testClassPath ); + } + @Test public void shouldExistTmpDirectory() throws IOException { @@ -360,9 +502,1240 @@ public void shouldExistTmpDirectory() throws IOException .isDirectory(); } + @Test + public void shouldSmartlyResolveJUnit5ProviderWithJUnit4() throws Exception + { + MavenProject mavenProject = new MavenProject(); + mavenProject.setArtifact( new DefaultArtifact( "dummy", "pom", createFromVersion( "1.0.0" ), + null, "jar", null, mock( ArtifactHandler.class ) ) ); + mojo.setProject( mavenProject ); + + final VersionRange surefireVersion = createFromVersion( "1" ); + + Artifact junitPlatformArtifact = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + Artifact testClasspathJUnit = new DefaultArtifact( "junit", "junit", createFromVersion( "4.12" ), null, "jar", + null, mock( ArtifactHandler.class ) ); + + Iterable testArtifacts = singleton( testClasspathJUnit ); + + File classesDirectory = new File( "target/classes" ); + + File testClassesDirectory = new File( "target/test-classes" ); + + TestClassPath testClasspathWrapper = + new TestClassPath( testArtifacts, classesDirectory, testClassesDirectory, null ); + + Artifact forkedBooter = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-booter", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + mojo.setPluginArtifactMap( singletonMap( "org.apache.maven.surefire:surefire-booter", forkedBooter ) ); + mojo.setRemoteRepositories( Collections.emptyList() ); + mojo.setProjectRemoteRepositories( Collections.emptyList() ); + RepositorySystem repositorySystem = mock( RepositorySystem.class ); + final Artifact surefireProvider = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ).thenAnswer( new Answer() + { + @Override + public Artifact answer( InvocationOnMock invocation ) + { + Dependency provider = (Dependency) invocation.getArguments()[0]; + assertThat( provider.getGroupId() ).isEqualTo( "org.apache.maven.surefire" ); + assertThat( provider.getArtifactId() ).isEqualTo( "surefire-junit-platform" ); + return surefireProvider; + } + } ); + final ArtifactResolutionResult surefireProviderResolutionResult = mock( ArtifactResolutionResult.class ); + final ArtifactResolutionResult junit4ResolutionResult = mock( ArtifactResolutionResult.class ); + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public ArtifactResolutionResult answer( InvocationOnMock invocation ) + { + ArtifactResolutionRequest req = (ArtifactResolutionRequest) invocation.getArguments()[0]; + Artifact artifact = req.getArtifact(); + if ( artifact == surefireProvider ) + { + return surefireProviderResolutionResult; + } + else if ( artifact.getGroupId().equals( "junit" ) + && artifact.getArtifactId().equals( "junit" ) + && artifact.getVersion().equals( "4.12" ) ) + { + return junit4ResolutionResult; + } + else + { + fail(); + return null; + } + } + } ); + + DependencyResolver dependencyResolver = mock( DependencyResolver.class ); + when( dependencyResolver.resolveDependencies( any( ProjectBuildingRequest.class ), + ArgumentMatchers.anyCollection(), isNull( Collection.class ), + any( TransformableFilter.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public Object answer( InvocationOnMock invocation ) + { + Collection deps = (Collection) invocation.getArguments()[1]; + assertThat( deps ).isEmpty(); + return emptySet(); + } + } ); + + Artifact java5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact apiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact engine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact commons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact opentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Set providerArtifacts = new HashSet<>(); + providerArtifacts.add( surefireProvider ); + providerArtifacts.add( java5 ); + providerArtifacts.add( launcher ); + providerArtifacts.add( apiguardian ); + providerArtifacts.add( engine ); + providerArtifacts.add( commons ); + providerArtifacts.add( opentest4j ); + + when( surefireProviderResolutionResult.getArtifacts() ) + .thenReturn( providerArtifacts ); + + Artifact junit = new DefaultArtifact( "junit", "junit", + createFromVersion( "4.12" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact hamcrest = new DefaultArtifact( "org.hamcrest", "hamcrest-core", + createFromVersion( "1.3" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Set junitArtifacts = new HashSet<>(); + junitArtifacts.add( junit ); + junitArtifacts.add( hamcrest ); + when( junit4ResolutionResult.getArtifacts() ) + .thenReturn( junitArtifacts ); + + mojo.setRepositorySystem( repositorySystem ); + mojo.setLogger( mock( Logger.class ) ); + mojo.setDependencyResolver( dependencyResolver ); + + invokeMethod( mojo, "setupStuff" ); + + MavenSession session = mock( MavenSession.class ); + mojo.setSession( session ); + when( session.getProjectBuildingRequest() ) + .thenReturn( mock( ProjectBuildingRequest.class ) ); + + PluginDescriptor pluginDescriptor = mock( PluginDescriptor.class ); + mojo.setPluginDescriptor( pluginDescriptor ); + Plugin p = mock( Plugin.class ); + when( pluginDescriptor.getPlugin() ) + .thenReturn( p ); + when( p.getDependencies() ) + .thenReturn( Collections.emptyList() ); + + JUnitPlatformProviderInfo prov = + mojo.createJUnitPlatformProviderInfo( junitPlatformArtifact, testClasspathWrapper ); + + Artifact expectedProvider = new DefaultArtifact( "org.apache.maven.surefire", "surefire-junit-platform", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact expectedCommonJava5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact expectedLauncher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact expectedApiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact expectedJUnit5Engine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact expectedOpentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact expectedPlatformCommons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + assertThat( prov.getProviderClasspath() ) + .hasSize( 7 ) + .containsOnly( expectedProvider, expectedCommonJava5, expectedLauncher, expectedApiguardian, + expectedJUnit5Engine, expectedOpentest4j, expectedPlatformCommons ); + + assertThat( testClasspathWrapper.getTestDependencies() ) + .hasSize( 1 ) + .includes( entry( "junit:junit", testClasspathJUnit ) ); + } + + @Test + public void shouldSmartlyResolveJUnit5ProviderWithVintage() throws Exception + { + MavenProject mavenProject = new MavenProject(); + mavenProject.setArtifact( new DefaultArtifact( "dummy", "pom", createFromVersion( "1.0.0" ), + null, "jar", null, mock( ArtifactHandler.class ) ) ); + mojo.setProject( mavenProject ); + + final VersionRange surefireVersion = createFromVersion( "1" ); + + Artifact junitPlatformArtifact = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathSomeTestArtifact = new DefaultArtifact( "third.party", "artifact", + createFromVersion( "1.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathVintage = new DefaultArtifact( "org.junit.vintage", "junit-vintage-engine", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathApiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathPlatformEng = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Artifact testClasspathJUnit4 = new DefaultArtifact( "junit", "junit", + createFromVersion( "4.12" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Artifact testClasspathHamcrest = new DefaultArtifact( "org.hamcrest", "hamcrest-core", + createFromVersion( "1.3" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathOpentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathCommons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Iterable testArtifacts = asList( testClasspathSomeTestArtifact, testClasspathVintage, + testClasspathApiguardian, testClasspathPlatformEng, testClasspathJUnit4, testClasspathHamcrest, + testClasspathOpentest4j, testClasspathCommons ); + + File classesDirectory = new File( "target/classes" ); + + File testClassesDirectory = new File( "target/test-classes" ); + + TestClassPath testClasspathWrapper = + new TestClassPath( testArtifacts, classesDirectory, testClassesDirectory, null ); + + Artifact forkedBooter = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-booter", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + mojo.setPluginArtifactMap( singletonMap( "org.apache.maven.surefire:surefire-booter", forkedBooter ) ); + mojo.setRemoteRepositories( Collections.emptyList() ); + mojo.setProjectRemoteRepositories( Collections.emptyList() ); + RepositorySystem repositorySystem = mock( RepositorySystem.class ); + final Artifact surefireProvider = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ).thenAnswer( new Answer() + { + @Override + public Artifact answer( InvocationOnMock invocation ) + { + Dependency provider = (Dependency) invocation.getArguments()[0]; + assertThat( provider.getGroupId() ).isEqualTo( "org.apache.maven.surefire" ); + assertThat( provider.getArtifactId() ).isEqualTo( "surefire-junit-platform" ); + return surefireProvider; + } + } ); + final ArtifactResolutionResult surefireProviderResolutionResult = mock( ArtifactResolutionResult.class ); + final ArtifactResolutionResult junit4ResolutionResult = mock( ArtifactResolutionResult.class ); + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public ArtifactResolutionResult answer( InvocationOnMock invocation ) + { + ArtifactResolutionRequest req = (ArtifactResolutionRequest) invocation.getArguments()[0]; + Artifact resolvable = req.getArtifact(); + if ( resolvable == surefireProvider ) + { + return surefireProviderResolutionResult; + } + else if ( "org.junit.platform".equals( resolvable.getGroupId() ) + && "junit-platform-engine".equals( resolvable.getArtifactId() ) + && "1.4.0".equals( resolvable.getVersion() ) ) + { + return createVintageEngineResolutionResult(); + } + else if ( "org.junit.platform".equals( resolvable.getGroupId() ) + && "junit-platform-launcher".equals( resolvable.getArtifactId() ) + && "1.4.0".equals( resolvable.getVersion() ) ) + { + return createExpectedJUnitPlatformLauncherResolutionResult(); + } + else + { + fail(); + return null; + } + } + } ); + + Artifact java5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact apiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact engine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact commons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact opentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Set providerArtifacts = new HashSet<>(); + providerArtifacts.add( surefireProvider ); + providerArtifacts.add( java5 ); + providerArtifacts.add( launcher ); + providerArtifacts.add( apiguardian ); + providerArtifacts.add( engine ); + providerArtifacts.add( commons ); + providerArtifacts.add( opentest4j ); + + when( surefireProviderResolutionResult.getArtifacts() ) + .thenReturn( providerArtifacts ); + + Artifact junit = new DefaultArtifact( "junit", "junit", + createFromVersion( "4.12" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact hamcrest = new DefaultArtifact( "org.hamcrest", "hamcrest-core", + createFromVersion( "1.3" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Set junitArtifacts = new HashSet<>(); + junitArtifacts.add( junit ); + junitArtifacts.add( hamcrest ); + when( junit4ResolutionResult.getArtifacts() ) + .thenReturn( junitArtifacts ); + + mojo.setRepositorySystem( repositorySystem ); + mojo.setLogger( mock( Logger.class ) ); + + invokeMethod( mojo, "setupStuff" ); + JUnitPlatformProviderInfo prov = + mojo.createJUnitPlatformProviderInfo( junitPlatformArtifact, testClasspathWrapper ); + + Artifact expectedProvider = new DefaultArtifact( "org.apache.maven.surefire", "surefire-junit-platform", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact expectedCommonJava5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact expectedLauncher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + assertThat( prov.getProviderClasspath() ) + .hasSize( 3 ) + .containsOnly( expectedProvider, expectedCommonJava5, expectedLauncher ); + + assertThat( testClasspathWrapper.getTestDependencies() ) + .hasSize( 8 ) + .includes( entry( "third.party:artifact", testClasspathSomeTestArtifact ), + entry( "org.junit.vintage:junit-vintage-engine", testClasspathVintage ), + entry( "org.apiguardian:apiguardian-api", testClasspathApiguardian ), + entry( "org.junit.platform:junit-platform-engine", testClasspathPlatformEng ), + entry( "junit:junit", testClasspathJUnit4 ), + entry( "org.hamcrest:hamcrest-core", testClasspathHamcrest ), + entry( "org.opentest4j:opentest4j", testClasspathOpentest4j ), + entry( "org.junit.platform:junit-platform-commons", testClasspathCommons ) ); + } + + @Test + public void shouldSmartlyResolveJUnit5ProviderWithJUnit5Commons() throws Exception + { + MavenProject mavenProject = new MavenProject(); + mavenProject.setArtifact( new DefaultArtifact( "dummy", "pom", createFromVersion( "1.0.0" ), + null, "jar", null, mock( ArtifactHandler.class ) ) ); + mojo.setProject( mavenProject ); + + final VersionRange surefireVersion = createFromVersion( "1" ); + + Artifact junitPlatformArtifact = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathSomeTestArtifact = new DefaultArtifact( "third.party", "artifact", + createFromVersion( "1.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathCommons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathApiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Iterable testArtifacts = + asList( testClasspathSomeTestArtifact, testClasspathApiguardian, testClasspathCommons ); + + File classesDirectory = new File( "target/classes" ); + + File testClassesDirectory = new File( "target/test-classes" ); + + TestClassPath testClasspathWrapper = + new TestClassPath( testArtifacts, classesDirectory, testClassesDirectory, null ); + + Artifact forkedBooter = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-booter", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + mojo.setPluginArtifactMap( singletonMap( "org.apache.maven.surefire:surefire-booter", forkedBooter ) ); + mojo.setRemoteRepositories( Collections.emptyList() ); + mojo.setProjectRemoteRepositories( Collections.emptyList() ); + RepositorySystem repositorySystem = mock( RepositorySystem.class ); + final Artifact surefireProvider = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ).thenAnswer( new Answer() + { + @Override + public Artifact answer( InvocationOnMock invocation ) + { + Dependency provider = (Dependency) invocation.getArguments()[0]; + assertThat( provider.getGroupId() ).isEqualTo( "org.apache.maven.surefire" ); + assertThat( provider.getArtifactId() ).isEqualTo( "surefire-junit-platform" ); + return surefireProvider; + } + } ); + + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public ArtifactResolutionResult answer( InvocationOnMock invocation ) + { + ArtifactResolutionRequest req = (ArtifactResolutionRequest) invocation.getArguments()[0]; + Artifact resolvable = req.getArtifact(); + if ( resolvable == surefireProvider ) + { + return createSurefireProviderResolutionResult( surefireVersion ); + } + else + { + fail(); + return null; + } + } + } ); + + DependencyResolver dependencyResolver = mock( DependencyResolver.class ); + when( dependencyResolver.resolveDependencies( any( ProjectBuildingRequest.class ), + ArgumentMatchers.anyCollection(), isNull( Collection.class ), + any( TransformableFilter.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public Object answer( InvocationOnMock invocation ) + { + Collection deps = (Collection) invocation.getArguments()[1]; + assertThat( deps ).isEmpty(); + return emptySet(); + } + } ); + + mojo.setRepositorySystem( repositorySystem ); + mojo.setLogger( mock( Logger.class ) ); + mojo.setDependencyResolver( dependencyResolver ); + + invokeMethod( mojo, "setupStuff" ); + + MavenSession session = mock( MavenSession.class ); + mojo.setSession( session ); + when( session.getProjectBuildingRequest() ) + .thenReturn( mock( ProjectBuildingRequest.class ) ); + + PluginDescriptor pluginDescriptor = mock( PluginDescriptor.class ); + mojo.setPluginDescriptor( pluginDescriptor ); + Plugin p = mock( Plugin.class ); + when( pluginDescriptor.getPlugin() ) + .thenReturn( p ); + when( p.getDependencies() ) + .thenReturn( Collections.emptyList() ); + + JUnitPlatformProviderInfo prov = + mojo.createJUnitPlatformProviderInfo( junitPlatformArtifact, testClasspathWrapper ); + Set resolvedProviderArtifacts = prov.getProviderClasspath(); + + Artifact provider = new DefaultArtifact( "org.apache.maven.surefire", "surefire-junit-platform", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact java5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact engine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact opentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + assertThat( resolvedProviderArtifacts ) + .hasSize( 5 ) + .containsOnly( provider, java5, launcher, engine, opentest4j ); + + assertThat( testClasspathWrapper.getTestDependencies() ) + .hasSize( 3 ) + .includes( entry( "third.party:artifact", testClasspathSomeTestArtifact ), + entry( "org.junit.platform:junit-platform-commons", testClasspathCommons ), + entry( "org.apiguardian:apiguardian-api", testClasspathApiguardian ) ); + } + + @Test + public void shouldSmartlyResolveJUnit5ProviderWithJUnit5Engine() throws Exception + { + MavenProject mavenProject = new MavenProject(); + mavenProject.setArtifact( new DefaultArtifact( "dummy", "pom", createFromVersion( "1.0.0" ), + null, "jar", null, mock( ArtifactHandler.class ) ) ); + mojo.setProject( mavenProject ); + + final VersionRange surefireVersion = createFromVersion( "1" ); + + Artifact junitPlatformArtifact = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathSomeTestArtifact = new DefaultArtifact( "third.party", "artifact", + createFromVersion( "1.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathJUnit5 = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathApiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathCommons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathOpentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Iterable testArtifacts = asList( testClasspathSomeTestArtifact, testClasspathJUnit5, + testClasspathApiguardian, testClasspathCommons, testClasspathOpentest4j ); + + File classesDirectory = new File( "target/classes" ); + + File testClassesDirectory = new File( "target/test-classes" ); + + TestClassPath testClasspathWrapper = + new TestClassPath( testArtifacts, classesDirectory, testClassesDirectory, null ); + + Artifact forkedBooter = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-booter", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + mojo.setPluginArtifactMap( singletonMap( "org.apache.maven.surefire:surefire-booter", forkedBooter ) ); + mojo.setRemoteRepositories( Collections.emptyList() ); + mojo.setProjectRemoteRepositories( Collections.emptyList() ); + RepositorySystem repositorySystem = mock( RepositorySystem.class ); + final Artifact surefireProvider = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ).thenAnswer( new Answer() + { + @Override + public Artifact answer( InvocationOnMock invocation ) + { + Dependency provider = (Dependency) invocation.getArguments()[0]; + assertThat( provider.getGroupId() ).isEqualTo( "org.apache.maven.surefire" ); + assertThat( provider.getArtifactId() ).isEqualTo( "surefire-junit-platform" ); + return surefireProvider; + } + } ); + + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public ArtifactResolutionResult answer( InvocationOnMock invocation ) + { + ArtifactResolutionRequest req = (ArtifactResolutionRequest) invocation.getArguments()[0]; + Artifact resolvable = req.getArtifact(); + if ( resolvable == surefireProvider ) + { + return createSurefireProviderResolutionResult( surefireVersion ); + } + else if ( resolvable.equals( testClasspathJUnit5 ) ) + { + return createResolutionResult( testClasspathJUnit5, testClasspathApiguardian, + testClasspathCommons, testClasspathOpentest4j ); + } + else if ( "org.junit.platform".equals( resolvable.getGroupId() ) + && "junit-platform-launcher".equals( resolvable.getArtifactId() ) + && "1.4.0".equals( resolvable.getVersion() ) ) + { + return createExpectedJUnitPlatformLauncherResolutionResult(); + } + else + { + fail(); + return null; + } + } + } ); + + mojo.setRepositorySystem( repositorySystem ); + mojo.setLogger( mock( Logger.class ) ); + + invokeMethod( mojo, "setupStuff" ); + JUnitPlatformProviderInfo prov = + mojo.createJUnitPlatformProviderInfo( junitPlatformArtifact, testClasspathWrapper ); + Set resolvedProviderArtifacts = prov.getProviderClasspath(); + + Artifact java5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + assertThat( resolvedProviderArtifacts ) + .hasSize( 3 ) + .containsOnly( surefireProvider, java5, launcher ); + + assertThat( testClasspathWrapper.getTestDependencies() ) + .hasSize( 5 ) + .includes( entry( "third.party:artifact", testClasspathSomeTestArtifact ), + entry( "org.junit.platform:junit-platform-engine", testClasspathJUnit5 ), + entry( "org.apiguardian:apiguardian-api", testClasspathApiguardian ), + entry( "org.junit.platform:junit-platform-commons", testClasspathCommons ), + entry( "org.opentest4j:opentest4j", testClasspathOpentest4j ) ); + } + + @Test + public void shouldSmartlyResolveJUnit5ProviderWithJupiterApi() throws Exception + { + MavenProject mavenProject = new MavenProject(); + mavenProject.setArtifact( new DefaultArtifact( "dummy", "pom", createFromVersion( "1.0.0" ), + null, "jar", null, mock( ArtifactHandler.class ) ) ); + mojo.setProject( mavenProject ); + + final VersionRange surefireVersion = createFromVersion( "1" ); + + Artifact junitPlatformArtifact = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathSomeTestArtifact = new DefaultArtifact( "third.party", "artifact", + createFromVersion( "1.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathJupiterApi = new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-api", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathApiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathCommons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathOpentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Iterable testArtifacts = asList( testClasspathSomeTestArtifact, testClasspathJupiterApi, + testClasspathApiguardian, testClasspathCommons, testClasspathOpentest4j ); + + File classesDirectory = new File( "target/classes" ); + + File testClassesDirectory = new File( "target/test-classes" ); + + TestClassPath testClasspathWrapper = + new TestClassPath( testArtifacts, classesDirectory, testClassesDirectory, null ); + + Artifact forkedBooter = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-booter", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + mojo.setPluginArtifactMap( singletonMap( "org.apache.maven.surefire:surefire-booter", forkedBooter ) ); + mojo.setRemoteRepositories( Collections.emptyList() ); + mojo.setProjectRemoteRepositories( Collections.emptyList() ); + RepositorySystem repositorySystem = mock( RepositorySystem.class ); + final Artifact surefireProvider = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ).thenAnswer( new Answer() + { + @Override + public Artifact answer( InvocationOnMock invocation ) + { + Dependency provider = (Dependency) invocation.getArguments()[0]; + assertThat( provider.getGroupId() ).isEqualTo( "org.apache.maven.surefire" ); + assertThat( provider.getArtifactId() ).isEqualTo( "surefire-junit-platform" ); + return surefireProvider; + } + } ); + + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public ArtifactResolutionResult answer( InvocationOnMock invocation ) + { + ArtifactResolutionRequest req = (ArtifactResolutionRequest) invocation.getArguments()[0]; + Artifact resolvable = req.getArtifact(); + if ( resolvable == surefireProvider ) + { + return createSurefireProviderResolutionResult( surefireVersion ); + } + else if ( resolvable.equals( testClasspathJupiterApi ) ) + { + return createResolutionResult( testClasspathJupiterApi, testClasspathApiguardian, + testClasspathCommons, testClasspathOpentest4j ); + } + else if ( "org.junit.platform".equals( resolvable.getGroupId() ) + && "junit-platform-launcher".equals( resolvable.getArtifactId() ) + && "1.4.0".equals( resolvable.getVersion() ) ) + { + return createExpectedJUnitPlatformLauncherResolutionResult(); + } + else if ( "org.junit.jupiter".equals( resolvable.getGroupId() ) + && "junit-jupiter-engine".equals( resolvable.getArtifactId() ) + && "5.4.0".equals( resolvable.getVersion() ) ) + { + return createJupiterEngineResolutionResult(); + } + else + { + fail(); + return null; + } + } + } ); + + DependencyResolver dependencyResolver = mock( DependencyResolver.class ); + when( dependencyResolver.resolveDependencies( any( ProjectBuildingRequest.class ), + ArgumentMatchers.anyCollection(), isNull( Collection.class ), + any( TransformableFilter.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public Object answer( InvocationOnMock invocation ) + { + Collection deps = (Collection) invocation.getArguments()[1]; + assertThat( deps ).isEmpty(); + return emptySet(); + } + } ); + + mojo.setRepositorySystem( repositorySystem ); + mojo.setLogger( mock( Logger.class ) ); + mojo.setDependencyResolver( dependencyResolver ); + + invokeMethod( mojo, "setupStuff" ); + + MavenSession session = mock( MavenSession.class ); + mojo.setSession( session ); + when( session.getProjectBuildingRequest() ) + .thenReturn( mock( ProjectBuildingRequest.class ) ); + + PluginDescriptor pluginDescriptor = mock( PluginDescriptor.class ); + mojo.setPluginDescriptor( pluginDescriptor ); + Plugin p = mock( Plugin.class ); + when( pluginDescriptor.getPlugin() ) + .thenReturn( p ); + when( p.getDependencies() ) + .thenReturn( Collections.emptyList() ); + + JUnitPlatformProviderInfo prov = + mojo.createJUnitPlatformProviderInfo( junitPlatformArtifact, testClasspathWrapper ); + Set resolvedProviderArtifacts = prov.getProviderClasspath(); + + Artifact java5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact jupiterEngine = new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-engine", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact platformEngine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + assertThat( resolvedProviderArtifacts ) + .hasSize( 5 ) + .containsOnly( surefireProvider, java5, launcher, jupiterEngine, platformEngine ); + + assertThat( testClasspathWrapper.getTestDependencies() ) + .hasSize( 5 ) + .includes( entry( "third.party:artifact", testClasspathSomeTestArtifact ), + entry( "org.junit.jupiter:junit-jupiter-api", testClasspathJupiterApi ), + entry( "org.apiguardian:apiguardian-api", testClasspathApiguardian ), + entry( "org.junit.platform:junit-platform-commons", testClasspathCommons ), + entry( "org.opentest4j:opentest4j", testClasspathOpentest4j ) ); + } + + @Test + public void shouldSmartlyResolveJUnit5ProviderWithJupiterEngine() throws Exception + { + MavenProject mavenProject = new MavenProject(); + mavenProject.setArtifact( new DefaultArtifact( "dummy", "pom", createFromVersion( "1.0.0" ), + null, "jar", null, mock( ArtifactHandler.class ) ) ); + mojo.setProject( mavenProject ); + + final VersionRange surefireVersion = createFromVersion( "1" ); + + Artifact junitPlatformArtifact = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathSomeTestArtifact = new DefaultArtifact( "third.party", "artifact", + createFromVersion( "1.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathJupiterEngine = new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-engine", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathPlatformEngine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathJupiterApi = new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-api", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathApiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathCommons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathOpentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Iterable testArtifacts = asList( testClasspathSomeTestArtifact, testClasspathJupiterEngine, + testClasspathPlatformEngine, testClasspathJupiterApi, testClasspathApiguardian, testClasspathCommons, + testClasspathOpentest4j ); + + File classesDirectory = new File( "target/classes" ); + + File testClassesDirectory = new File( "target/test-classes" ); + + TestClassPath testClasspathWrapper = + new TestClassPath( testArtifacts, classesDirectory, testClassesDirectory, null ); + + Artifact forkedBooter = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-booter", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + mojo.setPluginArtifactMap( singletonMap( "org.apache.maven.surefire:surefire-booter", forkedBooter ) ); + mojo.setRemoteRepositories( Collections.emptyList() ); + mojo.setProjectRemoteRepositories( Collections.emptyList() ); + RepositorySystem repositorySystem = mock( RepositorySystem.class ); + final Artifact surefireProvider = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ).thenAnswer( new Answer() + { + @Override + public Artifact answer( InvocationOnMock invocation ) + { + Dependency provider = (Dependency) invocation.getArguments()[0]; + assertThat( provider.getGroupId() ).isEqualTo( "org.apache.maven.surefire" ); + assertThat( provider.getArtifactId() ).isEqualTo( "surefire-junit-platform" ); + return surefireProvider; + } + } ); + + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public ArtifactResolutionResult answer( InvocationOnMock invocation ) + { + ArtifactResolutionRequest req = (ArtifactResolutionRequest) invocation.getArguments()[0]; + Artifact resolvable = req.getArtifact(); + if ( resolvable == surefireProvider ) + { + return createSurefireProviderResolutionResult( surefireVersion ); + } + else if ( resolvable.equals( testClasspathJupiterApi ) ) + { + return createResolutionResult( testClasspathJupiterApi, testClasspathApiguardian, + testClasspathCommons, testClasspathOpentest4j ); + } + else if ( "org.junit.platform".equals( resolvable.getGroupId() ) + && "junit-platform-launcher".equals( resolvable.getArtifactId() ) + && "1.4.0".equals( resolvable.getVersion() ) ) + { + return createExpectedJUnitPlatformLauncherResolutionResult(); + } + else if ( "org.junit.platform".equals( resolvable.getGroupId() ) + && "junit-platform-engine".equals( resolvable.getArtifactId() ) + && "1.4.0".equals( resolvable.getVersion() ) ) + { + return createVintageEngineResolutionResult(); + } + else + { + fail(); + return null; + } + } + } ); + + mojo.setRepositorySystem( repositorySystem ); + mojo.setLogger( mock( Logger.class ) ); + + invokeMethod( mojo, "setupStuff" ); + JUnitPlatformProviderInfo prov = + mojo.createJUnitPlatformProviderInfo( junitPlatformArtifact, testClasspathWrapper ); + Set resolvedProviderArtifacts = prov.getProviderClasspath(); + + Artifact java5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + assertThat( resolvedProviderArtifacts ) + .hasSize( 3 ) + .containsOnly( surefireProvider, java5, launcher ); + + assertThat( testClasspathWrapper.getTestDependencies() ) + .hasSize( 7 ) + .includes( entry( "third.party:artifact", testClasspathSomeTestArtifact ), + entry( "org.junit.jupiter:junit-jupiter-engine", testClasspathJupiterEngine ), + entry( "org.junit.platform:junit-platform-engine", testClasspathPlatformEngine ), + entry( "org.junit.jupiter:junit-jupiter-api", testClasspathJupiterApi ), + entry( "org.apiguardian:apiguardian-api", testClasspathApiguardian ), + entry( "org.junit.platform:junit-platform-commons", testClasspathCommons ), + entry( "org.opentest4j:opentest4j", testClasspathOpentest4j ) ); + } + + @Test + public void shouldSmartlyResolveJUnit5ProviderWithJupiterEngineInPluginDependencies() throws Exception + { + + final VersionRange surefireVersion = createFromVersion( "1" ); + + final Artifact plugin = new DefaultArtifact( "org.apache.maven.surefire", "maven-surefire-plugin", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact forkedBooter = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-booter", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact pluginDepJupiterEngine = new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-engine", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact pluginDepPlatformEngine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact pluginDepJupiterApi = new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-api", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact pluginDepApiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact pluginDepCommons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact pluginDepOpentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Map pluginDependencies = new HashMap<>(); + pluginDependencies.put( "org.apache.maven.surefire:maven-surefire-plugin", plugin ); + pluginDependencies.put( "org.apache.maven.surefire:surefire-booter", forkedBooter ); + pluginDependencies.put( "org.junit.jupiter:junit-jupiter-engine", pluginDepJupiterEngine ); + pluginDependencies.put( "org.junit.platform:junit-platform-engine", pluginDepPlatformEngine ); + pluginDependencies.put( "org.junit.jupiter:junit-jupiter-api", pluginDepJupiterApi ); + pluginDependencies.put( "org.apiguardian:apiguardian-api", pluginDepApiguardian ); + pluginDependencies.put( "org.junit.platform:junit-platform-commons", pluginDepCommons ); + pluginDependencies.put( "org.opentest4j:opentest4j", pluginDepOpentest4j ); + mojo.setPluginArtifactMap( pluginDependencies ); + + MavenProject mavenProject = new MavenProject(); + mavenProject.setArtifact( new DefaultArtifact( "dummy", "pom", createFromVersion( "1.0.0" ), + null, "jar", null, mock( ArtifactHandler.class ) ) ); + mojo.setProject( mavenProject ); + + Artifact junitPlatformArtifact = new DefaultArtifact( "g", "a", + createFromVersion( "0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathSomeTestArtifact = new DefaultArtifact( "third.party", "artifact", + createFromVersion( "1.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathJupiterApi = new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-api", + createFromVersion( "5.3.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathApiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathCommons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + final Artifact testClasspathOpentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Iterable testArtifacts = asList( testClasspathSomeTestArtifact, testClasspathJupiterApi, + testClasspathApiguardian, testClasspathCommons, testClasspathOpentest4j ); + + File classesDirectory = new File( "target/classes" ); + + File testClassesDirectory = new File( "target/test-classes" ); + + TestClassPath testClasspathWrapper = + new TestClassPath( testArtifacts, classesDirectory, testClassesDirectory, null ); + + mojo.setRemoteRepositories( Collections.emptyList() ); + mojo.setProjectRemoteRepositories( Collections.emptyList() ); + RepositorySystem repositorySystem = mock( RepositorySystem.class ); + final Artifact surefireProvider = new DefaultArtifact( "org.apache.maven.surefire", + "surefire-junit-platform", surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ).thenAnswer( new Answer() + { + @Override + public Artifact answer( InvocationOnMock invocation ) + { + Dependency provider = (Dependency) invocation.getArguments()[0]; + assertThat( provider.getGroupId() ).isEqualTo( "org.apache.maven.surefire" ); + assertThat( provider.getArtifactId() ).isEqualTo( "surefire-junit-platform" ); + return surefireProvider; + } + } ); + + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public ArtifactResolutionResult answer( InvocationOnMock invocation ) + { + ArtifactResolutionRequest req = (ArtifactResolutionRequest) invocation.getArguments()[0]; + Artifact resolvable = req.getArtifact(); + if ( resolvable == surefireProvider ) + { + return createSurefireProviderResolutionResult( surefireVersion ); + } + else if ( "org.junit.platform".equals( resolvable.getGroupId() ) + && "junit-platform-launcher".equals( resolvable.getArtifactId() ) + && "1.4.0".equals( resolvable.getVersion() ) ) + { + return createExpectedJUnitPlatformLauncherResolutionResult(); + } + else if ( "org.apache.maven.surefire".equals( resolvable.getGroupId() ) + && "maven-surefire-plugin".equals( resolvable.getArtifactId() ) + && "1".equals( resolvable.getVersion() ) ) + { + Set pluginItself = new HashSet<>(); + pluginItself.add( plugin ); + pluginItself.add( forkedBooter ); + ArtifactResolutionResult launcherResolutionResult = mock( ArtifactResolutionResult.class ); + when( launcherResolutionResult.getArtifacts() ) + .thenReturn( pluginItself ); + return launcherResolutionResult; + } + else + { + fail(); + return null; + } + } + } ); + + DependencyResolver dependencyResolver = mock( DependencyResolver.class ); + when( dependencyResolver.resolveDependencies( any( ProjectBuildingRequest.class ), + ArgumentMatchers.anyCollection(), isNull( Collection.class ), + any( TransformableFilter.class ) ) ) + .thenAnswer( new Answer() + { + @Override + public Object answer( InvocationOnMock invocation ) + { + Collection deps = (Collection) invocation.getArguments()[1]; + assertThat( deps ).hasSize( 1 ); + Dependency resolvable = (Dependency) deps.iterator().next(); + if ( "org.junit.jupiter".equals( resolvable.getGroupId() ) + && "junit-jupiter-engine".equals( resolvable.getArtifactId() ) + && "5.4.0".equals( resolvable.getVersion() ) ) + { + Set resolvedPluginDeps = new HashSet<>(); + resolvedPluginDeps.add( toArtifactResult( pluginDepJupiterEngine ) ); + resolvedPluginDeps.add( toArtifactResult( pluginDepPlatformEngine ) ); + resolvedPluginDeps.add( toArtifactResult( pluginDepJupiterApi ) ); + resolvedPluginDeps.add( toArtifactResult( pluginDepApiguardian ) ); + resolvedPluginDeps.add( toArtifactResult( pluginDepCommons ) ); + resolvedPluginDeps.add( toArtifactResult( pluginDepOpentest4j ) ); + return resolvedPluginDeps; + } + else + { + fail(); + return null; + } + } + } ); + + mojo.setRepositorySystem( repositorySystem ); + mojo.setLogger( mock( Logger.class ) ); + mojo.setDependencyResolver( dependencyResolver ); + + invokeMethod( mojo, "setupStuff" ); + + JUnitPlatformProviderInfo prov = + mojo.createJUnitPlatformProviderInfo( junitPlatformArtifact, testClasspathWrapper ); + + MavenSession session = mock( MavenSession.class ); + mojo.setSession( session ); + when( session.getProjectBuildingRequest() ) + .thenReturn( mock( ProjectBuildingRequest.class ) ); + + PluginDescriptor pluginDescriptor = mock( PluginDescriptor.class ); + mojo.setPluginDescriptor( pluginDescriptor ); + Plugin p = mock( Plugin.class ); + when( pluginDescriptor.getPlugin() ) + .thenReturn( p ); + List directPluginDependencies = toDependencies( pluginDepJupiterEngine ); + when( p.getDependencies() ) + .thenReturn( directPluginDependencies ); + + Set resolvedProviderArtifacts = prov.getProviderClasspath(); + + Artifact java5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact jupiterEngine = new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-engine", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact platformEngine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + assertThat( resolvedProviderArtifacts ) + .hasSize( 5 ) + .containsOnly( surefireProvider, java5, launcher, jupiterEngine, platformEngine ); + + assertThat( testClasspathWrapper.getTestDependencies() ) + .hasSize( 5 ) + .includes( entry( "third.party:artifact", testClasspathSomeTestArtifact ), + entry( "org.junit.jupiter:junit-jupiter-api", testClasspathJupiterApi ), + entry( "org.apiguardian:apiguardian-api", testClasspathApiguardian ), + entry( "org.junit.platform:junit-platform-commons", testClasspathCommons ), + entry( "org.opentest4j:opentest4j", testClasspathOpentest4j ) ); + } + + private static ArtifactResolutionResult createJUnitPlatformLauncherResolutionResult( + Artifact junit5Engine, Artifact apiguardian, Artifact commons, Artifact opentest4j ) + { + ArtifactResolutionResult launcherResolutionResult = mock( ArtifactResolutionResult.class ); + Set resolvedLauncherArtifacts = new HashSet<>(); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + commons.getVersionRange(), null, "jar", null, mock( ArtifactHandler.class ) ); + resolvedLauncherArtifacts.add( launcher ); + resolvedLauncherArtifacts.add( apiguardian ); + resolvedLauncherArtifacts.add( junit5Engine ); + resolvedLauncherArtifacts.add( commons ); + resolvedLauncherArtifacts.add( opentest4j ); + resolvedLauncherArtifacts.remove( null ); + when( launcherResolutionResult.getArtifacts() ) + .thenReturn( resolvedLauncherArtifacts ); + return launcherResolutionResult; + } + + private static ArtifactResolutionResult createVintageEngineResolutionResult() + { + ArtifactResolutionResult launcherResolutionResult = mock( ArtifactResolutionResult.class ); + Set resolvedLauncherArtifacts = new HashSet<>(); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.junit.vintage", "junit-vintage-engine", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-api", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "junit", "junit", + createFromVersion( "4.12" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.hamcrest", "hamcrest-core", + createFromVersion( "1.3" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + when( launcherResolutionResult.getArtifacts() ) + .thenReturn( resolvedLauncherArtifacts ); + return launcherResolutionResult; + } + + private static ArtifactResolutionResult createJupiterEngineResolutionResult() + { + ArtifactResolutionResult launcherResolutionResult = mock( ArtifactResolutionResult.class ); + Set resolvedLauncherArtifacts = new HashSet<>(); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-engine", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.junit.jupiter", "junit-jupiter-api", + createFromVersion( "5.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + resolvedLauncherArtifacts.add( new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ) ); + when( launcherResolutionResult.getArtifacts() ) + .thenReturn( resolvedLauncherArtifacts ); + return launcherResolutionResult; + } + + private static ArtifactResolutionResult createExpectedJUnitPlatformLauncherResolutionResult() + { + Artifact engine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact commons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.4.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact apiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact opentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + return createJUnitPlatformLauncherResolutionResult( engine, apiguardian, commons, opentest4j ); + } + + private static ArtifactResolutionResult createResolutionResult( Artifact... artifacts ) + { + ArtifactResolutionResult testClasspathCommonsResolutionResult = mock( ArtifactResolutionResult.class ); + Set resolvedCommonsArtifacts = new HashSet<>(); + Collections.addAll( resolvedCommonsArtifacts, artifacts ); + when( testClasspathCommonsResolutionResult.getArtifacts() ) + .thenReturn( resolvedCommonsArtifacts ); + return testClasspathCommonsResolutionResult; + } + + private static ArtifactResolutionResult createSurefireProviderResolutionResult( VersionRange surefireVersion ) + { + ArtifactResolutionResult surefirePlatformResolutionResult = mock( ArtifactResolutionResult.class ); + + Artifact provider = new DefaultArtifact( "org.apache.maven.surefire", "surefire-junit-platform", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact java5 = new DefaultArtifact( "org.apache.maven.surefire", "common-java5", + surefireVersion, null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact launcher = new DefaultArtifact( "org.junit.platform", "junit-platform-launcher", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact apiguardian = new DefaultArtifact( "org.apiguardian", "apiguardian-api", + createFromVersion( "1.0.0" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact engine = new DefaultArtifact( "org.junit.platform", "junit-platform-engine", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact commons = new DefaultArtifact( "org.junit.platform", "junit-platform-commons", + createFromVersion( "1.3.2" ), null, "jar", null, mock( ArtifactHandler.class ) ); + Artifact opentest4j = new DefaultArtifact( "org.opentest4j", "opentest4j", + createFromVersion( "1.1.1" ), null, "jar", null, mock( ArtifactHandler.class ) ); + + Set providerArtifacts = new HashSet<>(); + providerArtifacts.add( provider ); + providerArtifacts.add( java5 ); + providerArtifacts.add( launcher ); + providerArtifacts.add( apiguardian ); + providerArtifacts.add( engine ); + providerArtifacts.add( commons ); + providerArtifacts.add( opentest4j ); + + when( surefirePlatformResolutionResult.getArtifacts() ) + .thenReturn( providerArtifacts ); + return surefirePlatformResolutionResult; + } + + @Test + public void shouldVerifyConfigParameters() throws Exception + { + Mojo mojo = new Mojo() + { + @Override + public File getTestClassesDirectory() + { + return new File( System.getProperty( "user.dir" ), "target/test-classes" ); + } + + @Override + protected String getEnableProcessChecker() + { + return "fake"; + } + }; + + e.expect( MojoFailureException.class ); + e.expectMessage( "Unexpected value 'fake' in the configuration parameter 'enableProcessChecker'." ); + mojo.verifyParameters(); + } + + /** + * + */ public static class Mojo - extends AbstractSurefireMojo + extends AbstractSurefireMojo implements SurefireReportParameters { + private JUnitPlatformProviderInfo createJUnitPlatformProviderInfo( Artifact providerArtifact, + TestClassPath testClasspathWrapper ) + { + return new JUnitPlatformProviderInfo( providerArtifact, testClasspathWrapper ); + } + + @Override + protected void logDebugOrCliShowErrors( String s ) + { + // do nothing + } + @Override protected String getPluginName() { @@ -411,6 +1784,18 @@ public void setSkip( boolean skip ) } + @Override + public boolean isTestFailureIgnore() + { + return false; + } + + @Override + public void setTestFailureIgnore( boolean testFailureIgnore ) + { + + } + @Override public File getBasedir() { @@ -663,6 +2048,12 @@ protected boolean hasSuiteXmlFiles() return false; } + @Override + protected String[] getExcludedEnvironmentVariables() + { + return new String[0]; + } + @Override public File[] getSuiteXmlFiles() { @@ -724,10 +2115,17 @@ protected void setUseModulePath( boolean useModulePath ) } @Override - protected Artifact getMojoArtifact() + protected String getEnableProcessChecker() { return null; } + + @Override + protected Artifact getMojoArtifact() + { + return new DefaultArtifact( "org.apache.maven.surefire", "maven-surefire-plugin", createFromVersion( "1" ), + null, "jar", null, mock( ArtifactHandler.class ) ); + } } private static File mockFile( String absolutePath ) @@ -736,4 +2134,38 @@ private static File mockFile( String absolutePath ) when( f.getAbsolutePath() ).thenReturn( absolutePath ); return f; } + + private static Dependency toDependency( Artifact artifact ) + { + Dependency dependency = new Dependency(); + dependency.setGroupId( artifact.getGroupId() ); + dependency.setArtifactId( artifact.getArtifactId() ); + dependency.setVersion( artifact.getBaseVersion() ); + dependency.setType( "jar" ); + return dependency; + } + + private static List toDependencies( Artifact... artifacts ) + { + List dependencies = new ArrayList<>(); + for ( Artifact artifact : artifacts ) + { + dependencies.add( toDependency( artifact ) ); + } + return dependencies; + } + + private static ArtifactResult toArtifactResult( final Artifact artifact ) + { + class AR implements ArtifactResult + { + + @Override + public Artifact getArtifact() + { + return artifact; + } + } + return new AR(); + } } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/CommonReflectorTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/CommonReflectorTest.java new file mode 100644 index 0000000000..1f94a754e2 --- /dev/null +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/CommonReflectorTest.java @@ -0,0 +1,99 @@ +package org.apache.maven.plugin.surefire; + +/* + * 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.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.plugin.surefire.report.DefaultReporterFactory; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.powermock.reflect.Whitebox.getInternalState; + +/** + * + */ +public class CommonReflectorTest +{ + private StartupReportConfiguration startupReportConfiguration; + private ConsoleLogger consoleLogger; + private File reportsDirectory; + private File statistics; + private SurefireStatelessReporter xmlReporter; + private SurefireConsoleOutputReporter consoleOutputReporter = new SurefireConsoleOutputReporter(); + private SurefireStatelessTestsetInfoReporter infoReporter = new SurefireStatelessTestsetInfoReporter(); + + @Before + public void setup() + { + File target = new File( System.getProperty( "user.dir" ), "target" ); + reportsDirectory = new File( target, "tmp6" ); + statistics = new File( reportsDirectory, "TESTHASH" ); + xmlReporter = new SurefireStatelessReporter(); + infoReporter = new SurefireStatelessTestsetInfoReporter(); + + startupReportConfiguration = new StartupReportConfiguration( true, true, "PLAIN", false, reportsDirectory, + false, null, statistics, false, 1, null, null, false, + xmlReporter, consoleOutputReporter, infoReporter ); + + consoleLogger = mock( ConsoleLogger.class ); + } + + @Test + public void createReportingReporterFactory() + { + CommonReflector reflector = new CommonReflector( Thread.currentThread().getContextClassLoader() ); + DefaultReporterFactory factory = (DefaultReporterFactory) reflector.createReportingReporterFactory( + startupReportConfiguration, consoleLogger ); + + assertThat( factory ) + .isNotNull(); + + StartupReportConfiguration reportConfiguration = getInternalState( factory, "reportConfiguration" ); + assertThat( reportConfiguration ) + .isNotSameAs( startupReportConfiguration ); + assertThat( reportConfiguration.isUseFile() ).isTrue(); + assertThat( reportConfiguration.isPrintSummary() ).isTrue(); + assertThat( reportConfiguration.getReportFormat() ).isEqualTo( "PLAIN" ); + assertThat( reportConfiguration.isRedirectTestOutputToFile() ).isFalse(); + assertThat( reportConfiguration.getReportsDirectory() ).isSameAs( reportsDirectory ); + assertThat( reportConfiguration.isTrimStackTrace() ).isFalse(); + assertThat( reportConfiguration.getReportNameSuffix() ).isNull(); + assertThat( reportConfiguration.getStatisticsFile() ).isSameAs( statistics ); + assertThat( reportConfiguration.isRequiresRunHistory() ).isFalse(); + assertThat( reportConfiguration.getRerunFailingTestsCount() ).isEqualTo( 1 ); + assertThat( reportConfiguration.getXsdSchemaLocation() ).isNull(); + assertThat( reportConfiguration.getEncoding() ).isEqualTo( UTF_8 ); + assertThat( reportConfiguration.isForkMode() ).isFalse(); + assertThat( reportConfiguration.getXmlReporter().toString() ) + .isEqualTo( xmlReporter.toString() ); + assertThat( reportConfiguration.getTestsetReporter().toString() ) + .isEqualTo( infoReporter.toString() ); + assertThat( reportConfiguration.getConsoleOutputReporter().toString() ) + .isEqualTo( consoleOutputReporter.toString() ); + } +} \ No newline at end of file diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java index e413c05a58..7cbd568bdd 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT1A.java @@ -1,3 +1,5 @@ +package org.apache.maven.plugin.surefire; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,9 @@ * under the License. */ -package org.apache.maven.plugin.surefire; - +/** + * + */ public class DataZT1A { } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java index eaaa48d4e7..3779ca1a02 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT2A.java @@ -1,3 +1,5 @@ +package org.apache.maven.plugin.surefire; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,9 +19,9 @@ * under the License. */ -package org.apache.maven.plugin.surefire; - - +/** + * + */ public class DataZT2A { } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java index e64ff37b03..c44752b539 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/DataZT3A.java @@ -1,3 +1,5 @@ +package org.apache.maven.plugin.surefire; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,9 +19,9 @@ * under the License. */ -package org.apache.maven.plugin.surefire; - - +/** + * + */ public class DataZT3A { } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/MojoMocklessTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/MojoMocklessTest.java index f8ba15fceb..f7393ef4c7 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/MojoMocklessTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/MojoMocklessTest.java @@ -25,8 +25,12 @@ import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; import org.apache.maven.surefire.suite.RunResult; import org.apache.maven.surefire.util.DefaultScanResult; +import org.apache.maven.toolchain.Toolchain; import org.junit.Test; import java.io.File; @@ -38,9 +42,126 @@ import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.fest.assertions.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.powermock.reflect.Whitebox.invokeMethod; +import static org.powermock.reflect.Whitebox.setInternalState; +/** + * + */ public class MojoMocklessTest { + @Test + public void testGetStartupReportConfiguration() throws Exception + { + AbstractSurefireMojo surefirePlugin = new Mojo( null, null ); + StartupReportConfiguration config = invokeMethod( surefirePlugin, "getStartupReportConfiguration", "", false ); + + assertThat( config.getXmlReporter() ) + .isNotNull() + .isInstanceOf( SurefireStatelessReporter.class ); + + assertThat( config.getConsoleOutputReporter() ) + .isNotNull() + .isInstanceOf( SurefireConsoleOutputReporter.class ); + + assertThat( config.getTestsetReporter() ) + .isNotNull() + .isInstanceOf( SurefireStatelessTestsetInfoReporter.class ); + } + + @Test + public void testGetStartupReportConfiguration2() throws Exception + { + AbstractSurefireMojo surefirePlugin = new Mojo( null, null ); + SurefireStatelessReporter xmlReporter = new SurefireStatelessReporter( false, "3.0" ); + SurefireConsoleOutputReporter consoleReporter = new SurefireConsoleOutputReporter(); + SurefireStatelessTestsetInfoReporter testsetInfoReporter = new SurefireStatelessTestsetInfoReporter(); + setInternalState( surefirePlugin, "statelessTestsetReporter", xmlReporter ); + setInternalState( surefirePlugin, "consoleOutputReporter", consoleReporter ); + setInternalState( surefirePlugin, "statelessTestsetInfoReporter", testsetInfoReporter ); + + StartupReportConfiguration config = invokeMethod( surefirePlugin, "getStartupReportConfiguration", "", false ); + + assertThat( config.getXmlReporter() ) + .isNotNull() + .isSameAs( xmlReporter ); + + assertThat( config.getConsoleOutputReporter() ) + .isNotNull() + .isSameAs( consoleReporter ); + + assertThat( config.getTestsetReporter() ) + .isNotNull() + .isSameAs( testsetInfoReporter ); + } + + @Test + public void testForkMode() + { + AbstractSurefireMojo surefirePlugin = new Mojo( null, null ); + setInternalState( surefirePlugin, "toolchain", new MyToolChain() ); + setInternalState( surefirePlugin, "forkMode", "never" ); + assertThat( surefirePlugin.getEffectiveForkMode() ) + .isEqualTo( "once" ); + } + + @Test + @SuppressWarnings( "checkstyle:magicnumber" ) + public void testForkCountComputation() + { + AbstractSurefireMojo surefirePlugin = new Mojo( null, null ); + assertConversionFails( surefirePlugin, "nothing" ); + + assertConversionFails( surefirePlugin, "5,0" ); + assertConversionFails( surefirePlugin, "5.0" ); + assertConversionFails( surefirePlugin, "5,0C" ); + assertConversionFails( surefirePlugin, "5.0CC" ); + + assertForkCount( surefirePlugin, 5, "5" ); + + int availableProcessors = Runtime.getRuntime().availableProcessors(); + assertForkCount( surefirePlugin, 3 * availableProcessors, "3C" ); + assertForkCount( surefirePlugin, (int) ( 2.5 * availableProcessors ), "2.5C" ); + assertForkCount( surefirePlugin, availableProcessors, "1.0001 C" ); + assertForkCount( surefirePlugin, 1, 1d / ( (double) availableProcessors + 1 ) + "C" ); + assertForkCount( surefirePlugin, 0, "0 C" ); + } + + private static void assertForkCount( AbstractSurefireMojo surefirePlugin, int expected, String value ) + { + assertThat( surefirePlugin.convertWithCoreCount( value ) ) + .isEqualTo( expected ); + } + + private static void assertConversionFails( AbstractSurefireMojo surefirePlugin, String value ) + { + try + { + surefirePlugin.convertWithCoreCount( value ); + } + catch ( NumberFormatException e ) + { + return; + } + fail( "Expected NumberFormatException when converting " + value ); + } + + private static class MyToolChain implements Toolchain + { + @Override + public String getType() + { + return null; + } + + @Override + public String findTool( String s ) + { + return null; + } + } + @Test public void scanDependenciesShouldReturnNull() throws MojoFailureException @@ -245,7 +366,7 @@ public void scanMultipleDependencies() .contains( "pkg.MyTest" ); } - private final static class Mojo + private static final class Mojo extends AbstractSurefireMojo { private final List projectTestArtifacts; @@ -557,6 +678,12 @@ protected boolean hasSuiteXmlFiles() return false; } + @Override + protected String[] getExcludedEnvironmentVariables() + { + return new String[0]; + } + @Override public File[] getSuiteXmlFiles() { @@ -623,6 +750,12 @@ protected void setUseModulePath( boolean useModulePath ) } + @Override + protected String getEnableProcessChecker() + { + return null; + } + @Override protected Artifact getMojoArtifact() { diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireDependencyResolverTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireDependencyResolverTest.java index cd874f3f50..1ea700255b 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireDependencyResolverTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireDependencyResolverTest.java @@ -26,6 +26,7 @@ import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.model.Dependency; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.repository.RepositorySystem; import org.junit.Rule; @@ -48,9 +49,16 @@ import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec; import static org.apache.maven.plugin.surefire.SurefireDependencyResolver.PROVIDER_GROUP_ID; import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import static org.powermock.reflect.Whitebox.invokeMethod; +/** + * + */ public class SurefireDependencyResolverTest { @Rule @@ -106,8 +114,9 @@ public void testResolveArtifact() throws InvalidVersionSpecificationException final Artifact provider = createArtifact( "surefire-junit-platform" ); RepositorySystem repositorySystem = mock( RepositorySystem.class ); final ArtifactResolutionResult expectedResult = mock( ArtifactResolutionResult.class ); - when( repositorySystem.resolve( any( ArtifactResolutionRequest.class) ) ) - .then( new Answer() { + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .then( new Answer() + { @Override public ArtifactResolutionResult answer( InvocationOnMock invocation ) { @@ -144,9 +153,9 @@ public ArtifactResolutionResult answer( InvocationOnMock invocation ) } ); SurefireDependencyResolver surefireDependencyResolver = - new SurefireDependencyResolver( repositorySystem, null, null, null, null, null ); + new SurefireDependencyResolver( repositorySystem, null, null, null, null, null, null ); - ArtifactResolutionResult actualResult = surefireDependencyResolver.resolveArtifact( provider ); + ArtifactResolutionResult actualResult = surefireDependencyResolver.resolvePluginArtifact( provider ); assertThat( actualResult ) .isSameAs( expectedResult ); @@ -173,23 +182,16 @@ public void testGetProviderClasspath() throws Exception providerArtifacts.add( ext ); providerArtifacts.add( logger ); - ArtifactFactory artifactFactory = mock( ArtifactFactory.class ); - VersionRange providerVersion = createFromVersion( "5.3.1" ); - when( artifactFactory.createDependencyArtifact( eq( "org.apache.maven.surefire" ), - eq( "surefire-junit-platform" ), - eq( providerVersion ), - eq( "jar" ), - isNull( String.class ), - eq( "test" ) ) ) - .thenReturn( provider ); + final String providerVersion = "5.3.1"; final ArtifactResolutionResult result = mock( ArtifactResolutionResult.class ); when( result.getArtifacts() ) .thenReturn( providerArtifacts ); RepositorySystem repositorySystem = mock( RepositorySystem.class ); - when( repositorySystem.resolve( any( ArtifactResolutionRequest.class) ) ) - .then( new Answer() { + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .then( new Answer() + { @Override public ArtifactResolutionResult answer( InvocationOnMock invocation ) { @@ -224,11 +226,34 @@ public ArtifactResolutionResult answer( InvocationOnMock invocation ) return result; } } ); + when( repositorySystem.createDependencyArtifact( any( Dependency.class ) ) ) + .then( new Answer() + { + @Override + public Artifact answer( InvocationOnMock invocation ) + { + Object[] args = invocation.getArguments(); + assertThat( args ) + .hasSize( 1 ); + Dependency request = (Dependency) args[0]; + assertThat( request.getGroupId() ) + .isEqualTo( "org.apache.maven.surefire" ); + assertThat( request.getArtifactId() ) + .isEqualTo( "surefire-junit-platform" ); + assertThat( request.getVersion() ) + .isEqualTo( providerVersion ); + assertThat( request.getType() ) + .isEqualTo( "jar" ); + assertThat( request.getScope() ) + .isEqualTo( "test" ); + return provider; + } + } ); ConsoleLogger log = mock( ConsoleLogger.class ); SurefireDependencyResolver surefireDependencyResolver = - new SurefireDependencyResolver( repositorySystem, artifactFactory, log, null, null, null ); + new SurefireDependencyResolver( repositorySystem, log, null, null, null, null, null ); when( log.isDebugEnabled() ) .thenReturn( true ); @@ -300,8 +325,9 @@ public void testAddProviderToClasspath() throws Exception .thenReturn( new HashSet<>( asList( provider, api, logger, ext ) ) ); RepositorySystem repositorySystem = mock( RepositorySystem.class ); - when( repositorySystem.resolve( any( ArtifactResolutionRequest.class) ) ) - .then( new Answer() { + when( repositorySystem.resolve( any( ArtifactResolutionRequest.class ) ) ) + .then( new Answer() + { @Override public ArtifactResolutionResult answer( InvocationOnMock invocation ) { @@ -334,7 +360,7 @@ else if ( artifactToResolve == ext ) } ); SurefireDependencyResolver surefireDependencyResolver = - new SurefireDependencyResolver( repositorySystem, null, null, null, null, null ); + new SurefireDependencyResolver( repositorySystem, null, null, null, null, null, null ); Map pluginArtifactsMapping = new HashMap<>(); pluginArtifactsMapping.put( plugin.getGroupId() + ":" + plugin.getArtifactId(), plugin ); @@ -344,7 +370,9 @@ else if ( artifactToResolve == ext ) pluginArtifactsMapping.put( provider.getGroupId() + ":" + provider.getArtifactId(), provider ); pluginArtifactsMapping.put( ext.getGroupId() + ":" + ext.getArtifactId(), ext ); - Set cp = surefireDependencyResolver.addProviderToClasspath( pluginArtifactsMapping, plugin, common, api, logger ); + Set cp = + surefireDependencyResolver.addProviderToClasspath( pluginArtifactsMapping, plugin, api, logger ); + assertThat( cp ) .hasSize( 4 ) .containsOnly( provider, api, logger, ext ); @@ -400,7 +428,7 @@ private static Artifact createArtifact( String artifactId ) throws InvalidVersio private static Artifact createArtifact( String groupId, String artifactId ) throws InvalidVersionSpecificationException { - return createArtifact(groupId, artifactId, "1"); + return createArtifact( groupId, artifactId, "1" ); } private static Artifact createArtifact( String groupId, String artifactId, String version ) diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java index e5f8eb8573..5b150540ab 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireHelperTest.java @@ -19,6 +19,9 @@ * under the License. */ +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.surefire.AbstractSurefireMojoTest.Mojo; +import org.apache.maven.surefire.suite.RunResult; import org.junit.Test; import java.io.File; @@ -29,7 +32,9 @@ import static java.util.Collections.singleton; import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS; import static org.apache.maven.plugin.surefire.SurefireHelper.escapeToPlatformPath; +import static org.apache.maven.plugin.surefire.SurefireHelper.reportExecution; import static org.fest.assertions.Assertions.assertThat; +import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; /** @@ -84,7 +89,7 @@ public void testConstants() assertThat( SurefireHelper.DUMPSTREAM_FILENAME_FORMATTER ) .isEqualTo( SurefireHelper.DUMP_FILE_PREFIX + "%d.dumpstream" ); - assertThat( String.format( SurefireHelper.DUMPSTREAM_FILENAME_FORMATTER, 5) ) + assertThat( String.format( SurefireHelper.DUMPSTREAM_FILENAME_FORMATTER, 5 ) ) .endsWith( "-jvmRun5.dumpstream" ); } @@ -94,6 +99,7 @@ public void shouldEscapeWindowsPath() assumeTrue( IS_OS_WINDOWS ); String root = "X:\\path\\to\\project\\"; String pathToJar = "target\\surefire\\surefirebooter4942721306300108667.jar"; + @SuppressWarnings( "checkstyle:magicnumber" ) int projectNameLength = 247 - root.length() - pathToJar.length(); StringBuilder projectFolder = new StringBuilder(); for ( int i = 0; i < projectNameLength; i++ ) @@ -108,4 +114,46 @@ public void shouldEscapeWindowsPath() escaped = escapeToPlatformPath( path ); assertThat( escaped ).isEqualTo( root + "\\" + pathToJar ); } + + @Test + public void shouldHandleFailIfNoTests() throws Exception + { + RunResult summary = new RunResult( 0, 0, 0, 0 ); + try + { + Mojo plugin = new Mojo(); + plugin.setFailIfNoTests( true ); + reportExecution( plugin, summary, null, null ); + } + catch ( MojoFailureException e ) + { + assertThat( e.getLocalizedMessage() ) + .isEqualTo( "No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)" ); + return; + } + fail( "Expected MojoFailureException with message " + + "'No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)'" ); + } + + @Test + public void shouldHandleTestFailure() throws Exception + { + RunResult summary = new RunResult( 1, 0, 1, 0 ); + try + { + reportExecution( new Mojo(), summary, null, null ); + } + catch ( MojoFailureException e ) + { + assertThat( e.getLocalizedMessage() ) + .isEqualTo( "There are test failures.\n\nPlease refer to null " + + "for the individual test results.\nPlease refer to dump files (if any exist) " + + "[date].dump, [date]-jvmRun[N].dump and [date].dumpstream." ); + return; + } + fail( "Expected MojoFailureException with message " + + "'There are test failures.\n\nPlease refer to null " + + "for the individual test results.\nPlease refer to dump files (if any exist) " + + "[date].dump, [date]-jvmRun[N].dump and [date].dumpstream.'" ); + } } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefirePropertiesTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefirePropertiesTest.java index 03aa1364ed..69c5fbfc1a 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefirePropertiesTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefirePropertiesTest.java @@ -1,4 +1,5 @@ package org.apache.maven.plugin.surefire; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -123,7 +124,8 @@ public void testPutAll() private static int size( Iterator iterator ) { int count = 0; - while ( iterator.hasNext() ) { + while ( iterator.hasNext() ) + { iterator.next(); count++; } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireReflectorTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireReflectorTest.java index a7c8b9da4a..2553617856 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireReflectorTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/SurefireReflectorTest.java @@ -1 +1,71 @@ -package org.apache.maven.plugin.surefire; /* * 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.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerDecorator; import org.apache.maven.plugin.surefire.log.api.PrintStreamLogger; import org.apache.maven.surefire.booter.IsolatedClassLoader; import org.apache.maven.surefire.booter.SurefireReflector; import org.junit.Before; import org.junit.Test; import static org.apache.maven.surefire.util.ReflectionUtils.getMethod; import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.sameInstance; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** * @author Tibor Digana (tibor17) * @see ConsoleLogger * @see SurefireReflector * @since 2.20 */ public class SurefireReflectorTest { private ConsoleLogger logger; private SurefireReflector reflector; @Before public void prepareData() { logger = spy( new PrintStreamLogger( System.out ) ); ClassLoader cl = new IsolatedClassLoader( Thread.currentThread().getContextClassLoader(), false, "role" ); reflector = new SurefireReflector( cl ); } @Test public void shouldProxyConsoleLogger() { Object mirror = reflector.createConsoleLogger( logger ); assertThat( mirror, is( notNullValue() ) ); assertThat( mirror.getClass().getInterfaces()[0].getName(), is( ConsoleLogger.class.getName() ) ); assertThat( mirror, is( not( sameInstance( (Object) logger ) ) ) ); assertThat( mirror, is( instanceOf( ConsoleLoggerDecorator.class ) ) ); invokeMethodWithArray( mirror, getMethod( mirror, "info", String.class ), "Hi There!" ); verify( logger, times( 1 ) ).info( "Hi There!" ); } } \ No newline at end of file +package org.apache.maven.plugin.surefire; + +/* + * 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.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerDecorator; +import org.apache.maven.plugin.surefire.log.api.PrintStreamLogger; +import org.apache.maven.surefire.booter.IsolatedClassLoader; +import org.apache.maven.surefire.booter.SurefireReflector; +import org.junit.Before; +import org.junit.Test; + +import static org.apache.maven.surefire.util.ReflectionUtils.getMethod; +import static org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.sameInstance; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +/** + * @author Tibor Digana (tibor17) + * @see ConsoleLogger + * @see SurefireReflector + * @since 2.20 + */ +public class SurefireReflectorTest +{ + private ConsoleLogger logger; + private ClassLoader cl; + + @Before + public void prepareData() + { + logger = spy( new PrintStreamLogger( System.out ) ); + cl = new IsolatedClassLoader( Thread.currentThread().getContextClassLoader(), false, "role" ); + } + + @Test + public void shouldProxyConsoleLogger() + { + Object mirror = SurefireReflector.createConsoleLogger( logger, cl ); + assertThat( mirror, is( notNullValue() ) ); + assertThat( mirror.getClass().getInterfaces()[0].getName(), is( ConsoleLogger.class.getName() ) ); + assertThat( mirror, is( not( sameInstance( (Object) logger ) ) ) ); + assertThat( mirror, is( instanceOf( ConsoleLoggerDecorator.class ) ) ); + invokeMethodWithArray( mirror, getMethod( mirror, "info", String.class ), "Hi There!" ); + verify( logger, times( 1 ) ).info( "Hi There!" ); + } +} diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java index 7750c93e74..616534d970 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java @@ -21,16 +21,36 @@ import junit.framework.Assert; import junit.framework.TestCase; -import org.apache.maven.surefire.booter.*; +import org.apache.commons.io.FileUtils; +import org.apache.maven.surefire.booter.BooterDeserializer; +import org.apache.maven.surefire.booter.ClassLoaderConfiguration; +import org.apache.maven.surefire.booter.ClasspathConfiguration; +import org.apache.maven.surefire.booter.ProcessCheckerType; +import org.apache.maven.surefire.booter.PropertiesWrapper; +import org.apache.maven.surefire.booter.ProviderConfiguration; +import org.apache.maven.surefire.booter.Shutdown; +import org.apache.maven.surefire.booter.StartupConfiguration; +import org.apache.maven.surefire.booter.TypeEncodedValue; import org.apache.maven.surefire.cli.CommandLineOption; import org.apache.maven.surefire.report.ReporterConfiguration; -import org.apache.maven.surefire.testset.*; +import org.apache.maven.surefire.testset.DirectoryScannerParameters; +import org.apache.maven.surefire.testset.ResolvedTest; +import org.apache.maven.surefire.testset.RunOrderParameters; +import org.apache.maven.surefire.testset.TestArtifactInfo; +import org.apache.maven.surefire.testset.TestListResolver; +import org.apache.maven.surefire.testset.TestRequest; import org.apache.maven.surefire.util.RunOrder; +import org.junit.After; +import org.junit.Before; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.util.*; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; import static org.apache.maven.surefire.cli.CommandLineOption.LOGGING_LEVEL_DEBUG; import static org.apache.maven.surefire.cli.CommandLineOption.REACTOR_FAIL_FAST; @@ -45,17 +65,36 @@ public class BooterDeserializerProviderConfigurationTest extends TestCase { - public static final TypeEncodedValue aTestTyped = new TypeEncodedValue( String.class.getName(), "aTest" ); + static final TypeEncodedValue TEST_TYPED = new TypeEncodedValue( String.class.getName(), "aTest" ); - private static final String aUserRequestedTest = "aUserRequestedTest"; + private static final String USER_REQUESTED_TEST = "aUserRequestedTest"; - private static final String aUserRequestedTestMethod = "aUserRequestedTestMethod"; + private static final String USER_REQUESTED_TEST_METHOD = "aUserRequestedTestMethod"; - private static final int rerunFailingTestsCount = 3; + private static final int RERUN_FAILING_TEST_COUNT = 3; + + private static int idx = 0; + + private File basedir; private final List cli = Arrays.asList( LOGGING_LEVEL_DEBUG, SHOW_ERRORS, REACTOR_FAIL_FAST ); + @Before + public void setupDirectories() throws IOException + { + File target = new File( System.getProperty( "user.dir" ), "target" ); + basedir = new File( target, "BooterDeserializerProviderConfigurationTest-" + ++idx ); + FileUtils.deleteDirectory( basedir ); + assertTrue( basedir.mkdirs() ); + } + + @After + public void deleteDirectories() throws IOException + { + FileUtils.deleteDirectory( basedir ); + } + private static ClassLoaderConfiguration getForkConfiguration() { return new ClassLoaderConfiguration( true, false ); @@ -127,15 +166,16 @@ public void testTestRequest() TestListResolver resolver = testSuiteDefinition.getTestListResolver(); Assert.assertNotNull( resolver ); Assert.assertFalse( resolver.isEmpty() ); - Assert.assertEquals( aUserRequestedTest + "#" + aUserRequestedTestMethod, resolver.getPluginParameterTest() ); + Assert.assertEquals( USER_REQUESTED_TEST + "#" + USER_REQUESTED_TEST_METHOD, + resolver.getPluginParameterTest() ); Assert.assertFalse( resolver.getIncludedPatterns().isEmpty() ); Assert.assertTrue( resolver.getExcludedPatterns().isEmpty() ); Assert.assertEquals( 1, resolver.getIncludedPatterns().size() ); ResolvedTest filter = resolver.getIncludedPatterns().iterator().next(); Assert.assertNotNull( filter ); - Assert.assertEquals( "**/" + aUserRequestedTest, filter.getTestClassPattern() ); - Assert.assertEquals( aUserRequestedTestMethod, filter.getTestMethodPattern() ); - Assert.assertEquals( rerunFailingTestsCount, testSuiteDefinition.getRerunFailingTestsCount() ); + Assert.assertEquals( "**/" + USER_REQUESTED_TEST, filter.getTestClassPattern() ); + Assert.assertEquals( USER_REQUESTED_TEST_METHOD, filter.getTestMethodPattern() ); + Assert.assertEquals( RERUN_FAILING_TEST_COUNT, testSuiteDefinition.getRerunFailingTestsCount() ); assertEquals( cli, reloaded.getMainCliOptions() ); } @@ -143,7 +183,7 @@ public void testTestForFork() throws IOException { final ProviderConfiguration reloaded = getReloadedProviderConfiguration(); - Assert.assertEquals( aTestTyped, reloaded.getTestForFork() ); + Assert.assertEquals( TEST_TYPED, reloaded.getTestForFork() ); assertEquals( cli, reloaded.getMainCliOptions() ); } @@ -207,7 +247,7 @@ private ProviderConfiguration saveAndReload( ProviderConfiguration booterConfigu boolean readTestsFromInStream ) throws IOException { - final ForkConfiguration forkConfiguration = ForkConfigurationTest.getForkConfiguration( (String) null ); + final ForkConfiguration forkConfiguration = ForkConfigurationTest.getForkConfiguration( basedir, null ); PropertiesWrapper props = new PropertiesWrapper( new HashMap() ); BooterSerializer booterSerializer = new BooterSerializer( forkConfiguration ); Object test; @@ -222,7 +262,7 @@ private ProviderConfiguration saveAndReload( ProviderConfiguration booterConfigu final File propsTest = booterSerializer.serialize( props, booterConfiguration, testProviderConfiguration, test, readTestsFromInStream, 51L, 1 ); BooterDeserializer booterDeserializer = new BooterDeserializer( new FileInputStream( propsTest ) ); - assertEquals( 51L, (Object) booterDeserializer.getPluginPid() ); + assertEquals( "51", (Object) booterDeserializer.getPluginPid() ); return booterDeserializer.deserialize(); } @@ -233,11 +273,11 @@ private ProviderConfiguration getTestProviderConfiguration( DirectoryScannerPara ReporterConfiguration reporterConfiguration = new ReporterConfiguration( cwd, true ); TestRequest testSuiteDefinition = new TestRequest( getSuiteXmlFileStrings(), getTestSourceDirectory(), - new TestListResolver( aUserRequestedTest + "#aUserRequestedTestMethod" ), - rerunFailingTestsCount ); + new TestListResolver( USER_REQUESTED_TEST + "#aUserRequestedTestMethod" ), + RERUN_FAILING_TEST_COUNT ); RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null ); return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration, - new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap(), aTestTyped, + new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap(), TEST_TYPED, readTestsFromInStream, cli, 0, Shutdown.DEFAULT, 0 ); } @@ -246,7 +286,7 @@ private StartupConfiguration getTestStartupConfiguration( ClassLoaderConfigurati ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration( true, true ); return new StartupConfiguration( "com.provider", classpathConfiguration, classLoaderConfiguration, false, - false ); + false, ProcessCheckerType.ALL ); } private File getTestSourceDirectory() diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java index 7a1a7e2d68..ec844d3959 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java @@ -20,11 +20,27 @@ */ import junit.framework.TestCase; -import org.apache.maven.surefire.booter.*; +import org.apache.commons.io.FileUtils; +import org.apache.maven.surefire.booter.AbstractPathConfiguration; +import org.apache.maven.surefire.booter.BooterDeserializer; +import org.apache.maven.surefire.booter.Classpath; +import org.apache.maven.surefire.booter.ClasspathConfiguration; +import org.apache.maven.surefire.booter.ClassLoaderConfiguration; +import org.apache.maven.surefire.booter.ProcessCheckerType; +import org.apache.maven.surefire.booter.PropertiesWrapper; +import org.apache.maven.surefire.booter.ProviderConfiguration; +import org.apache.maven.surefire.booter.StartupConfiguration; +import org.apache.maven.surefire.booter.Shutdown; import org.apache.maven.surefire.cli.CommandLineOption; import org.apache.maven.surefire.report.ReporterConfiguration; -import org.apache.maven.surefire.testset.*; +import org.apache.maven.surefire.testset.DirectoryScannerParameters; +import org.apache.maven.surefire.testset.RunOrderParameters; +import org.apache.maven.surefire.testset.TestArtifactInfo; +import org.apache.maven.surefire.testset.TestRequest; +import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.util.RunOrder; +import org.junit.After; +import org.junit.Before; import java.io.File; import java.io.FileInputStream; @@ -46,11 +62,31 @@ public class BooterDeserializerStartupConfigurationTest extends TestCase { + + private static int idx = 0; + + private File basedir; + private final ClasspathConfiguration classpathConfiguration = createClasspathConfiguration(); private final List cli = Arrays.asList( LOGGING_LEVEL_DEBUG, SHOW_ERRORS, REACTOR_FAIL_FAST ); + @Before + public void setupDirectories() throws IOException + { + File target = new File( System.getProperty( "user.dir" ), "target" ); + basedir = new File( target, "BooterDeserializerProviderConfigurationTest-" + ++idx ); + FileUtils.deleteDirectory( basedir ); + assertTrue( basedir.mkdirs() ); + } + + @After + public void deleteDirectories() throws IOException + { + FileUtils.deleteDirectory( basedir ); + } + public void testProvider() throws IOException { @@ -67,6 +103,11 @@ public void testClassPathConfiguration() assertCpConfigEquals( classpathConfiguration, (ClasspathConfiguration) reloadedClasspathConfiguration ); } + public void testProcessChecker() throws IOException + { + assertEquals( ProcessCheckerType.ALL, getReloadedStartupConfiguration().getProcessChecker() ); + } + private void assertCpConfigEquals( ClasspathConfiguration expectedConfiguration, ClasspathConfiguration actualConfiguration ) { @@ -93,6 +134,18 @@ public void testClassLoaderConfigurationTrues() assertEquals( current, saveAndReload( testStartupConfiguration ).isManifestOnlyJarRequestedAndUsable() ); } + public void testProcessCheckerAll() throws IOException + { + assertEquals( ProcessCheckerType.ALL, getReloadedStartupConfiguration().getProcessChecker() ); + } + + public void testProcessCheckerNull() throws IOException + { + StartupConfiguration startupConfiguration = new StartupConfiguration( "com.provider", classpathConfiguration, + getManifestOnlyJarForkConfiguration(), false, false, null ); + assertNull( saveAndReload( startupConfiguration ).getProcessChecker() ); + } + private ClasspathConfiguration createClasspathConfiguration() { Classpath testClassPath = new Classpath( Arrays.asList( "CP1", "CP2" ) ); @@ -100,17 +153,16 @@ private ClasspathConfiguration createClasspathConfiguration() return new ClasspathConfiguration( testClassPath, providerClasspath, Classpath.emptyClasspath(), true, true ); } - public static ClassLoaderConfiguration getSystemClassLoaderConfiguration() + private static ClassLoaderConfiguration getSystemClassLoaderConfiguration() { return new ClassLoaderConfiguration( true, false ); } - public static ClassLoaderConfiguration getManifestOnlyJarForkConfiguration() + private static ClassLoaderConfiguration getManifestOnlyJarForkConfiguration() { return new ClassLoaderConfiguration( true, true ); } - private StartupConfiguration getReloadedStartupConfiguration() throws IOException { @@ -121,7 +173,7 @@ private StartupConfiguration getReloadedStartupConfiguration() private StartupConfiguration saveAndReload( StartupConfiguration startupConfiguration ) throws IOException { - final ForkConfiguration forkConfiguration = ForkConfigurationTest.getForkConfiguration( (String) null ); + final ForkConfiguration forkConfiguration = ForkConfigurationTest.getForkConfiguration( basedir, null ); PropertiesWrapper props = new PropertiesWrapper( new HashMap() ); BooterSerializer booterSerializer = new BooterSerializer( forkConfiguration ); String aTest = "aTest"; @@ -129,7 +181,7 @@ private StartupConfiguration saveAndReload( StartupConfiguration startupConfigur false, null, 1 ); BooterDeserializer booterDeserializer = new BooterDeserializer( new FileInputStream( propsTest ) ); assertNull( booterDeserializer.getPluginPid() ); - return booterDeserializer.getProviderConfiguration(); + return booterDeserializer.getStartupConfiguration(); } private ProviderConfiguration getProviderConfiguration() @@ -142,18 +194,18 @@ private ProviderConfiguration getProviderConfiguration() ReporterConfiguration reporterConfiguration = new ReporterConfiguration( cwd, true ); TestRequest testSuiteDefinition = new TestRequest( Arrays.asList( getSuiteXmlFileStrings() ), getTestSourceDirectory(), - new TestListResolver( "aUserRequestedTest#aUserRequestedTestMethod" )); + new TestListResolver( "aUserRequestedTest#aUserRequestedTestMethod" ) ); RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, null ); return new ProviderConfiguration( directoryScannerParameters, runOrderParameters, true, reporterConfiguration, new TestArtifactInfo( "5.0", "ABC" ), testSuiteDefinition, new HashMap(), - BooterDeserializerProviderConfigurationTest.aTestTyped, true, cli, 0, Shutdown.DEFAULT, 0 ); + BooterDeserializerProviderConfigurationTest.TEST_TYPED, true, cli, 0, Shutdown.DEFAULT, 0 ); } private StartupConfiguration getTestStartupConfiguration( ClassLoaderConfiguration classLoaderConfiguration ) { return new StartupConfiguration( "com.provider", classpathConfiguration, classLoaderConfiguration, false, - false ); + false, ProcessCheckerType.ALL ); } private File getTestSourceDirectory() diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfigurationTest.java index 6bedab930e..06fe7546cb 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/DefaultForkConfigurationTest.java @@ -31,6 +31,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -47,7 +48,12 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.powermock.api.mockito.PowerMockito.*; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.spy; +import static org.powermock.api.mockito.PowerMockito.verifyPrivate; +import static org.powermock.api.mockito.PowerMockito.verifyStatic; +import static org.powermock.api.mockito.PowerMockito.when; import static org.powermock.reflect.Whitebox.invokeMethod; /** @@ -58,6 +64,7 @@ */ @RunWith( PowerMockRunner.class ) @PrepareForTest( { DefaultForkConfiguration.class, Relocator.class } ) +@PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } ) public class DefaultForkConfigurationTest { private Classpath booterClasspath; @@ -67,6 +74,7 @@ public class DefaultForkConfigurationTest private Properties modelProperties; private String argLine; private Map environmentVariables; + private String[] excludedEnvironmentVariables; private boolean debug; private int forkCount; private boolean reuseForks; @@ -83,6 +91,7 @@ public void setup() modelProperties = new Properties(); argLine = null; environmentVariables = new HashMap<>(); + excludedEnvironmentVariables = new String[0]; debug = true; forkCount = 2; reuseForks = true; @@ -94,8 +103,8 @@ public void setup() public void shouldBeNullArgLine() throws Exception { DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine, - workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks, - pluginPlatform, log ) + workingDirectory, modelProperties, argLine, environmentVariables, excludedEnvironmentVariables, + debug, forkCount, reuseForks, pluginPlatform, log ) { @Override @@ -120,8 +129,8 @@ public void shouldBeEmptyArgLine() throws Exception { argLine = ""; DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine, - workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks, - pluginPlatform, log ) + workingDirectory, modelProperties, argLine, environmentVariables, excludedEnvironmentVariables, + debug, forkCount, reuseForks, pluginPlatform, log ) { @Override @@ -146,8 +155,8 @@ public void shouldBeEmptyArgLineInsteadOfNewLines() throws Exception { argLine = "\n\r"; DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine, - workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks, - pluginPlatform, log ) + workingDirectory, modelProperties, argLine, environmentVariables, excludedEnvironmentVariables, + debug, forkCount, reuseForks, pluginPlatform, log ) { @Override @@ -172,8 +181,8 @@ public void shouldBeWithoutEscaping() throws Exception { argLine = "-Dfile.encoding=UTF-8"; DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine, - workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks, - pluginPlatform, log ) + workingDirectory, modelProperties, argLine, environmentVariables, excludedEnvironmentVariables, + debug, forkCount, reuseForks, pluginPlatform, log ) { @Override @@ -199,8 +208,8 @@ public void shouldBeWithEscaping() throws Exception modelProperties.put( "encoding", "UTF-8" ); argLine = "-Dfile.encoding=@{encoding}"; DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine, - workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks, - pluginPlatform, log ) + workingDirectory, modelProperties, argLine, environmentVariables, excludedEnvironmentVariables, + debug, forkCount, reuseForks, pluginPlatform, log ) { @Override @@ -225,8 +234,8 @@ public void shouldBeWhitespaceInsteadOfNewLines() throws Exception { argLine = "a\n\rb"; DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine, - workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks, - pluginPlatform, log ) + workingDirectory, modelProperties, argLine, environmentVariables, excludedEnvironmentVariables, + debug, forkCount, reuseForks, pluginPlatform, log ) { @Override @@ -251,8 +260,8 @@ public void shouldEscapeThreadNumber() throws Exception { argLine = "-Dthread=${surefire.threadNumber}"; DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine, - workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks, - pluginPlatform, log ) + workingDirectory, modelProperties, argLine, environmentVariables, excludedEnvironmentVariables, + debug, forkCount, reuseForks, pluginPlatform, log ) { @Override @@ -277,8 +286,8 @@ public void shouldEscapeForkNumber() throws Exception { argLine = "-Dthread=${surefire.forkNumber}"; DefaultForkConfiguration config = new DefaultForkConfiguration( booterClasspath, tempDirectory, debugLine, - workingDirectory, modelProperties, argLine, environmentVariables, debug, forkCount, reuseForks, - pluginPlatform, log ) + workingDirectory, modelProperties, argLine, environmentVariables, excludedEnvironmentVariables, + debug, forkCount, reuseForks, pluginPlatform, log ) { @Override @@ -303,8 +312,8 @@ public void shouldRelocateBooterClassWhenShadefire() throws Exception { ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true ); ClasspathConfiguration cc = new ClasspathConfiguration( true, true ); - StartupConfiguration conf = - new StartupConfiguration( "org.apache.maven.shadefire.surefire.MyProvider", cc, clc, false, false ); + StartupConfiguration conf = new StartupConfiguration( "org.apache.maven.shadefire.surefire.MyProvider", + cc, clc, false, false, null ); StartupConfiguration confMock = spy( conf ); mockStatic( Relocator.class ); when( Relocator.relocate( anyString() ) ).thenCallRealMethod(); @@ -325,7 +334,7 @@ public void shouldNotRelocateBooterClass() throws Exception ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true ); ClasspathConfiguration cc = new ClasspathConfiguration( true, true ); StartupConfiguration conf = - new StartupConfiguration( "org.apache.maven.surefire.MyProvider", cc, clc, false, false ); + new StartupConfiguration( "org.apache.maven.surefire.MyProvider", cc, clc, false, false, null ); StartupConfiguration confMock = spy( conf ); mockStatic( Relocator.class ); when( Relocator.relocate( anyString() ) ).thenCallRealMethod(); diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java index 575c0fd382..f38f99773d 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkConfigurationTest.java @@ -20,7 +20,6 @@ */ import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.SystemUtils; import org.apache.maven.plugin.surefire.JdkAttributes; import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger; @@ -31,6 +30,8 @@ import org.apache.maven.surefire.booter.ClasspathConfiguration; import org.apache.maven.surefire.booter.StartupConfiguration; import org.apache.maven.surefire.booter.SurefireBooterForkException; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import java.io.File; @@ -39,34 +40,58 @@ import java.util.List; import java.util.Properties; -import static java.io.File.createTempFile; import static java.util.Collections.singletonList; import static org.apache.maven.surefire.booter.Classpath.emptyClasspath; +import static org.apache.maven.surefire.booter.ProcessCheckerType.ALL; import static org.fest.util.Files.temporaryFolder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +/** + * + */ public class ForkConfigurationTest { private static final StartupConfiguration STARTUP_CONFIG = new StartupConfiguration( "", new ClasspathConfiguration( true, true ), new ClassLoaderConfiguration( true, true ), false, - false ); + false, + ALL ); + + private static int idx = 0; + + private File basedir; + + @Before + public void setupDirectories() throws IOException + { + File target = new File( System.getProperty( "user.dir" ), "target" ); + basedir = new File( target, "SUREFIRE-1136-" + ++idx ); + FileUtils.deleteDirectory( basedir ); + assertTrue( basedir.mkdirs() ); + } + + @After + public void deleteDirectories() throws IOException + { + FileUtils.deleteDirectory( basedir ); + } @Test + @SuppressWarnings( { "checkstyle:methodname", "checkstyle:magicnumber" } ) public void testCreateCommandLine_UseSystemClassLoaderForkOnce_ShouldConstructManifestOnlyJar() throws IOException, SurefireBooterForkException { - ForkConfiguration config = getForkConfiguration( (String) null ); + ForkConfiguration config = getForkConfiguration( basedir, null ); File cpElement = getTempClasspathFile(); List cp = singletonList( cpElement.getAbsolutePath() ); ClasspathConfiguration cpConfig = new ClasspathConfiguration( new Classpath( cp ), emptyClasspath(), emptyClasspath(), true, true ); ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true ); - StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, false, false ); + StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, false, false, ALL ); Commandline cli = config.createCommandLine( startup, 1, temporaryFolder() ); @@ -79,14 +104,14 @@ public void testArglineWithNewline() throws IOException, SurefireBooterForkException { // SUREFIRE-657 - ForkConfiguration config = getForkConfiguration( "abc\ndef" ); + ForkConfiguration config = getForkConfiguration( basedir, "abc\ndef" ); File cpElement = getTempClasspathFile(); List cp = singletonList( cpElement.getAbsolutePath() ); ClasspathConfiguration cpConfig = new ClasspathConfiguration( new Classpath( cp ), emptyClasspath(), emptyClasspath(), true, true ); ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true ); - StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, false, false ); + StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, false, false, ALL ); Commandline commandLine = config.createCommandLine( startup, 1, temporaryFolder() ); assertTrue( commandLine.toString().contains( "abc def" ) ); @@ -96,23 +121,16 @@ public void testArglineWithNewline() public void testCurrentWorkingDirectoryPropagationIncludingForkNumberExpansion() throws IOException, SurefireBooterForkException { - // SUREFIRE-1136 - File baseDir = - new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + RandomStringUtils.randomAlphabetic( 3 ) ); - assertTrue( baseDir.mkdirs() ); - baseDir.deleteOnExit(); - - File cwd = new File( baseDir, "fork_${surefire.forkNumber}" ); + File cwd = new File( basedir, "fork_${surefire.forkNumber}" ); ClasspathConfiguration cpConfig = new ClasspathConfiguration( emptyClasspath(), emptyClasspath(), emptyClasspath(), true, true ); ClassLoaderConfiguration clc = new ClassLoaderConfiguration( true, true ); - StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, false, false ); + StartupConfiguration startup = new StartupConfiguration( "", cpConfig, clc, false, false, ALL ); ForkConfiguration config = getForkConfiguration( cwd.getCanonicalFile() ); Commandline commandLine = config.createCommandLine( startup, 1, temporaryFolder() ); - File forkDirectory = new File( baseDir, "fork_1" ); - forkDirectory.deleteOnExit(); + File forkDirectory = new File( basedir, "fork_1" ); String shellWorkDir = commandLine.getShell().getWorkingDirectory().getCanonicalPath(); assertEquals( shellWorkDir, forkDirectory.getCanonicalPath() ); @@ -122,29 +140,25 @@ public void testCurrentWorkingDirectoryPropagationIncludingForkNumberExpansion() public void testExceptionWhenCurrentDirectoryIsNotRealDirectory() throws IOException { - // SUREFIRE-1136 - File baseDir = - new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + RandomStringUtils.randomAlphabetic( 3 ) ); - assertTrue( baseDir.mkdirs() ); - baseDir.deleteOnExit(); - - File cwd = new File( baseDir, "cwd.txt" ); + File cwd = new File( basedir, "cwd.txt" ); FileUtils.touch( cwd ); - cwd.deleteOnExit(); - - ForkConfiguration config = getForkConfiguration( cwd.getCanonicalFile() ); try { + ForkConfiguration config = getForkConfiguration( cwd.getCanonicalFile() ); config.createCommandLine( STARTUP_CONFIG, 1, temporaryFolder() ); } - catch ( SurefireBooterForkException sbfe ) + catch ( SurefireBooterForkException e ) { // To handle issue with ~ expansion on Windows String absolutePath = cwd.getCanonicalPath(); - assertEquals( "WorkingDirectory " + absolutePath + " exists and is not a directory", sbfe.getMessage() ); + assertEquals( "WorkingDirectory " + absolutePath + " exists and is not a directory", e.getMessage() ); return; } + finally + { + assertTrue( cwd.delete() ); + } fail(); } @@ -153,19 +167,14 @@ public void testExceptionWhenCurrentDirectoryIsNotRealDirectory() public void testExceptionWhenCurrentDirectoryCannotBeCreated() throws IOException { - // SUREFIRE-1136 - File baseDir = - new File( FileUtils.getTempDirectory(), "SUREFIRE-1136-" + RandomStringUtils.randomAlphabetic( 3 ) ); - assertTrue( baseDir.mkdirs() ); - baseDir.deleteOnExit(); - - // NULL is invalid for JDK starting from 1.7.60 - https://github.com/openjdk-mirror/jdk/commit/e5389115f3634d25d101e2dcc71f120d4fd9f72f + // NULL is invalid for JDK starting from 1.7.60 + // - https://github.com/openjdk-mirror/jdk/commit/e5389115f3634d25d101e2dcc71f120d4fd9f72f // ? character is invalid on Windows, seems to be imposable to create invalid directory using Java on Linux - File cwd = new File( baseDir, "?\u0000InvalidDirectoryName" ); - ForkConfiguration config = getForkConfiguration( cwd.getAbsoluteFile() ); + File cwd = new File( basedir, "?\u0000InvalidDirectoryName" ); try { + ForkConfiguration config = getForkConfiguration( cwd.getAbsoluteFile() ); config.createCommandLine( STARTUP_CONFIG, 1, temporaryFolder() ); } catch ( SurefireBooterForkException sbfe ) @@ -173,6 +182,10 @@ public void testExceptionWhenCurrentDirectoryCannotBeCreated() assertEquals( "Cannot create workingDirectory " + cwd.getAbsolutePath(), sbfe.getMessage() ); return; } + finally + { + FileUtils.deleteDirectory( cwd ); + } if ( SystemUtils.IS_OS_WINDOWS || isJavaVersionAtLeast7u60() ) { @@ -183,38 +196,40 @@ public void testExceptionWhenCurrentDirectoryCannotBeCreated() private File getTempClasspathFile() throws IOException { - File cpElement = createTempFile( "ForkConfigurationTest.", ".file" ); - cpElement.deleteOnExit(); + File cpElement = new File( basedir, "ForkConfigurationTest." + idx + ".file" ); + FileUtils.deleteDirectory( cpElement ); return cpElement; } - static ForkConfiguration getForkConfiguration( String argLine ) + static ForkConfiguration getForkConfiguration( File basedir, String argLine ) throws IOException { File jvm = new File( new File( System.getProperty( "java.home" ), "bin" ), "java" ); - return getForkConfiguration( argLine, jvm.getAbsolutePath(), new File( "." ).getCanonicalFile() ); + return getForkConfiguration( basedir, argLine, jvm.getAbsolutePath(), new File( "." ).getCanonicalFile() ); } - private static ForkConfiguration getForkConfiguration( File cwd ) + private ForkConfiguration getForkConfiguration( File cwd ) throws IOException { File jvm = new File( new File( System.getProperty( "java.home" ), "bin" ), "java" ); - return getForkConfiguration( null, jvm.getAbsolutePath(), cwd ); + return getForkConfiguration( basedir, null, jvm.getAbsolutePath(), cwd ); } - private static ForkConfiguration getForkConfiguration( String argLine, String jvm, File cwd ) + private static ForkConfiguration getForkConfiguration( File basedir, String argLine, String jvm, File cwd ) throws IOException { Platform platform = new Platform().withJdkExecAttributesForTests( new JdkAttributes( jvm, false ) ); - File tmpDir = createTempFile( "target", "surefire" ); - assertTrue( tmpDir.delete() ); + File tmpDir = new File( new File( basedir, "target" ), "surefire" ); + FileUtils.deleteDirectory( tmpDir ); assertTrue( tmpDir.mkdirs() ); return new JarManifestForkConfiguration( emptyClasspath(), tmpDir, null, - cwd, new Properties(), argLine, Collections.emptyMap(), false, 1, false, + cwd, new Properties(), argLine, + Collections.emptyMap(), new String[0], false, 1, false, platform, new NullConsoleLogger() ); } // based on http://stackoverflow.com/questions/2591083/getting-version-of-java-in-runtime + @SuppressWarnings( "checkstyle:magicnumber" ) private static boolean isJavaVersionAtLeast7u60() { String[] javaVersionElements = System.getProperty( "java.runtime.version" ).split( "\\.|_|-b" ); diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java index 0fd275f7b9..79c6f0e178 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/ForkingRunListenerTest.java @@ -25,6 +25,7 @@ import org.apache.maven.plugin.surefire.booterclient.output.ForkClient; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger; +import org.apache.maven.surefire.booter.ForkedChannelEncoder; import org.apache.maven.surefire.booter.ForkingRunListener; import org.apache.maven.surefire.report.CategorizedReportEntry; import org.apache.maven.surefire.report.ConsoleOutputReceiver; @@ -40,16 +41,17 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; -import java.nio.charset.Charset; +import java.util.Collections; import java.util.List; -import java.util.StringTokenizer; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; -import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; /** * @author Kristian Rosenvold */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class ForkingRunListenerTest extends TestCase { @@ -57,10 +59,6 @@ public class ForkingRunListenerTest private final PrintStream printStream, anotherPrintStream; - final int defaultChannel = 17; - - final int anotherChannel = 18; - public ForkingRunListenerTest() { content = new ByteArrayOutputStream(); @@ -76,20 +74,6 @@ private void reset() content.reset(); } - public void testHeaderCreation() - { - final byte[] header = ForkingRunListener.createHeader( (byte) 'F', 0xCAFE ); - String asString = new String( header ); - assertEquals( "F,cafe," + Charset.defaultCharset().name() + ",", asString ); - } - - public void testHeaderCreationShort() - { - final byte[] header = ForkingRunListener.createHeader( (byte) 'F', 0xE ); - String asString = new String( header ); - assertEquals( "F,e," + Charset.defaultCharset().name() + ",", asString ); - } - public void testSetStarting() throws ReporterException, IOException { @@ -117,19 +101,6 @@ public void testStarting() standardTestRun.assertExpected( MockReporter.TEST_STARTING, expected ); } - public void testStringTokenizer() - { - String test = "5,11,com.abc.TestClass,testMethod,null,22,,,"; - StringTokenizer tok = new StringTokenizer( test, "," ); - assertEquals( "5", tok.nextToken() ); - assertEquals( "11", tok.nextToken() ); - assertEquals( "com.abc.TestClass", tok.nextToken() ); - assertEquals( "testMethod", tok.nextToken() ); - assertEquals( "null", tok.nextToken() ); - assertEquals( "22", tok.nextToken() ); - assertFalse( tok.hasMoreTokens() ); - } - public void testSucceded() throws ReporterException, IOException { @@ -199,7 +170,7 @@ public void testConsole() final StandardTestRun standardTestRun = new StandardTestRun(); ConsoleLogger directConsoleReporter = (ConsoleLogger) standardTestRun.run(); directConsoleReporter.info( "HeyYou" ); - standardTestRun.assertExpected( MockReporter.CONSOLE_OUTPUT, "HeyYou" ); + standardTestRun.assertExpected( MockReporter.CONSOLE_INFO, "HeyYou" ); } public void testConsoleOutput() @@ -207,7 +178,7 @@ public void testConsoleOutput() { final StandardTestRun standardTestRun = new StandardTestRun(); ConsoleOutputReceiver directConsoleReporter = (ConsoleOutputReceiver) standardTestRun.run(); - directConsoleReporter.writeTestOutput( "HeyYou".getBytes(), 0, 6, true ); + directConsoleReporter.writeTestOutput( "HeyYou", false, true ); standardTestRun.assertExpected( MockReporter.STDOUT, "HeyYou" ); } @@ -218,16 +189,17 @@ public void testSystemProperties() standardTestRun.run(); reset(); - createForkingRunListener( defaultChannel ); + createForkingRunListener(); TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory(); NullConsoleLogger log = new NullConsoleLogger(); ForkClient forkStreamClient = - new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, null, 1 ); + new ForkClient( providerReporterFactory, new MockNotifiableTestStream(), log, new AtomicBoolean(), 1 ); - forkStreamClient.consumeMultiLineContent( content.toString( "UTF-8" ) ); + forkStreamClient.consumeMultiLineContent( ":maven:surefire:std:out:sys-prop:normal-run:UTF-8:azE=:djE=" + + "\n:maven:surefire:std:out:sys-prop:normal-run:UTF-8:azI=:djI=" ); - MatcherAssert.assertThat( forkStreamClient.getTestVmSystemProperties().size(), is( greaterThan( 1 ) ) ); + MatcherAssert.assertThat( forkStreamClient.getTestVmSystemProperties().size(), is( 2 ) ); } public void testMultipleEntries() @@ -237,7 +209,7 @@ public void testMultipleEntries() standardTestRun.run(); reset(); - RunListener forkingReporter = createForkingRunListener( defaultChannel ); + RunListener forkingReporter = createForkingRunListener(); TestSetReportEntry reportEntry = createDefaultReportEntry(); forkingReporter.testSetStarting( reportEntry ); @@ -267,10 +239,10 @@ public void test2DifferentChannels() ReportEntry expected = createDefaultReportEntry(); final SimpleReportEntry secondExpected = createAnotherDefaultReportEntry(); - new ForkingRunListener( printStream, defaultChannel, false ) + new ForkingRunListener( new ForkedChannelEncoder( printStream ), false ) .testStarting( expected ); - new ForkingRunListener( anotherPrintStream, anotherChannel, false ) + new ForkingRunListener( new ForkedChannelEncoder( anotherPrintStream ), false ) .testSkipped( secondExpected ); TestSetMockReporterFactory providerReporterFactory = new TestSetMockReporterFactory(); @@ -295,14 +267,19 @@ public void test2DifferentChannels() // Todo: Test weird characters + private SimpleReportEntry createDefaultReportEntry( Map sysProps ) + { + return new SimpleReportEntry( "com.abc.TestClass", null, "testMethod", null, null, 22, sysProps ); + } + private SimpleReportEntry createDefaultReportEntry() { - return new SimpleReportEntry( "com.abc.TestClass", "testMethod", 22 ); + return createDefaultReportEntry( Collections.emptyMap() ); } private SimpleReportEntry createAnotherDefaultReportEntry() { - return new SimpleReportEntry( "com.abc.AnotherTestClass", "testAnotherMethod", 42 ); + return new SimpleReportEntry( "com.abc.AnotherTestClass", null, "testAnotherMethod", null, 42 ); } private SimpleReportEntry createReportEntryWithStackTrace() @@ -333,9 +310,9 @@ private SimpleReportEntry createReportEntryWithSpecialMessage( String message ) } } - private RunListener createForkingRunListener( Integer testSetChannel ) + private RunListener createForkingRunListener() { - return new ForkingRunListener( printStream, testSetChannel, false ); + return new ForkingRunListener( new ForkedChannelEncoder( printStream ), false ); } private class StandardTestRun @@ -346,7 +323,7 @@ public RunListener run() throws ReporterException { reset(); - return createForkingRunListener( defaultChannel ); + return createForkingRunListener(); } public void clientReceiveContent() diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java index 5e71238b04..e44c10ba53 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/JarManifestForkConfigurationTest.java @@ -22,14 +22,18 @@ import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.net.URLDecoder; +import java.nio.charset.Charset; import java.nio.file.Path; import org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.ClasspathElementUri; import org.apache.maven.plugin.surefire.booterclient.output.InPluginProcessDumpSingleton; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.relativize; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.toAbsoluteUri; import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.toClasspathElementUri; +import static org.apache.maven.plugin.surefire.booterclient.JarManifestForkConfiguration.escapeUri; import static org.fest.assertions.Assertions.assertThat; import org.junit.AfterClass; @@ -39,7 +43,9 @@ import static org.fest.util.Files.delete; import static org.fest.util.Files.newTemporaryFolder; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.same; import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.mockStatic; @@ -47,6 +53,7 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -55,6 +62,7 @@ */ @RunWith( PowerMockRunner.class ) @PrepareForTest( { JarManifestForkConfiguration.class, InPluginProcessDumpSingleton.class } ) +@PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } ) public class JarManifestForkConfigurationTest { private static final File TMP = newTemporaryFolder(); @@ -88,6 +96,8 @@ public void relativeClasspathUnixSimple() .thenReturn( "../../../.m2/repository/grp/art/1.0/art-1.0.jar" ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "../../../.m2/repository/grp/art/1.0/art-1.0.jar" ); } @@ -105,6 +115,8 @@ public void relativeClasspathUnixTricky() .thenReturn( "../../../../../the Maven repo/grp/art/1.0/art-1.0.jar" ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "../../../../../the%20Maven%20repo/grp/art/1.0/art-1.0.jar" ); } @@ -122,6 +134,8 @@ public void relativeClasspathWindowsSimple() .thenReturn( "..\\..\\..\\Users\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "../../../Users/me/.m2/repository/grp/art/1.0/art-1.0.jar" ); } @@ -134,11 +148,14 @@ public void relativeClasspathWindowsTricky() Path parent = mock( Path.class ); when( parent.toString() ).thenReturn( "C:\\Windows\\Temp\\surefire" ); Path classPathElement = mock( Path.class ); - when( classPathElement.toString() ).thenReturn( "C:\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); + when( classPathElement.toString() ) + .thenReturn( "C:\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); when( relativize( parent, classPathElement ) ) .thenReturn( "..\\..\\..\\Test User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar" ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "../../../Test%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" ); } @@ -168,12 +185,55 @@ public URI answer( InvocationOnMock invocation ) throws URISyntaxException .thenThrow( new IllegalArgumentException() ); when( toClasspathElementUri( same( parent ), same( classPathElement ), same( dumpDirectory ), anyBoolean() ) ) .thenCallRealMethod(); + when( escapeUri( anyString(), any( Charset.class ) ) ) + .thenCallRealMethod(); when( toAbsoluteUri( same( classPathElement ) ) ) .thenCallRealMethod(); assertThat( toClasspathElementUri( parent, classPathElement, dumpDirectory, true ).uri ) .isEqualTo( "file:///X:/Users/me/.m2/repository/grp/art/1.0/art-1.0.jar" ); } + @Test + @SuppressWarnings( "checkstyle:magicnumber" ) + public void shouldEscapeUri() + throws Exception + { + assertThat( escapeUri( "a", UTF_8 ) ).isEqualTo( "a" ); + assertThat( escapeUri( " ", UTF_8 ) ).isEqualTo( "%20" ); + assertThat( escapeUri( "%", UTF_8 ) ).isEqualTo( "%25" ); + assertThat( escapeUri( "+", UTF_8 ) ).isEqualTo( "%2B" ); + assertThat( escapeUri( ",", UTF_8 ) ).isEqualTo( "%2C" ); + assertThat( escapeUri( "/", UTF_8 ) ).isEqualTo( "/" ); + assertThat( escapeUri( "7", UTF_8 ) ).isEqualTo( "7" ); + assertThat( escapeUri( ":", UTF_8 ) ).isEqualTo( "%3A" ); + assertThat( escapeUri( "@", UTF_8 ) ).isEqualTo( "%40" ); + assertThat( escapeUri( "A", UTF_8 ) ).isEqualTo( "A" ); + assertThat( escapeUri( "[", UTF_8 ) ).isEqualTo( "%5B" ); + assertThat( escapeUri( "\\", UTF_8 ) ).isEqualTo( "/" ); + assertThat( escapeUri( "]", UTF_8 ) ).isEqualTo( "%5D" ); + assertThat( escapeUri( "`", UTF_8 ) ).isEqualTo( "%60" ); + assertThat( escapeUri( "a", UTF_8 ) ).isEqualTo( "a" ); + assertThat( escapeUri( "{", UTF_8 ) ).isEqualTo( "%7B" ); + assertThat( escapeUri( "" + (char) 0xFF, UTF_8 ) ).isEqualTo( "%C3%BF" ); + + assertThat( escapeUri( "..\\..\\..\\Test : User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar", + UTF_8 ) ) + .isEqualTo( "../../../Test%20%3A%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" ); + + assertThat( escapeUri( "..\\..\\..\\Test : User\\me\\.m2\\repository\\grp\\art\\1.0\\art-1.0.jar", + Charset.defaultCharset() ) ) + .isEqualTo( "../../../Test%20%3A%20User/me/.m2/repository/grp/art/1.0/art-1.0.jar" ); + + assertThat( escapeUri( "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire", UTF_8 ) ) + .isEqualTo( "../../surefire-its/target/junit-pathWith%C3%9Cmlaut_1/target/surefire" ); + + String source = "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire"; + String encoded = escapeUri( "../../surefire-its/target/junit-pathWithÜmlaut_1/target/surefire", UTF_8 ); + String decoded = URLDecoder.decode( encoded, UTF_8.name() ); + assertThat( decoded ) + .isEqualTo( source ); + } + @Test public void shouldRelativizeOnRealPlatform() { @@ -218,6 +278,6 @@ public void shouldMakeRelativeUriOnRealPlatform() ClasspathElementUri testDirUriPath = toClasspathElementUri( parentDir, testDir, dumpDirectory, true ); assertThat( testDirUriPath.uri ) - .isEqualTo( "../@3%20test%20with%20white%20spaces" ); + .isEqualTo( "../%403%20test%20with%20white%20spaces" ); } } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockNotifiableTestStream.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockNotifiableTestStream.java index b98aca7470..c44b82d9a8 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockNotifiableTestStream.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockNotifiableTestStream.java @@ -20,7 +20,7 @@ */ import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.NotifiableTestStream; -import org.apache.maven.surefire.booter.*; +import org.apache.maven.surefire.booter.Shutdown; /** * Mock of {@link NotifiableTestStream} for testing purposes. diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java index 2c9612f3a4..fdd9110d67 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/MockReporter.java @@ -24,6 +24,7 @@ import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.TestSetReportEntry; +import org.apache.maven.surefire.report.RunMode; import java.util.ArrayList; import java.util.List; @@ -55,7 +56,13 @@ public class MockReporter public static final String TEST_ASSUMPTION_FAIL = "TEST_ASSUMPTION_SKIPPED"; - public static final String CONSOLE_OUTPUT = "CONSOLE_OUTPUT"; + public static final String CONSOLE_INFO = "CONSOLE_INFO"; + + public static final String CONSOLE_WARN = "CONSOLE_WARN"; + + public static final String CONSOLE_DEBUG = "CONSOLE_DEBUG"; + + public static final String CONSOLE_ERR = "CONSOLE_ERR"; public static final String STDOUT = "STDOUT"; @@ -125,6 +132,12 @@ public void testExecutionSkippedByUser() { } + @Override + public RunMode markAs( RunMode currentRunMode ) + { + return null; + } + public void testSkippedByUser( ReportEntry report ) { testSkipped( report ); @@ -167,7 +180,7 @@ public boolean isDebugEnabled() @Override public void debug( String message ) { - events.add( CONSOLE_OUTPUT ); + events.add( CONSOLE_DEBUG ); data.add( message ); } @@ -180,7 +193,7 @@ public boolean isInfoEnabled() @Override public void info( String message ) { - events.add( CONSOLE_OUTPUT ); + events.add( CONSOLE_INFO ); data.add( message ); } @@ -193,7 +206,7 @@ public boolean isWarnEnabled() @Override public void warning( String message ) { - events.add( CONSOLE_OUTPUT ); + events.add( CONSOLE_WARN ); data.add( message ); } @@ -206,24 +219,26 @@ public boolean isErrorEnabled() @Override public void error( String message ) { - events.add( CONSOLE_OUTPUT ); + events.add( CONSOLE_ERR ); data.add( message ); } @Override public void error( String message, Throwable t ) { + error( message ); } @Override public void error( Throwable t ) { + error( t.getLocalizedMessage() ); } @Override - public void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) + public void writeTestOutput( String output, boolean newLine, boolean stdout ) { events.add( stdout ? STDOUT : STDERR ); - data.add( new String( buf, off, len ) ); + data.add( newLine ? output + "\n" : output ); } } 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 d129df384f..a9077fe088 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 @@ -29,10 +29,9 @@ import org.apache.maven.surefire.booter.StartupConfiguration; import org.junit.Test; -import javax.annotation.Nonnull; import java.io.File; import java.util.Collection; -import java.util.HashMap; +import java.util.Collections; import java.util.List; import java.util.Properties; @@ -45,6 +44,7 @@ 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; /** @@ -64,16 +64,9 @@ public void shouldCreateModularArgsFile() throws Exception File pwd = new File( "." ).getCanonicalFile(); ModularClasspathForkConfiguration config = new ModularClasspathForkConfiguration( booter, tmp, "", pwd, - new Properties(), "", new HashMap(), true, 1, true, new Platform(), - new NullConsoleLogger() ) - { - @Nonnull - @Override - String toModuleName( @Nonnull File moduleDescriptor ) - { - return "abc"; - } - }; + new Properties(), "", + Collections.emptyMap(), new String[0], true, 1, true, + new Platform(), new NullConsoleLogger() ); File patchFile = new File( "target" + separatorChar + "test-classes" ); File descriptor = new File( tmp, "module-info.class" ); @@ -85,7 +78,7 @@ String toModuleName( @Nonnull File moduleDescriptor ) String startClassName = ForkedBooter.class.getName(); File jigsawArgsFile = - config.createArgsFile( descriptor, modulePath, classPath, packages, patchFile, startClassName ); + config.createArgsFile( "abc", modulePath, classPath, packages, patchFile, startClassName ); assertThat( jigsawArgsFile ) .isNotNull(); @@ -141,15 +134,15 @@ String toModuleName( @Nonnull File moduleDescriptor ) assertThat( argsFileLines.get( 12 ) ) .isEqualTo( ForkedBooter.class.getName() ); - ModularClasspath modularClasspath = new ModularClasspath( descriptor, modulePath, packages, patchFile ); + ModularClasspath modularClasspath = new ModularClasspath( "abc", modulePath, packages, patchFile ); Classpath testClasspathUrls = new Classpath( singleton( "target" + separator + "test-classes" ) ); 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 ); + new StartupConfiguration( "JUnitCoreProvider", modularClasspathConfiguration, clc, true, true, null ); OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline(); config.resolveClasspath( cli, ForkedBooter.class.getName(), startupConfiguration, createTempFile( "surefire", "surefire-reports" ) ); diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java index 0ab24b9e6a..3770fa068b 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/TestSetMockReporterFactory.java @@ -20,6 +20,9 @@ */ import org.apache.maven.plugin.surefire.StartupReportConfiguration; +import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; import org.apache.maven.plugin.surefire.report.DefaultReporterFactory; import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger; import org.apache.maven.surefire.report.RunListener; @@ -55,7 +58,8 @@ private static StartupReportConfiguration defaultValue() { File target = new File( "./target" ); File statisticsFile = new File( target, "TESTHASH" ); - return new StartupReportConfiguration( true, true, "PLAIN", false, false, target, false, null, statisticsFile, - false, 0, null, null, true ); + return new StartupReportConfiguration( true, true, "PLAIN", false, target, false, null, statisticsFile, + false, 0, null, null, true, new SurefireStatelessReporter(), new SurefireConsoleOutputReporter(), + new SurefireStatelessTestsetInfoReporter() ); } } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushableCommandlineTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushableCommandlineTest.java new file mode 100644 index 0000000000..3cd0fb83cc --- /dev/null +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/OutputStreamFlushableCommandlineTest.java @@ -0,0 +1,132 @@ +package org.apache.maven.plugin.surefire.booterclient.lazytestprovider; + +/* + * 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.shared.utils.cli.CommandLineException; +import org.fest.assertions.Condition; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.verifyZeroInteractions; + +/** + * + */ +public class OutputStreamFlushableCommandlineTest +{ + + @Test + public void shouldGetEnvironmentVariables() + { + OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline(); + String[] env = cli.getEnvironmentVariables(); + + assertThat( env ) + .doesNotHaveDuplicates() + .satisfies( new ContainsAnyStartsWith( "JAVA_HOME=" ) ); + + String[] excluded = { "JAVA_HOME" }; + cli = new OutputStreamFlushableCommandline( excluded ); + env = cli.getEnvironmentVariables(); + + assertThat( env ) + .doesNotHaveDuplicates() + .satisfies( new NotContainsAnyStartsWith( "JAVA_HOME=" ) ); + } + + @Test + public void shouldExecute() throws CommandLineException + { + OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline(); + cli.getShell().setWorkingDirectory( System.getProperty( "user.dir" ) ); + cli.getShell().setExecutable( IS_OS_WINDOWS ? "dir" : "ls" ); + assertThat( cli.getFlushReceiver() ).isNull(); + cli.execute(); + assertThat( cli.getFlushReceiver() ).isNotNull(); + } + + @Test + public void shouldGetFlushReceiver() + { + OutputStreamFlushableCommandline cli = new OutputStreamFlushableCommandline(); + assertThat( cli.getFlushReceiver() ).isNull(); + } + + @Test + public void shouldFlush() throws IOException + { + ByteArrayOutputStream os = mock( ByteArrayOutputStream.class ); + OutputStreamFlushReceiver flushReceiver = new OutputStreamFlushReceiver( os ); + verifyZeroInteractions( os ); + flushReceiver.flush(); + verify( os, times( 1 ) ).flush(); + } + + private static final class ContainsAnyStartsWith extends Condition + { + private final String expected; + + ContainsAnyStartsWith( String expected ) + { + this.expected = expected; + } + + @Override + public boolean matches( Object[] values ) + { + boolean matches = false; + for ( Object value : values ) + { + assertThat( value ).isInstanceOf( String.class ); + matches |= ( (String) value ).startsWith( expected ); + } + return matches; + } + } + + private static final class NotContainsAnyStartsWith extends Condition + { + private final String expected; + + NotContainsAnyStartsWith( String expected ) + { + this.expected = expected; + } + + @Override + public boolean matches( Object[] values ) + { + boolean matches = false; + for ( Object value : values ) + { + assertThat( value ).isInstanceOf( String.class ); + matches |= ( (String) value ).startsWith( expected ); + } + return !matches; + } + } +} diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java index d120638264..21bc6631ea 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/lazytestprovider/TestProvidingInputStreamTest.java @@ -35,7 +35,8 @@ import static org.apache.maven.surefire.booter.MasterProcessCommand.BYE_ACK; import static org.apache.maven.surefire.booter.MasterProcessCommand.decode; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; /** * Asserts that this stream properly reads bytes from queue. diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClientTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClientTest.java new file mode 100644 index 0000000000..09230bb90c --- /dev/null +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkClientTest.java @@ -0,0 +1,2134 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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.plugin.surefire.booterclient.MockReporter; +import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.NotifiableTestStream; +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.plugin.surefire.report.DefaultReporterFactory; +import org.apache.maven.surefire.booter.Shutdown; +import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.SafeThrowable; +import org.apache.maven.surefire.report.StackTraceWriter; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicBoolean; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Arrays.copyOfRange; +import static org.apache.commons.codec.binary.Base64.encodeBase64String; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.CONSOLE_DEBUG; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.CONSOLE_ERR; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.CONSOLE_WARN; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.CONSOLE_INFO; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.SET_COMPLETED; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.SET_STARTING; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.STDOUT; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.STDERR; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.TEST_ASSUMPTION_FAIL; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.TEST_ERROR; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.TEST_FAILED; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.TEST_STARTING; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.TEST_SKIPPED; +import static org.apache.maven.plugin.surefire.booterclient.MockReporter.TEST_SUCCEEDED; +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.MapAssert.entry; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.startsWith; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +/** + * Test for {@link ForkClient}. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class ForkClientTest +{ + private static final int ELAPSED_TIME = 102; + + @Test + public void shouldNotFailOnEmptyInput1() + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, null, logger, printedErrorStream, 0 ); + client.consumeLine( null ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldNotFailOnEmptyInput2() + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, null, logger, printedErrorStream, 0 ); + client.consumeLine( " " ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldNotFailOnEmptyInput3() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, null, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( null ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldNotFailOnEmptyInput4() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + when( logger.isDebugEnabled() ) + .thenReturn( true ); + ForkClient client = new ForkClient( factory, null, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( " " ); + verify( logger ) + .isDebugEnabled(); + verify( logger ) + .warning( startsWith( "Corrupted STDOUT by directly writing to native stream in forked JVM 0. " + + "See FAQ web page and the dump file " ) ); + verify( logger ) + .debug( " " ); + verifyNoMoreInteractions( logger ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldNotFailOnEmptyInput5() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + when( logger.isDebugEnabled() ) + .thenReturn( true ); + ForkClient client = new ForkClient( factory, null, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( "Listening for transport dt_socket at address: bla" ); + verify( logger ) + .isDebugEnabled(); + verify( logger ) + .debug( "Listening for transport dt_socket at address: bla" ); + verifyNoMoreInteractions( logger ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldNotFailOnEmptyInput6() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + when( logger.isDebugEnabled() ) + .thenReturn( false ); + when( logger.isInfoEnabled() ) + .thenReturn( true ); + ForkClient client = new ForkClient( factory, null, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( "Listening for transport dt_socket at address: bla" ); + verify( logger ) + .isDebugEnabled(); + verify( logger ) + .isInfoEnabled(); + verify( logger ) + .info( "Listening for transport dt_socket at address: bla" ); + verifyNoMoreInteractions( logger ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldBePossibleToKill() + { + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + + ForkClient client = new ForkClient( null, notifiableTestStream, null, null, 0 ); + client.kill(); + + verify( notifiableTestStream, times( 1 ) ) + .shutdown( eq( Shutdown.KILL ) ); + } + + @Test + public void shouldAcquireNextTest() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:next-test\n" ); + verify( notifiableTestStream, times( 1 ) ) + .provideNewTest(); + verifyNoMoreInteractions( notifiableTestStream ); + verifyZeroInteractions( factory ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldNotifyWithBye() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:bye\n" ); + client.kill(); + + verify( notifiableTestStream, times( 1 ) ) + .acknowledgeByeEventReceived(); + verify( notifiableTestStream, never() ) + .shutdown( any( Shutdown.class ) ); + verifyNoMoreInteractions( notifiableTestStream ); + verifyZeroInteractions( factory ); + assertThat( client.isSaidGoodBye() ) + .isTrue(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldStopOnNextTest() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + final boolean[] verified = {false}; + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ) + { + @Override + protected void stopOnNextTest() + { + super.stopOnNextTest(); + verified[0] = true; + } + }; + client.consumeMultiLineContent( ":maven:surefire:std:out:stop-on-next-test\n" ); + verifyZeroInteractions( notifiableTestStream ); + verifyZeroInteractions( factory ); + assertThat( verified[0] ) + .isTrue(); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldReceiveStdOut() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:std-out-stream:normal-run:UTF-8:bXNn\n" ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ) + .contains( STDOUT ); + assertThat( receiver.getData() ) + .hasSize( 1 ) + .contains( "msg" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldReceiveStdOutNewLine() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:std-out-stream-new-line:normal-run:UTF-8:bXNn\n" ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ) + .contains( STDOUT ); + assertThat( receiver.getData() ) + .hasSize( 1 ) + .contains( "msg\n" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldReceiveStdErr() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:std-err-stream:normal-run:UTF-8:bXNn\n" ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ) + .contains( STDERR ); + assertThat( receiver.getData() ) + .hasSize( 1 ) + .contains( "msg" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldReceiveStdErrNewLine() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:std-err-stream-new-line:normal-run:UTF-8:bXNn\n" ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ) + .contains( STDERR ); + assertThat( receiver.getData() ) + .hasSize( 1 ) + .contains( "msg\n" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldLogConsoleError() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:console-error-log:UTF-8:" + + encodeBase64String( "Listening for transport dt_socket at address:".getBytes( UTF_8 ) ) + + ":-:-:-" ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verify( factory, times( 1 ) ) + .getReportsDirectory(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .isNotEmpty(); + assertThat( receiver.getEvents() ) + .contains( CONSOLE_ERR ); + assertThat( receiver.getData() ) + .isNotEmpty(); + assertThat( receiver.getData() ) + .contains( "Listening for transport dt_socket at address:" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldLogConsoleErrorWithStackTrace() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:console-error-log:UTF-8" + + ":" + encodeBase64String( "Listening for transport dt_socket at address:".getBytes( UTF_8 ) ) + + ":" + encodeBase64String( "s1".getBytes( UTF_8 ) ) + + ":" + encodeBase64String( "s2".getBytes( UTF_8 ) ) ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verify( factory, times( 1 ) ) + .getReportsDirectory(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .isNotEmpty(); + assertThat( receiver.getEvents() ) + .contains( CONSOLE_ERR ); + assertThat( receiver.getData() ) + .isNotEmpty(); + assertThat( receiver.getData() ) + .contains( "Listening for transport dt_socket at address:" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isTrue(); + assertThat( client.getErrorInFork() ) + .isNotNull(); + assertThat( client.getErrorInFork().getThrowable().getLocalizedMessage() ) + .isEqualTo( "Listening for transport dt_socket at address:" ); + assertThat( client.getErrorInFork().smartTrimmedStackTrace() ) + .isEqualTo( "s1" ); + assertThat( client.getErrorInFork().writeTrimmedTraceToString() ) + .isEqualTo( "s2" ); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldLogConsoleWarning() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + when( logger.isWarnEnabled() ) + .thenReturn( true ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:console-warning-log:UTF-8:" + + encodeBase64String( "s1".getBytes( UTF_8 ) ) ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ) + .contains( CONSOLE_WARN ); + assertThat( receiver.getData() ) + .hasSize( 1 ) + .contains( "s1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldLogConsoleDebug() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + when( logger.isDebugEnabled() ) + .thenReturn( true ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:console-debug-log:UTF-8:" + + encodeBase64String( "s1".getBytes( UTF_8 ) ) ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ) + .contains( CONSOLE_DEBUG ); + assertThat( receiver.getData() ) + .hasSize( 1 ) + .contains( "s1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldLogConsoleInfo() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:console-info-log:UTF-8:" + + encodeBase64String( "s1".getBytes( UTF_8 ) ) ); + verifyZeroInteractions( notifiableTestStream ); + verify( factory, times( 1 ) ) + .createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ) + .contains( CONSOLE_INFO ); + assertThat( receiver.getData() ) + .hasSize( 1 ) + .contains( "s1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldSendSystemProperty() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:sys-prop:normal-run:UTF-8:azE=:djE=" + + encodeBase64String( "s1".getBytes( UTF_8 ) ) ); + verifyZeroInteractions( notifiableTestStream ); + verifyZeroInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .isEmpty(); + assertThat( receiver.getData() ) + .isEmpty(); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .hasSize( 1 ); + assertThat( client.getTestVmSystemProperties() ) + .includes( entry( "k1", "v1" ) ); + } + + @Test + public void shouldSendTestsetStartingKilled() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:testset-starting:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace ); + + client.tryToTimeout( System.currentTimeMillis() + 1000L, 1 ); + + verify( notifiableTestStream ) + .shutdown( Shutdown.KILL ); + verifyNoMoreInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ); + assertThat( receiver.getEvents() ) + .contains( SET_STARTING ); + assertThat( receiver.getData() ) + .hasSize( 1 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getNameText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isTrue(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + } + + @Test + public void shouldSendTestsetStarting() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameText() ).thenReturn( "dn2" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getSourceText() ).thenReturn( "dn1" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedSourceText = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceText() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedNameText = encodeBase64String( toArray( UTF_8.encode( reportEntry.getNameText() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:testset-starting:normal-run:UTF-8:" + + encodedSourceName + + ":" + + encodedSourceText + + ":" + + encodedName + + ":" + + encodedNameText + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace ); + + client.tryToTimeout( System.currentTimeMillis(), 1 ); + + verifyZeroInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ); + assertThat( receiver.getEvents() ) + .contains( SET_STARTING ); + assertThat( receiver.getData() ) + .hasSize( 1 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isEqualTo( "dn1" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getNameText() ) + .isEqualTo( "dn2" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getDefaultReporterFactory() ) + .isSameAs( factory ); + } + + @Test + public void shouldSendTestsetCompleted() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:testset-completed:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace ); + + verifyZeroInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ); + assertThat( receiver.getEvents() ) + .contains( SET_COMPLETED ); + assertThat( receiver.getData() ) + .hasSize( 1 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getNameText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getDefaultReporterFactory() ) + .isSameAs( factory ); + } + + @Test + public void shouldSendTestStarting() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + client.consumeMultiLineContent( ":maven:surefire:std:out:test-starting:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace ); + + verifyZeroInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.hasTestsInProgress() ) + .isTrue(); + assertThat( client.testsInProgress() ) + .hasSize( 1 ) + .contains( "pkg.MyTest" ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 1 ); + assertThat( receiver.getEvents() ) + .contains( TEST_STARTING ); + assertThat( receiver.getData() ) + .hasSize( 1 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getNameText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getDefaultReporterFactory() ) + .isSameAs( factory ); + } + + @Test + public void shouldSendTestSucceeded() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-starting:normal-run:UTF-8:" + + encodedSourceName + + ":-:-:-:-:-:-:-:-:-" ); + + assertThat( client.testsInProgress() ) + .hasSize( 1 ) + .contains( "pkg.MyTest" ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-succeeded:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace ); + + verifyZeroInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 2 ); + assertThat( receiver.getEvents() ) + .contains( TEST_STARTING, TEST_SUCCEEDED ); + assertThat( receiver.getData() ) + .hasSize( 2 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getNameText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1\ntrace line 2" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1\ntrace line 2" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getDefaultReporterFactory() ) + .isSameAs( factory ); + } + + @Test + public void shouldSendTestFailed() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-starting:normal-run:UTF-8:" + + encodedSourceName + + ":-:-:-:-:-:-:-:-:-" ); + + assertThat( client.testsInProgress() ) + .hasSize( 1 ) + .contains( "pkg.MyTest" ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-failed:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace ); + + verifyZeroInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 2 ); + assertThat( receiver.getEvents() ) + .contains( TEST_STARTING, TEST_FAILED ); + assertThat( receiver.getData() ) + .hasSize( 2 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getNameText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getNameText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getDefaultReporterFactory() ) + .isSameAs( factory ); + } + + @Test + public void shouldSendTestSkipped() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-starting:normal-run:UTF-8:" + + encodedSourceName + + ":-:-:-:-:-:-:-:-:-" ); + + assertThat( client.testsInProgress() ) + .hasSize( 1 ) + .contains( "pkg.MyTest" ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-skipped:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace ); + + verifyZeroInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 2 ); + assertThat( receiver.getEvents() ) + .contains( TEST_STARTING, TEST_SKIPPED ); + assertThat( receiver.getData() ) + .hasSize( 2 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getNameText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getNameText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1\ntrace line 2" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1\ntrace line 2" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getDefaultReporterFactory() ) + .isSameAs( factory ); + } + + @Test + public void shouldSendTestError() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getSourceText() ).thenReturn( "display name" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedSourceText = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceText() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-starting:normal-run:UTF-8:" + + encodedSourceName + + ":" + + encodedSourceText + + ":-:':-:-:-:-:-:-" ); + + assertThat( client.testsInProgress() ) + .hasSize( 1 ) + .contains( "pkg.MyTest" ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-error:normal-run:UTF-8:" + + encodedSourceName + + ":" + + encodedSourceText + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace ); + + verifyZeroInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 2 ); + assertThat( receiver.getEvents() ) + .contains( TEST_STARTING, TEST_ERROR ); + assertThat( receiver.getData() ) + .hasSize( 2 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isEqualTo( "display name" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getSourceText() ) + .isEqualTo( "display name" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getDefaultReporterFactory() ) + .isSameAs( factory ); + } + + @Test + public void shouldSendTestAssumptionFailure() + throws IOException + { + String cwd = System.getProperty( "user.dir" ); + File target = new File( cwd, "target" ); + DefaultReporterFactory factory = mock( DefaultReporterFactory.class ); + when( factory.getReportsDirectory() ) + .thenReturn( new File( target, "surefire-reports" ) ); + MockReporter receiver = new MockReporter(); + when( factory.createReporter() ) + .thenReturn( receiver ); + NotifiableTestStream notifiableTestStream = mock( NotifiableTestStream.class ); + AtomicBoolean printedErrorStream = new AtomicBoolean(); + ConsoleLogger logger = mock( ConsoleLogger.class ); + + + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "some test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameText() ).thenReturn( "display name" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedText = encodeBase64String( toArray( UTF_8.encode( reportEntry.getNameText() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ForkClient client = new ForkClient( factory, notifiableTestStream, logger, printedErrorStream, 0 ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-starting:normal-run:UTF-8:" + + encodedSourceName + + ":-:-:-:-:-:-:-:-:-" ); + + assertThat( client.testsInProgress() ) + .hasSize( 1 ) + .contains( "pkg.MyTest" ); + + client.consumeMultiLineContent( ":maven:surefire:std:out:test-assumption-failure:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + encodedText + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace ); + + verifyZeroInteractions( notifiableTestStream ); + verify( factory ).createReporter(); + verifyNoMoreInteractions( factory ); + assertThat( client.getReporter() ) + .isNotNull(); + assertThat( receiver.getEvents() ) + .hasSize( 2 ); + assertThat( receiver.getEvents() ) + .contains( TEST_STARTING, TEST_ASSUMPTION_FAIL ); + assertThat( receiver.getData() ) + .hasSize( 2 ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getSourceText() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 0 ) ).getName() ) + .isNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getSourceName() ) + .isEqualTo( "pkg.MyTest" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getName() ) + .isEqualTo( "my test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getNameText() ) + .isEqualTo( "display name" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getElapsed() ) + .isEqualTo( ELAPSED_TIME ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getMessage() ) + .isEqualTo( "some test" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getGroup() ) + .isEqualTo( "this group" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter() ) + .isNotNull(); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ) + .getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( "msg" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( "MyTest:86 >> Error" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTraceToString() ) + .isEqualTo( "trace line 1\ntrace line 2" ); + assertThat( ( (ReportEntry) receiver.getData().get( 1 ) ).getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( "trace line 1\ntrace line 2" ); + assertThat( client.isSaidGoodBye() ) + .isFalse(); + assertThat( client.isErrorInFork() ) + .isFalse(); + assertThat( client.getErrorInFork() ) + .isNull(); + assertThat( client.hadTimeout() ) + .isFalse(); + assertThat( client.hasTestsInProgress() ) + .isFalse(); + assertThat( client.testsInProgress() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getTestVmSystemProperties() ) + .isEmpty(); + assertThat( client.getDefaultReporterFactory() ) + .isSameAs( factory ); + } + + private static byte[] toArray( ByteBuffer buffer ) + { + return copyOfRange( buffer.array(), buffer.arrayOffset(), buffer.arrayOffset() + buffer.remaining() ); + } + +} diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoderTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoderTest.java new file mode 100644 index 0000000000..42dd636030 --- /dev/null +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/output/ForkedChannelDecoderTest.java @@ -0,0 +1,864 @@ +package org.apache.maven.plugin.surefire.booterclient.output; + +/* + * 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.plugin.surefire.log.api.ConsoleLoggerUtils; +import org.apache.maven.surefire.booter.ForkedChannelEncoder; +import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.RunMode; +import org.apache.maven.surefire.report.SafeThrowable; +import org.apache.maven.surefire.report.StackTraceWriter; +import org.apache.maven.surefire.util.internal.ObjectUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.experimental.theories.DataPoints; +import org.junit.experimental.theories.FromDataPoints; +import org.junit.experimental.theories.Theories; +import org.junit.experimental.theories.Theory; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.PrintStream; +import java.io.StringReader; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Map; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.codec.binary.Base64.encodeBase64String; +import static org.apache.maven.plugin.surefire.booterclient.output.ForkedChannelDecoder.toReportEntry; +import static org.apache.maven.surefire.report.RunMode.NORMAL_RUN; +import static org.fest.assertions.Assertions.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.rules.ExpectedException.none; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.nullable; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +/** + * Test for {@link ForkedChannelDecoder}. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +@RunWith( Enclosed.class ) +public class ForkedChannelDecoderTest +{ + /** + * + */ + public static class DecoderOperationsTest + { + @Rule + public final ExpectedException rule = none(); + + @Test + public void shouldBeFailSafe() + { + assertThat( ForkedChannelDecoder.decode( null, UTF_8 ) ).isNull(); + assertThat( ForkedChannelDecoder.decode( "-", UTF_8 ) ).isNull(); + assertThat( ForkedChannelDecoder.decodeToInteger( null ) ).isNull(); + assertThat( ForkedChannelDecoder.decodeToInteger( "-" ) ).isNull(); + } + + @Test + @SuppressWarnings( "checkstyle:innerassignment" ) + public void shouldHaveSystemProperty() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.sendSystemProperties( ObjectUtils.systemProps() ); + + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setSystemPropertiesListener( new PropertyEventAssertionListener() ); + LineNumberReader reader = out.newReader( UTF_8 ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + for ( String line; ( line = reader.readLine() ) != null; ) + { + decoder.handleEvent( line, errorHandler ); + } + verifyZeroInteractions( errorHandler ); + assertThat( reader.getLineNumber() ).isPositive(); + } + + @Test + public void shouldRecognizeEmptyStream4ReportEntry() + { + ReportEntry reportEntry = toReportEntry( null, null, null, "", "", null, null, "", + "", "", null ); + assertThat( reportEntry ).isNull(); + + reportEntry = toReportEntry( UTF_8, "", "", "", "", "", "", "-", "", "", "" ); + assertThat( reportEntry ).isNotNull(); + assertThat( reportEntry.getStackTraceWriter() ).isNull(); + assertThat( reportEntry.getSourceName() ).isEmpty(); + assertThat( reportEntry.getSourceText() ).isEmpty(); + assertThat( reportEntry.getName() ).isEmpty(); + assertThat( reportEntry.getNameText() ).isEmpty(); + assertThat( reportEntry.getGroup() ).isEmpty(); + assertThat( reportEntry.getNameWithGroup() ).isEmpty(); + assertThat( reportEntry.getMessage() ).isEmpty(); + assertThat( reportEntry.getElapsed() ).isNull(); + + rule.expect( NumberFormatException.class ); + toReportEntry( UTF_8, "", "", "", "", "", "", "", "", "", "" ); + fail(); + } + + @Test + @SuppressWarnings( "checkstyle:magicnumber" ) + public void testCreatingReportEntry() + { + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "Exception: msg\ntrace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1\ntrace line 2"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( exceptionMessage ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( 102 ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameText() ).thenReturn( "my display name" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getSourceText() ).thenReturn( "test class display name" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedSourceText = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceText() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedText = encodeBase64String( toArray( UTF_8.encode( reportEntry.getNameText() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + ReportEntry decodedReportEntry = toReportEntry( UTF_8, encodedSourceName, encodedSourceText, + encodedName, encodedText, encodedGroup, encodedMessage, "-", null, null, null ); + + assertThat( decodedReportEntry ).isNotNull(); + assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); + assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); + assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); + assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); + assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); + assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); + assertThat( decodedReportEntry.getStackTraceWriter() ).isNull(); + + decodedReportEntry = toReportEntry( UTF_8, encodedSourceName, encodedSourceText, encodedName, encodedText, + encodedGroup, encodedMessage, "-", encodedExceptionMsg, encodedSmartStackTrace, null ); + + assertThat( decodedReportEntry ).isNotNull(); + assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); + assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); + assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); + assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); + assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); + assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); + assertThat( decodedReportEntry.getElapsed() ).isNull(); + assertThat( decodedReportEntry.getStackTraceWriter() ).isNull(); + + decodedReportEntry = toReportEntry( UTF_8, encodedSourceName, encodedSourceText, encodedName, encodedText, + encodedGroup, encodedMessage, "1003", encodedExceptionMsg, encodedSmartStackTrace, null ); + + assertThat( decodedReportEntry ).isNotNull(); + assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); + assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); + assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); + assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); + assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); + assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); + assertThat( decodedReportEntry.getElapsed() ).isEqualTo( 1003 ); + assertThat( decodedReportEntry.getStackTraceWriter() ).isNull(); + + decodedReportEntry = toReportEntry( UTF_8, encodedSourceName, encodedSourceText, encodedName, encodedText, + encodedGroup, encodedMessage, "1003", encodedExceptionMsg, encodedSmartStackTrace, + encodedStackTrace ); + + assertThat( decodedReportEntry ).isNotNull(); + assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); + assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); + assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); + assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); + assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); + assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); + assertThat( decodedReportEntry.getElapsed() ).isEqualTo( 1003 ); + assertThat( decodedReportEntry.getStackTraceWriter() ).isNotNull(); + assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ).isNotNull(); + assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ) + .isEqualTo( exceptionMessage ); + assertThat( decodedReportEntry.getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( smartStackTrace ); + assertThat( decodedReportEntry.getStackTraceWriter().writeTraceToString() ).isEqualTo( stackTrace ); + assertThat( decodedReportEntry.getStackTraceWriter().writeTrimmedTraceToString() ).isEqualTo( stackTrace ); + + decodedReportEntry = toReportEntry( UTF_8, encodedSourceName, encodedSourceText, encodedName, encodedText, + encodedGroup, encodedMessage, "1003", encodedExceptionMsg, encodedSmartStackTrace, + encodedTrimmedStackTrace ); + + assertThat( decodedReportEntry ).isNotNull(); + assertThat( decodedReportEntry.getSourceName() ).isEqualTo( reportEntry.getSourceName() ); + assertThat( decodedReportEntry.getSourceText() ).isEqualTo( reportEntry.getSourceText() ); + assertThat( decodedReportEntry.getName() ).isEqualTo( reportEntry.getName() ); + assertThat( decodedReportEntry.getNameText() ).isEqualTo( reportEntry.getNameText() ); + assertThat( decodedReportEntry.getGroup() ).isEqualTo( reportEntry.getGroup() ); + assertThat( decodedReportEntry.getMessage() ).isEqualTo( reportEntry.getMessage() ); + assertThat( decodedReportEntry.getElapsed() ).isEqualTo( 1003 ); + assertThat( decodedReportEntry.getStackTraceWriter() ).isNotNull(); + assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ).isNotNull(); + assertThat( decodedReportEntry.getStackTraceWriter().getThrowable().getMessage() ) + .isEqualTo( exceptionMessage ); + assertThat( decodedReportEntry.getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( smartStackTrace ); + assertThat( decodedReportEntry.getStackTraceWriter().writeTraceToString() ).isEqualTo( trimmedStackTrace ); + assertThat( decodedReportEntry.getStackTraceWriter().writeTrimmedTraceToString() ) + .isEqualTo( trimmedStackTrace ); + } + + @Test + public void shouldSendByeEvent() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.bye(); + String read = new String( out.toByteArray(), UTF_8 ); + assertThat( read ) + .isEqualTo( ":maven:surefire:std:out:bye\n" ); + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setByeListener( new EventAssertionListener() ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void shouldSendStopOnNextTestEvent() throws IOException + { + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.stopOnNextTest(); + String read = new String( out.toByteArray(), UTF_8 ); + assertThat( read ) + .isEqualTo( ":maven:surefire:std:out:stop-on-next-test\n" ); + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setStopOnNextTestListener( new EventAssertionListener() ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void shouldSendNextTestEvent() throws IOException + { + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.acquireNextTest(); + String read = new String( out.toByteArray(), UTF_8 ); + assertThat( read ) + .isEqualTo( ":maven:surefire:std:out:next-test\n" ); + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setAcquireNextTestListener( new EventAssertionListener() ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testConsole() throws IOException + { + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.consoleInfoLog( "msg" ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setConsoleInfoListener( new StringEventAssertionListener( "msg" ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testError() throws IOException + { + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.consoleErrorLog( "msg" ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setConsoleErrorListener( new StackTraceEventListener( "msg", null, null ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testErrorWithException() throws IOException + { + Throwable t = new Throwable( "msg" ); + + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.consoleErrorLog( t ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + String stackTrace = ConsoleLoggerUtils.toString( t ); + decoder.setConsoleErrorListener( new StackTraceEventListener( "msg", null, stackTrace ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testErrorWithStackTraceWriter() throws IOException + { + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + StackTraceWriter stackTraceWriter = new DeserializedStacktraceWriter( "1", "2", "3" ); + forkedChannelEncoder.consoleErrorLog( stackTraceWriter, false ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setConsoleErrorListener( new StackTraceEventListener( "1", "2", "3" ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testDebug() throws IOException + { + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.consoleDebugLog( "msg" ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setConsoleDebugListener( new StringEventAssertionListener( "msg" ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testWarning() throws IOException + { + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.consoleWarningLog( "msg" ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setConsoleWarningListener( new StringEventAssertionListener( "msg" ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testStdOutStream() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.stdOut( "msg", false ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setStdOutListener( new StandardOutErrEventAssertionListener( NORMAL_RUN, "msg", false ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testStdOutStreamPrint() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.stdOut( "", false ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setStdOutListener( new StandardOutErrEventAssertionListener( NORMAL_RUN, "", false ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testStdOutStreamPrintWithNull() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.stdOut( null, false ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setStdOutListener( new StandardOutErrEventAssertionListener( NORMAL_RUN, null, false ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testStdOutStreamPrintln() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.stdOut( "", true ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setStdOutListener( new StandardOutErrEventAssertionListener( NORMAL_RUN, "", true ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testStdOutStreamPrintlnWithNull() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.stdOut( null, true ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setStdOutListener( new StandardOutErrEventAssertionListener( NORMAL_RUN, null, true ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void testStdErrStream() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.stdErr( "msg", false ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setStdErrListener( new StandardOutErrEventAssertionListener( NORMAL_RUN, "msg", false ) ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + assertThat( lines.readLine() ) + .isNull(); + } + + @Test + public void shouldCountSameNumberOfSystemProperties() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + forkedChannelEncoder.sendSystemProperties( ObjectUtils.systemProps() ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setSystemPropertiesListener( new PropertyEventAssertionListener() ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + } + + @Test + public void shouldHandleErrorAfterNullLine() + { + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setSystemPropertiesListener( new PropertyEventAssertionListener() ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( null, errorHandler ); + verify( errorHandler, times( 1 ) ) + .handledError( nullable( String.class ), nullable( Throwable.class ) ); + } + + @Test + public void shouldHandleErrorAfterUnknownOperation() + { + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setSystemPropertiesListener( new PropertyEventAssertionListener() ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( ":maven:surefire:std:out:abnormal-run:-", errorHandler ); + verify( errorHandler, times( 1 ) ) + .handledError( eq( ":maven:surefire:std:out:abnormal-run:-" ), nullable( Throwable.class ) ); + } + + @Test + public void shouldHandleExit() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( new SafeThrowable( "1" ) ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( "2" ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( "3" ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( "4" ); + forkedChannelEncoder.sendExitEvent( stackTraceWriter, false ); + + LineNumberReader lines = out.newReader( UTF_8 ); + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + decoder.setExitErrorEventListener( new ForkedProcessExitErrorListener() + { + @Override + public void handle( String exceptionMessage, String smartTrimmedStackTrace, String stackTrace ) + { + assertThat( exceptionMessage ).isEqualTo( "1" ); + assertThat( smartTrimmedStackTrace ).isEqualTo( "2" ); + assertThat( stackTrace ).isEqualTo( "3" ); + } + } ); + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( lines.readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + } + } + + /** + * + */ + @RunWith( Theories.class ) + public static class ReportEntryTest + { + @DataPoints( value = "operation" ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public static String[][] operations = { { "testSetStarting", "setTestSetStartingListener" }, + { "testSetCompleted", "setTestSetCompletedListener" }, + { "testStarting", "setTestStartingListener" }, + { "testSucceeded", "setTestSucceededListener" }, + { "testFailed", "setTestFailedListener" }, + { "testSkipped", "setTestSkippedListener" }, + { "testError", "setTestErrorListener" }, + { "testAssumptionFailure", "setTestAssumptionFailureListener" } + }; + + @DataPoints( value = "reportedMessage" ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public static String[] reportedMessage = { null, "skipped test" }; + + @DataPoints( value = "elapsed" ) + @SuppressWarnings( { "checkstyle:visibilitymodifier", "checkstyle:magicnumber" } ) + public static Integer[] elapsed = { null, 102 }; + + @DataPoints( value = "trim" ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public static boolean[] trim = { false, true }; + + @DataPoints( value = "msg" ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public static boolean[] msg = { false, true }; + + @DataPoints( value = "smart" ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public static boolean[] smart = { false, true }; + + @DataPoints( value = "trace" ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public static boolean[] trace = { false, true }; + + @Theory + public void testReportEntryOperations( @FromDataPoints( "operation" ) String[] operation, + @FromDataPoints( "reportedMessage" ) String reportedMessage, + @FromDataPoints( "elapsed" ) Integer elapsed, + @FromDataPoints( "trim" ) boolean trim, + @FromDataPoints( "msg" ) boolean msg, + @FromDataPoints( "smart" ) boolean smart, + @FromDataPoints( "trace" ) boolean trace ) + throws Exception + { + String exceptionMessage = msg ? "msg" : null; + String smartStackTrace = smart ? "MyTest:86 >> Error" : null; + String exceptionStackTrace = + trace ? ( trim ? "trace line 1\ntrace line 2" : "Exception: msg\ntrace line 1\ntrace line 2" ) + : null; + + StackTraceWriter stackTraceWriter = null; + if ( exceptionStackTrace != null ) + { + SafeThrowable safeThrowable = new SafeThrowable( exceptionMessage ); + stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( exceptionStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( exceptionStackTrace ); + } + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( elapsed ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( reportedMessage ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getName() ).thenReturn( "display name of test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getSourceText() ).thenReturn( "test class display name" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + ForkedChannelEncoder.class.getMethod( operation[0], ReportEntry.class, boolean.class ) + .invoke( forkedChannelEncoder, reportEntry, trim ); + + ForkedChannelDecoder decoder = new ForkedChannelDecoder(); + + ForkedChannelDecoder.class.getMethod( operation[1], ForkedProcessReportEventListener.class ) + .invoke( decoder, new ReportEventAssertionListener( reportEntry ) ); + + AssertionErrorHandler errorHandler = mock( AssertionErrorHandler.class ); + decoder.handleEvent( out.newReader( UTF_8 ).readLine(), errorHandler ); + verifyZeroInteractions( errorHandler ); + } + } + + private static class AssertionErrorHandler implements ForkedChannelDecoderErrorHandler + { + public void handledError( String line, Throwable e ) + { + if ( e != null ) + { + e.printStackTrace(); + } + fail( line + ( e == null ? "" : "\n" + e.getLocalizedMessage() ) ); + } + } + + private static class PropertyEventAssertionListener implements ForkedProcessPropertyEventListener + { + private final Map sysProps = System.getProperties(); + + public void handle( RunMode runMode, String key, String value ) + { + assertThat( runMode ).isEqualTo( NORMAL_RUN ); + assertTrue( sysProps.containsKey( key ) ); + assertThat( sysProps.get( key ) ).isEqualTo( value ); + } + } + + private static class EventAssertionListener implements ForkedProcessEventListener + { + public void handle() + { + } + } + + private static class StringEventAssertionListener implements ForkedProcessStringEventListener + { + private final String msg; + + StringEventAssertionListener( String msg ) + { + this.msg = msg; + } + + public void handle( String msg ) + { + assertThat( msg ) + .isEqualTo( this.msg ); + } + } + + private static class StackTraceEventListener implements ForkedProcessStackTraceEventListener + { + private final String msg; + private final String smartStackTrace; + private final String stackTrace; + + StackTraceEventListener( String msg, String smartStackTrace, String stackTrace ) + { + this.msg = msg; + this.smartStackTrace = smartStackTrace; + this.stackTrace = stackTrace; + } + + @Override + public void handle( String msg, String smartStackTrace, String stackTrace ) + { + assertThat( msg ) + .isEqualTo( this.msg ); + + assertThat( smartStackTrace ) + .isEqualTo( this.smartStackTrace ); + + assertThat( stackTrace ) + .isEqualTo( this.stackTrace ); + } + } + + private static class StandardOutErrEventAssertionListener implements ForkedProcessStandardOutErrEventListener + { + private final RunMode runMode; + private final String output; + private final boolean newLine; + + StandardOutErrEventAssertionListener( RunMode runMode, String output, boolean newLine ) + { + this.runMode = runMode; + this.output = output; + this.newLine = newLine; + } + + public void handle( RunMode runMode, String output, boolean newLine ) + { + assertThat( runMode ) + .isEqualTo( this.runMode ); + + assertThat( output ) + .isEqualTo( this.output ); + + assertThat( newLine ) + .isEqualTo( this.newLine ); + } + } + + private static class ReportEventAssertionListener implements ForkedProcessReportEventListener + { + private final ReportEntry reportEntry; + + ReportEventAssertionListener( ReportEntry reportEntry ) + { + this.reportEntry = reportEntry; + } + + public void handle( RunMode runMode, ReportEntry reportEntry ) + { + assertThat( reportEntry.getSourceName() ).isEqualTo( this.reportEntry.getSourceName() ); + assertThat( reportEntry.getSourceText() ).isEqualTo( this.reportEntry.getSourceText() ); + assertThat( reportEntry.getName() ).isEqualTo( this.reportEntry.getName() ); + assertThat( reportEntry.getNameText() ).isEqualTo( this.reportEntry.getNameText() ); + assertThat( reportEntry.getGroup() ).isEqualTo( this.reportEntry.getGroup() ); + assertThat( reportEntry.getMessage() ).isEqualTo( this.reportEntry.getMessage() ); + assertThat( reportEntry.getElapsed() ).isEqualTo( this.reportEntry.getElapsed() ); + if ( reportEntry.getStackTraceWriter() == null ) + { + assertThat( this.reportEntry.getStackTraceWriter() ).isNull(); + } + else + { + assertThat( this.reportEntry.getStackTraceWriter() ).isNotNull(); + + assertThat( reportEntry.getStackTraceWriter().getThrowable().getMessage() ) + .isEqualTo( this.reportEntry.getStackTraceWriter().getThrowable().getMessage() ); + + assertThat( reportEntry.getStackTraceWriter().getThrowable().getLocalizedMessage() ) + .isEqualTo( this.reportEntry.getStackTraceWriter().getThrowable().getLocalizedMessage() ); + + assertThat( reportEntry.getStackTraceWriter().smartTrimmedStackTrace() ) + .isEqualTo( this.reportEntry.getStackTraceWriter().smartTrimmedStackTrace() ); + } + } + } + + private static class Stream extends PrintStream + { + private final ByteArrayOutputStream out; + + Stream( ByteArrayOutputStream out ) + { + super( out, true ); + this.out = out; + } + + byte[] toByteArray() + { + return out.toByteArray(); + } + + LineNumberReader newReader( Charset streamCharset ) + { + return new LineNumberReader( new StringReader( new String( toByteArray(), streamCharset ) ) ); + } + + static Stream newStream() + { + return new Stream( new ByteArrayOutputStream() ); + } + } + + private static byte[] toArray( ByteBuffer buffer ) + { + return Arrays.copyOfRange( buffer.array(), buffer.arrayOffset(), buffer.arrayOffset() + buffer.remaining() ); + } +} diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java index 55c3a644eb..0dfe1b8c97 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/DefaultReporterFactoryTest.java @@ -22,19 +22,26 @@ import java.io.File; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Queue; import junit.framework.TestCase; import org.apache.maven.plugin.surefire.StartupReportConfiguration; +import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.shared.utils.logging.MessageUtils; import org.apache.maven.surefire.report.RunStatistics; import org.apache.maven.surefire.report.SafeThrowable; import org.apache.maven.surefire.report.StackTraceWriter; +import org.apache.maven.surefire.suite.RunResult; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.error; import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.failure; import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.TestResultType.flake; @@ -44,31 +51,40 @@ import static org.apache.maven.plugin.surefire.report.DefaultReporterFactory.getTestResultType; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.powermock.reflect.Whitebox.getInternalState; +import static org.powermock.reflect.Whitebox.invokeMethod; +/** + * + */ public class DefaultReporterFactoryTest extends TestCase { - private final static String TEST_ONE = "testOne"; + private static final String TEST_ONE = "testOne"; - private final static String TEST_TWO = "testTwo"; + private static final String TEST_TWO = "testTwo"; - private final static String TEST_THREE = "testThree"; + private static final String TEST_THREE = "testThree"; - private final static String TEST_FOUR = "testFour"; + private static final String TEST_FOUR = "testFour"; - private final static String TEST_FIVE = "testFive"; + private static final String TEST_FIVE = "testFive"; - private final static String ASSERTION_FAIL = "assertionFail"; + private static final String ASSERTION_FAIL = "assertionFail"; - private final static String ERROR = "error"; + private static final String ERROR = "error"; public void testMergeTestHistoryResult() + throws Exception { MessageUtils.setColorEnabled( false ); - File reportsDirectory = new File("target"); + File target = new File( System.getProperty( "user.dir" ), "target" ); + File reportsDirectory = new File( target, "tmp5" ); StartupReportConfiguration reportConfig = - new StartupReportConfiguration( true, true, "PLAIN", false, false, reportsDirectory, false, null, - new File( reportsDirectory, "TESTHASH" ), false, 1, null, null, false ); + new StartupReportConfiguration( true, true, "PLAIN", false, reportsDirectory, false, null, + new File( reportsDirectory, "TESTHASH" ), false, 1, null, null, false, + new SurefireStatelessReporter(), new SurefireConsoleOutputReporter(), + new SurefireStatelessTestsetInfoReporter() ); DummyTestReporter reporter = new DummyTestReporter(); @@ -111,7 +127,7 @@ public void testMergeTestHistoryResult() factory.addListener( secondRunListener ); factory.addListener( thirdRunListener ); - factory.mergeTestHistoryResult(); + invokeMethod( factory, "mergeTestHistoryResult" ); RunStatistics mergedStatistics = factory.getGlobalRunStatistics(); // Only TEST_THREE is a failing test, other three are flaky tests @@ -132,14 +148,12 @@ public void testMergeTestHistoryResult() reporter.reset(); factory.printTestFailures( error ); String[] expectedFailureOutput = - { "Errors: ", TEST_THREE, " Run 1: " + ASSERTION_FAIL, " Run 2: " + ERROR, " Run 3: " + ERROR, "" - }; + { "Errors: ", TEST_THREE, " Run 1: " + ASSERTION_FAIL, " Run 2: " + ERROR, " Run 3: " + ERROR, "" }; assertEquals( asList( expectedFailureOutput ), reporter.getMessages() ); reporter.reset(); factory.printTestFailures( failure ); - String[] expectedErrorOutput = { }; - assertEquals( asList( expectedErrorOutput ), reporter.getMessages() ); + assertEquals( emptyList(), reporter.getMessages() ); } static final class DummyTestReporter implements ConsoleLogger @@ -197,12 +211,13 @@ public void error( String message ) @Override public void error( String message, Throwable t ) { - messages.add( message ); + messages.add( message + " " + t.getLocalizedMessage() ); } @Override public void error( Throwable t ) { + messages.add( t.getLocalizedMessage() ); } List getMessages() @@ -256,13 +271,134 @@ public void testGetTestResultType() assertEquals( skipped, getTestResultType( skippedList, 1 ) ); } + public void testLogger() + { + MessageUtils.setColorEnabled( false ); + File target = new File( System.getProperty( "user.dir" ), "target" ); + File reportsDirectory = new File( target, "tmp6" ); + StartupReportConfiguration reportConfig = + new StartupReportConfiguration( true, true, "PLAIN", false, reportsDirectory, false, null, + new File( reportsDirectory, "TESTHASH" ), false, 1, null, null, false, + new SurefireStatelessReporter(), new SurefireConsoleOutputReporter(), + new SurefireStatelessTestsetInfoReporter() ); + + DummyTestReporter reporter = new DummyTestReporter(); + + DefaultReporterFactory factory = new DefaultReporterFactory( reportConfig, reporter ); + + TestSetRunListener runListener = (TestSetRunListener) factory.createReporter(); + + assertTrue( runListener.isDebugEnabled() ); + assertTrue( runListener.isInfoEnabled() ); + assertTrue( runListener.isWarnEnabled() ); + assertTrue( runListener.isErrorEnabled() ); + + runListener.debug( "msg" ); + assertEquals( 1, reporter.getMessages().size() ); + assertEquals( "msg", reporter.getMessages().get( 0 ) ); + reporter.reset(); + + runListener.info( "msg\n" ); + assertEquals( 1, reporter.getMessages().size() ); + assertEquals( "msg", reporter.getMessages().get( 0 ) ); + reporter.reset(); + + runListener.warning( "msg\r\n" ); + assertEquals( 1, reporter.getMessages().size() ); + assertEquals( "msg", reporter.getMessages().get( 0 ) ); + reporter.reset(); + + runListener.error( "msg" ); + assertEquals( 1, reporter.getMessages().size() ); + assertEquals( "msg", reporter.getMessages().get( 0 ) ); + reporter.reset(); + + runListener.error( "msg\n", new Exception( "e" ) ); + assertEquals( 1, reporter.getMessages().size() ); + assertEquals( "msg e", reporter.getMessages().get( 0 ) ); + reporter.reset(); + + runListener.error( new Exception( "e" ) ); + assertEquals( 1, reporter.getMessages().size() ); + assertEquals( "e", reporter.getMessages().get( 0 ) ); + reporter.reset(); + } + + public void testCreateReporterWithZeroStatistics() + { + MessageUtils.setColorEnabled( false ); + File target = new File( System.getProperty( "user.dir" ), "target" ); + File reportsDirectory = new File( target, "tmp7" ); + StartupReportConfiguration reportConfig = + new StartupReportConfiguration( true, true, "PLAIN", false, reportsDirectory, false, null, + new File( reportsDirectory, "TESTHASH" ), false, 0, null, null, false, + new SurefireStatelessReporter(), new SurefireConsoleOutputReporter(), + new SurefireStatelessTestsetInfoReporter() ); + + assertTrue( reportConfig.isUseFile() ); + assertTrue( reportConfig.isPrintSummary() ); + assertEquals( "PLAIN", reportConfig.getReportFormat() ); + assertFalse( reportConfig.isRedirectTestOutputToFile() ); + assertEquals( reportsDirectory, reportConfig.getReportsDirectory() ); + assertFalse( reportConfig.isTrimStackTrace() ); + assertNull( reportConfig.getReportNameSuffix() ); + assertEquals( new File( reportsDirectory, "TESTHASH" ), reportConfig.getStatisticsFile() ); + assertFalse( reportConfig.isRequiresRunHistory() ); + assertEquals( 0, reportConfig.getRerunFailingTestsCount() ); + assertNull( reportConfig.getXsdSchemaLocation() ); + assertEquals( UTF_8, reportConfig.getEncoding() ); + assertFalse( reportConfig.isForkMode() ); + assertNotNull( reportConfig.getXmlReporter() ); + assertNotNull( reportConfig.getConsoleOutputReporter() ); + assertNotNull( reportConfig.getTestsetReporter() ); + assertNull( reportConfig.getStatisticsReporter() ); + + DummyTestReporter reporter = new DummyTestReporter(); + + DefaultReporterFactory factory = new DefaultReporterFactory( reportConfig, reporter ); + assertEquals( reportsDirectory, factory.getReportsDirectory() ); + + TestSetRunListener runListener = (TestSetRunListener) factory.createReporter(); + Collection listeners = getInternalState( factory, "listeners" ); + assertEquals( 1, listeners.size() ); + assertTrue( listeners.contains( runListener ) ); + + assertNotNull( runListener.getTestMethodStats() ); + + factory.runStarting(); + + factory.close(); + + RunStatistics statistics = factory.getGlobalRunStatistics(); + assertEquals( 0, statistics.getCompletedCount() ); + assertEquals( new RunResult( 0, 0, 0, 0 ), statistics.getRunResult() ); + assertEquals( 0, statistics.getFailures() ); + assertEquals( 0, statistics.getErrors() ); + assertEquals( 0, statistics.getSkipped() ); + assertEquals( 0, statistics.getFlakes() ); + assertEquals( "Tests run: 0, Failures: 0, Errors: 0, Skipped: 0", statistics.getSummary() ); + assertEquals( 0, statistics.getCompletedCount() ); + + List messages = reporter.getMessages(); + assertEquals( "", messages.get( 0 ) ); + assertEquals( "-------------------------------------------------------", messages.get( 1 ) ); + assertEquals( " T E S T S", messages.get( 2 ) ); + assertEquals( "-------------------------------------------------------", messages.get( 3 ) ); + assertEquals( "", messages.get( 4 ) ); + assertEquals( "Results:", messages.get( 5 ) ); + assertEquals( "", messages.get( 6 ) ); + assertEquals( "Tests run: 0, Failures: 0, Errors: 0, Skipped: 0", messages.get( 7 ) ); + assertEquals( "", messages.get( 8 ) ); + assertEquals( 9, messages.size() ); + } + static class DummyStackTraceWriter implements StackTraceWriter { private final String stackTrace; - public DummyStackTraceWriter( String stackTrace ) + DummyStackTraceWriter( String stackTrace ) { this.stackTrace = stackTrace; } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporterTest.java index 6e6f3d5ec7..0914051287 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporterTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/StatelessXmlReporterTest.java @@ -32,24 +32,26 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Deque; import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.maven.surefire.util.internal.ObjectUtils.systemProps; +/** + * + */ @SuppressWarnings( "ResultOfMethodCallIgnored" ) public class StatelessXmlReporterTest - extends TestCase + extends TestCase { private static final String XSD = "https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report-3.0.xsd"; - private final static String TEST_ONE = "aTestMethod"; - private final static String TEST_TWO = "bTestMethod"; - private final static String TEST_THREE = "cTestMethod"; + private static final String TEST_ONE = "aTestMethod"; + private static final String TEST_TWO = "bTestMethod"; + private static final String TEST_THREE = "cTestMethod"; private static final AtomicInteger FOLDER_POSTFIX = new AtomicInteger(); private TestSetStats stats; @@ -59,7 +61,7 @@ public class StatelessXmlReporterTest @Override protected void setUp() - throws Exception + throws Exception { stats = new TestSetStats( false, true ); rerunStats = new TestSetStats( false, true ); @@ -84,29 +86,30 @@ protected void tearDown() public void testFileNameWithoutSuffix() { StatelessXmlReporter reporter = - new StatelessXmlReporter( reportDir, null, false, 0, - new ConcurrentHashMap>>(), XSD ); + new StatelessXmlReporter( reportDir, null, false, 0, + new ConcurrentHashMap>(), XSD, "3.0", + false, false, false, false ); reporter.cleanTestHistoryMap(); - ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), getClass().getName(), 12 ); - WrappedReportEntry testSetReportEntry = - new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null, systemProps() ); + ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), null, getClass().getName(), null, 12 ); + WrappedReportEntry testSetReportEntry = new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, + 12, null, null, systemProps() ); stats.testSucceeded( testSetReportEntry ); reporter.testSetCompleted( testSetReportEntry, stats ); expectedReportFile = new File( reportDir, "TEST-" + getClass().getName() + ".xml" ); assertTrue( "Report file (" + expectedReportFile.getAbsolutePath() + ") doesn't exist", - expectedReportFile.exists() ); + expectedReportFile.exists() ); } public void testAllFieldsSerialized() - throws IOException + throws IOException { - ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), TEST_ONE, 12 ); + ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), null, TEST_ONE, null, 12 ); WrappedReportEntry testSetReportEntry = - new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null, systemProps() ); - expectedReportFile = new File( reportDir, "TEST-" + TEST_ONE + ".xml" ); + new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null, systemProps() ); + expectedReportFile = new File( reportDir, "TEST-" + getClass().getName() + ".xml" ); stats.testSucceeded( testSetReportEntry ); StackTraceWriter stackTraceWriter = new DeserializedStacktraceWriter( "A fud msg", "trimmed", "fail at foo" ); @@ -124,26 +127,23 @@ public void testAllFieldsSerialized() stdOutPrefix = "st]]>d-out"; } - byte[] stdOutBytes = (stdOutPrefix + "!\u0020\u0000\u001F").getBytes(); - stdOut.write( stdOutBytes, 0, stdOutBytes.length ); + stdOut.write( stdOutPrefix + "!\u0020\u0000\u001F", false ); Utf8RecodingDeferredFileOutputStream stdErr = new Utf8RecodingDeferredFileOutputStream( "fds" ); - - byte[] stdErrBytes = (stdErrPrefix + "?&-&£\u0020\u0000\u001F").getBytes(); - stdErr.write( stdErrBytes, 0, stdErrBytes.length ); + stdErr.write( stdErrPrefix + "?&-&£\u0020\u0000\u001F", false ); WrappedReportEntry t2 = - new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_TWO, stackTraceWriter, 13 ), - ReportEntryType.ERROR, 13, stdOut, stdErr ); + new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_TWO, null, + stackTraceWriter, 13 ), ReportEntryType.ERROR, 13, stdOut, stdErr ); stats.testSucceeded( t2 ); StatelessXmlReporter reporter = new StatelessXmlReporter( reportDir, null, false, 0, - new ConcurrentHashMap>>(), XSD ); + new ConcurrentHashMap>(), XSD, "3.0", false, false, false, false ); reporter.testSetCompleted( testSetReportEntry, stats ); FileInputStream fileInputStream = new FileInputStream( expectedReportFile ); - Xpp3Dom testSuite = Xpp3DomBuilder.build( new InputStreamReader( fileInputStream, UTF_8) ); + Xpp3Dom testSuite = Xpp3DomBuilder.build( new InputStreamReader( fileInputStream, UTF_8 ) ); assertEquals( "testsuite", testSuite.getName() ); Xpp3Dom properties = testSuite.getChild( "properties" ); assertEquals( System.getProperties().size(), properties.getChildCount() ); @@ -153,14 +153,14 @@ public void testAllFieldsSerialized() Xpp3Dom[] testcase = testSuite.getChildren( "testcase" ); Xpp3Dom tca = testcase[0]; - assertEquals( TEST_ONE, tca.getAttribute( "name" ) ); // Hopefully same order on jdk5 + assertEquals( TEST_ONE, tca.getAttribute( "name" ) ); assertEquals( "0.012", tca.getAttribute( "time" ) ); assertEquals( getClass().getName(), tca.getAttribute( "classname" ) ); Xpp3Dom tcb = testcase[1]; assertEquals( TEST_TWO, tcb.getAttribute( "name" ) ); assertEquals( "0.013", tcb.getAttribute( "time" ) ); - assertEquals( Inner.class.getName(), tcb.getAttribute( "classname" ) ); + assertEquals( getClass().getName(), tcb.getAttribute( "classname" ) ); Xpp3Dom errorNode = tcb.getChild( "error" ); assertNotNull( errorNode ); assertEquals( "A fud msg", errorNode.getAttribute( "message" ) ); @@ -172,19 +172,18 @@ public void testAllFieldsSerialized() } public void testOutputRerunFlakyFailure() - throws IOException + throws IOException { - ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), TEST_ONE, 12 ); - WrappedReportEntry testSetReportEntry = - new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null, systemProps() ); - expectedReportFile = new File( reportDir, "TEST-" + TEST_ONE + ".xml" ); + new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_ONE, null, 12 ), + ReportEntryType.SUCCESS, 12, null, null, systemProps() ); + expectedReportFile = new File( reportDir, "TEST-" + getClass().getName() + ".xml" ); stats.testSucceeded( testSetReportEntry ); StackTraceWriter stackTraceWriterOne = new DeserializedStacktraceWriter( "A fud msg", "trimmed", - "fail at foo" ); + "fail at foo" ); StackTraceWriter stackTraceWriterTwo = - new DeserializedStacktraceWriter( "A fud msg two", "trimmed two", "fail at foo two" ); + new DeserializedStacktraceWriter( "A fud msg two", "trimmed two", "fail at foo two" ); String firstRunOut = "first run out"; String firstRunErr = "first run err"; @@ -192,24 +191,24 @@ public void testOutputRerunFlakyFailure() String secondRunErr = "second run err"; WrappedReportEntry testTwoFirstError = - new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_TWO, stackTraceWriterOne, 5 ), - ReportEntryType.ERROR, 5, createStdOutput( firstRunOut ), - createStdOutput( firstRunErr ) ); + new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_TWO, null, + stackTraceWriterOne, 5 ), ReportEntryType.ERROR, 5, createStdOutput( firstRunOut ), + createStdOutput( firstRunErr ) ); WrappedReportEntry testTwoSecondError = - new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_TWO, stackTraceWriterTwo, 13 ), - ReportEntryType.ERROR, 13, createStdOutput( secondRunOut ), - createStdOutput( secondRunErr ) ); + new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_TWO, null, + stackTraceWriterTwo, 13 ), ReportEntryType.ERROR, 13, createStdOutput( secondRunOut ), + createStdOutput( secondRunErr ) ); WrappedReportEntry testThreeFirstRun = - new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_THREE, stackTraceWriterOne, 13 ), - ReportEntryType.FAILURE, 13, createStdOutput( firstRunOut ), - createStdOutput( firstRunErr ) ); + new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_THREE, null, + stackTraceWriterOne, 13 ), ReportEntryType.FAILURE, 13, createStdOutput( firstRunOut ), + createStdOutput( firstRunErr ) ); WrappedReportEntry testThreeSecondRun = - new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_THREE, stackTraceWriterTwo, 2 ), - ReportEntryType.SUCCESS, 2, createStdOutput( secondRunOut ), - createStdOutput( secondRunErr ) ); + new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_THREE, null, + stackTraceWriterTwo, 2 ), ReportEntryType.SUCCESS, 2, createStdOutput( secondRunOut ), + createStdOutput( secondRunErr ) ); stats.testSucceeded( testTwoFirstError ); stats.testSucceeded( testThreeFirstRun ); @@ -217,8 +216,8 @@ public void testOutputRerunFlakyFailure() rerunStats.testSucceeded( testThreeSecondRun ); StatelessXmlReporter reporter = - new StatelessXmlReporter( reportDir, null, false, 1, - new HashMap>>(), XSD ); + new StatelessXmlReporter( reportDir, null, false, 1, + new HashMap>(), XSD, "3.0", false, false, false, false ); reporter.testSetCompleted( testSetReportEntry, stats ); reporter.testSetCompleted( testSetReportEntry, rerunStats ); @@ -244,7 +243,7 @@ public void testOutputRerunFlakyFailure() assertEquals( TEST_TWO, testCaseTwo.getAttribute( "name" ) ); // Run time for a rerun failing test is the run time of the first run assertEquals( "0.005", testCaseTwo.getAttribute( "time" ) ); - assertEquals( Inner.class.getName(), testCaseTwo.getAttribute( "classname" ) ); + assertEquals( getClass().getName(), testCaseTwo.getAttribute( "classname" ) ); Xpp3Dom errorNode = testCaseTwo.getChild( "error" ); Xpp3Dom rerunErrorNode = testCaseTwo.getChild( "rerunError" ); assertNotNull( errorNode ); @@ -266,7 +265,7 @@ public void testOutputRerunFlakyFailure() assertEquals( TEST_THREE, testCaseThree.getAttribute( "name" ) ); // Run time for a flaky test is the run time of the first successful run assertEquals( "0.002", testCaseThree.getAttribute( "time" ) ); - assertEquals( Inner.class.getName(), testCaseThree.getAttribute( "classname" ) ); + assertEquals( getClass().getName(), testCaseThree.getAttribute( "classname" ) ); Xpp3Dom flakyFailureNode = testCaseThree.getChild( "flakyFailure" ); assertNotNull( flakyFailureNode ); assertEquals( firstRunOut, flakyFailureNode.getChild( "system-out" ).getValue() ); @@ -283,15 +282,10 @@ private boolean defaultCharsetSupportsSpecialChar() } private Utf8RecodingDeferredFileOutputStream createStdOutput( String content ) - throws IOException + throws IOException { Utf8RecodingDeferredFileOutputStream stdOut = new Utf8RecodingDeferredFileOutputStream( "fds2" ); - stdOut.write( content.getBytes(), 0, content.length() ); + stdOut.write( content, false ); return stdOut; } - - class Inner - { - - } } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/TestSetStatsTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/TestSetStatsTest.java new file mode 100644 index 0000000000..7aac3819a7 --- /dev/null +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/TestSetStatsTest.java @@ -0,0 +1,71 @@ +package org.apache.maven.plugin.surefire.report; + +/* + * 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.report.ReportEntry; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +/** + * tests for {@link TestSetStats}. + */ +@RunWith( PowerMockRunner.class ) +@PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } ) +public class TestSetStatsTest +{ + @Mock + private ReportEntry reportEntry; + + @Test + public void shouldConcatenateWithTestGroup() + { + when( reportEntry.getNameWithGroup() ) + .thenReturn( "pkg.MyTest (my group)" ); + String actual = TestSetStats.concatenateWithTestGroup( buffer(), reportEntry, false ); + verify( reportEntry, times( 1 ) ).getNameWithGroup(); + verifyNoMoreInteractions( reportEntry ); + String expected = buffer().a( "pkg." ).strong( "MyTest (my group)" ).toString(); + assertThat( actual ) + .isEqualTo( expected ); + } + + @Test + public void shouldConcatenateWithJUnit5TestGroup() + { + when( reportEntry.getReportNameWithGroup() ) + .thenReturn( "pkg.MyTest (my group)" ); + String actual = TestSetStats.concatenateWithTestGroup( buffer(), reportEntry, true ); + verify( reportEntry, times( 1 ) ).getReportNameWithGroup(); + verifyNoMoreInteractions( reportEntry ); + String expected = buffer().strong( "pkg.MyTest (my group)" ).toString(); + assertThat( actual ) + .isEqualTo( expected ); + } +} diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/WrappedReportEntryTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/WrappedReportEntryTest.java index 030fc2ffb5..36d1696732 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/WrappedReportEntryTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/report/WrappedReportEntryTest.java @@ -1,4 +1,5 @@ package org.apache.maven.plugin.surefire.report; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -23,51 +24,102 @@ import junit.framework.TestCase; +import static org.apache.maven.plugin.surefire.report.ReportEntryType.ERROR; +import static org.apache.maven.plugin.surefire.report.ReportEntryType.FAILURE; +import static org.apache.maven.plugin.surefire.report.ReportEntryType.SKIPPED; +import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS; + /** * @author Kristian Rosenvold */ public class WrappedReportEntryTest extends TestCase { - public void testClassNameOnly() - throws Exception { - String category = "surefire.testcase.JunitParamsTest"; + String className = "surefire.testcase.JunitParamsTest"; WrappedReportEntry wr = - new WrappedReportEntry( new SimpleReportEntry( "fud", category ), null, 12, null, null ); - final String reportName = wr.getReportName(); + new WrappedReportEntry( new SimpleReportEntry( className, null, null, null ), SUCCESS, 12, null, null ); + final String reportName = wr.getReportSourceName(); + assertEquals( "surefire.testcase.JunitParamsTest.null", wr.getClassMethodName() ); assertEquals( "surefire.testcase.JunitParamsTest", reportName ); + assertTrue( wr.isSucceeded() ); + assertFalse( wr.isErrorOrFailure() ); + assertFalse( wr.isSkipped() ); } public void testRegular() { - ReportEntry reportEntry = new SimpleReportEntry( "fud", "testSum(surefire.testcase.NonJunitParamsTest)" ); + ReportEntry reportEntry = new SimpleReportEntry( "surefire.testcase.JunitParamsTest", null, "testSum", null ); WrappedReportEntry wr = new WrappedReportEntry( reportEntry, null, 12, null, null ); - final String reportName = wr.getReportName(); - assertEquals( "testSum", reportName ); + assertEquals( "surefire.testcase.JunitParamsTest.testSum", wr.getClassMethodName() ); + assertEquals( "surefire.testcase.JunitParamsTest", wr.getReportSourceName() ); + assertEquals( "surefire.testcase.JunitParamsTest", wr.getReportSourceName( "" ) ); + assertEquals( "surefire.testcase.JunitParamsTest(BDD)", wr.getReportSourceName( "BDD" ) ); + assertEquals( "surefire.testcase.JunitParamsTest", wr.getSourceName( "" ) ); + assertEquals( "surefire.testcase.JunitParamsTest(BDD)", wr.getSourceName( "BDD" ) ); + assertEquals( "testSum", wr.getReportName() ); + assertFalse( wr.isSucceeded() ); + assertFalse( wr.isErrorOrFailure() ); + assertFalse( wr.isSkipped() ); + assertTrue( wr.getSystemProperties().isEmpty() ); + assertNull( wr.getGroup() ); + assertEquals( "surefire.testcase.JunitParamsTest", wr.getNameWithGroup() ); + } + + public void testDisplayNames() + { + ReportEntry reportEntry = + new SimpleReportEntry( "surefire.testcase.JunitParamsTest", "dn1", "testSum", "dn2", "exception" ); + WrappedReportEntry wr = new WrappedReportEntry( reportEntry, ERROR, 12, null, null ); + assertEquals( "surefire.testcase.JunitParamsTest.testSum", wr.getClassMethodName() ); + assertEquals( "dn1", wr.getReportSourceName() ); + assertEquals( "dn1(BDD)", wr.getReportSourceName( "BDD" ) ); + assertEquals( "surefire.testcase.JunitParamsTest(BDD)", wr.getSourceName( "BDD" ) ); + assertEquals( "dn2", wr.getReportName() ); + assertFalse( wr.isSucceeded() ); + assertTrue( wr.isErrorOrFailure() ); + assertFalse( wr.isSkipped() ); + assertNull( wr.getStackTraceWriter() ); + assertEquals( "surefire.testcase.JunitParamsTest.testSum Time elapsed: 0.012 s", + wr.getElapsedTimeSummary() ); + assertEquals( "surefire.testcase.JunitParamsTest.testSum Time elapsed: 0.012 s <<< ERROR!", + wr.getOutput( false ) ); + assertEquals( "exception", wr.getMessage() ); + } + + public void testEqualDisplayNames() + { + ReportEntry reportEntry = new SimpleReportEntry( "surefire.testcase.JunitParamsTest", + "surefire.testcase.JunitParamsTest", "testSum", "testSum" ); + WrappedReportEntry wr = new WrappedReportEntry( reportEntry, FAILURE, 12, null, null ); + assertEquals( "surefire.testcase.JunitParamsTest", wr.getReportSourceName() ); + assertEquals( "surefire.testcase.JunitParamsTest(BDD)", wr.getReportSourceName( "BDD" ) ); + assertEquals( "testSum", wr.getReportName() ); + assertFalse( wr.isSucceeded() ); + assertTrue( wr.isErrorOrFailure() ); + assertFalse( wr.isSkipped() ); } public void testGetReportNameWithParams() - throws Exception { - String category = "[0] 1\u002C 2\u002C 3 (testSum)(surefire.testcase.JunitParamsTest)"; - ReportEntry reportEntry = new SimpleReportEntry( "fud", category ); - WrappedReportEntry wr = new WrappedReportEntry( reportEntry, null, 12, null, null ); - final String reportName = wr.getReportName(); + String className = "[0] 1\u002C 2\u002C 3 (testSum)"; + ReportEntry reportEntry = new SimpleReportEntry( className, null, null, null ); + WrappedReportEntry wr = new WrappedReportEntry( reportEntry, SKIPPED, 12, null, null ); + final String reportName = wr.getReportSourceName(); assertEquals( "[0] 1, 2, 3 (testSum)", reportName ); + assertFalse( wr.isSucceeded() ); + assertFalse ( wr.isErrorOrFailure() ); + assertTrue( wr.isSkipped() ); } public void testElapsed() - throws Exception { - String category = "[0] 1\u002C 2\u002C 3 (testSum)(surefire.testcase.JunitParamsTest)"; - ReportEntry reportEntry = new SimpleReportEntry( "fud", category ); + String className = "[0] 1\u002C 2\u002C 3 (testSum)"; + ReportEntry reportEntry = new SimpleReportEntry( className, null, null, null ); WrappedReportEntry wr = new WrappedReportEntry( reportEntry, null, 12, null, null ); String elapsedTimeSummary = wr.getElapsedTimeSummary(); - assertEquals( "[0] 1, 2, 3 (testSum)(surefire.testcase.JunitParamsTest) Time elapsed: 0.012 s", + assertEquals( "[0] 1, 2, 3 (testSum) Time elapsed: 0.012 s", elapsedTimeSummary ); } - - } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java index 5a171ab8bd..1a15fbe0f9 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMapTest.java @@ -19,16 +19,24 @@ * under the License. */ +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; -import java.io.StringReader; +import java.io.InputStream; import java.util.Arrays; import java.util.List; + import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.SimpleReportEntry; import junit.framework.TestCase; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.IOUtils.readLines; +import static org.apache.maven.surefire.util.internal.StringUtils.NL; +import static org.fest.assertions.Assertions.assertThat; + /** * @author Kristian Rosenvold */ @@ -36,10 +44,9 @@ public class RunEntryStatisticsMapTest extends TestCase { public void testPrioritizedClassRuntime() - throws IOException { - final RunEntryStatisticsMap runEntryStatisticsMap = RunEntryStatisticsMap.fromReader( getStatisticsFile() ); - final List> list = Arrays.>asList( A.class, B.class, C.class ); + final RunEntryStatisticsMap runEntryStatisticsMap = RunEntryStatisticsMap.fromStream( getStatisticsFile() ); + final List> list = Arrays.asList( A.class, B.class, C.class ); final List> prioritizedTestsClassRunTime = runEntryStatisticsMap.getPrioritizedTestsClassRunTime( list, 2 ); assertEquals( C.class, prioritizedTestsClassRunTime.get( 0 ) ); @@ -48,10 +55,9 @@ public void testPrioritizedClassRuntime() } public void testPrioritizedFailureFirst() - throws IOException { - final RunEntryStatisticsMap runEntryStatisticsMap = RunEntryStatisticsMap.fromReader( getStatisticsFile() ); - final List> list = Arrays.>asList( A.class, B.class, NewClass.class, C.class ); + final RunEntryStatisticsMap runEntryStatisticsMap = RunEntryStatisticsMap.fromStream( getStatisticsFile() ); + final List> list = Arrays.asList( A.class, B.class, NewClass.class, C.class ); final List> prioritizedTestsClassRunTime = runEntryStatisticsMap.getPrioritizedTestsByFailureFirst( list ); assertEquals( A.class, prioritizedTestsClassRunTime.get( 0 ) ); @@ -60,14 +66,15 @@ public void testPrioritizedFailureFirst() assertEquals( B.class, prioritizedTestsClassRunTime.get( 3 ) ); } - private StringReader getStatisticsFile() + private InputStream getStatisticsFile() { - String content = "0,17,testA(org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$A)\n" + - "2,42,testB(org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$B)\n" + - "1,100,testC(org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$C)\n"; - return new StringReader( content ); + String content = "0,17,org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$A,testA\n" + + "2,42,org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$B,testB\n" + + "1,100,org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest$C,testC\n"; + return new ByteArrayInputStream( content.getBytes( UTF_8 ) ); } + @SuppressWarnings( "checkstyle:magicnumber" ) public void testSerialize() throws Exception { @@ -75,24 +82,124 @@ public void testSerialize() RunEntryStatisticsMap existingEntries = RunEntryStatisticsMap.fromFile( data ); RunEntryStatisticsMap newResults = new RunEntryStatisticsMap(); - ReportEntry reportEntry1 = new SimpleReportEntry( "abc", "method1", 42 ); - ReportEntry reportEntry2 = new SimpleReportEntry( "abc", "willFail", 17 ); - ReportEntry reportEntry3 = new SimpleReportEntry( "abc", "method3", 100 ); + ReportEntry reportEntry1 = new SimpleReportEntry( "abc", null, "method1", null, 42 ); + ReportEntry reportEntry2 = new SimpleReportEntry( "abc", null, "willFail", null, 17 ); + ReportEntry reportEntry3 = new SimpleReportEntry( "abc", null, "method3", null, 100 ); newResults.add( existingEntries.createNextGeneration( reportEntry1 ) ); newResults.add( existingEntries.createNextGeneration( reportEntry2 ) ); newResults.add( existingEntries.createNextGeneration( reportEntry3 ) ); newResults.serialize( data ); + try ( InputStream io = new FileInputStream( data ) ) + { + List lines = readLines( io, UTF_8 ); + + assertThat( lines ) + .hasSize( 3 ); + + assertThat( lines ) + .containsSequence( "1,17,abc,willFail", "1,42,abc,method1", "1,100,abc,method3" ); + } RunEntryStatisticsMap nextRun = RunEntryStatisticsMap.fromFile( data ); newResults = new RunEntryStatisticsMap(); - newResults.add( existingEntries.createNextGeneration( reportEntry1 ) ); - newResults.add( existingEntries.createNextGenerationFailure( reportEntry2 ) ); - newResults.add( existingEntries.createNextGeneration( reportEntry3 ) ); + ReportEntry newRunReportEntry1 = new SimpleReportEntry( "abc", null, "method1", null, 52 ); + ReportEntry newRunReportEntry2 = new SimpleReportEntry( "abc", null, "willFail", null, 27 ); + ReportEntry newRunReportEntry3 = new SimpleReportEntry( "abc", null, "method3", null, 110 ); + + newResults.add( nextRun.createNextGeneration( newRunReportEntry1 ) ); + newResults.add( nextRun.createNextGenerationFailure( newRunReportEntry2 ) ); + newResults.add( nextRun.createNextGeneration( newRunReportEntry3 ) ); newResults.serialize( data ); + try ( InputStream io = new FileInputStream( data ) ) + { + List lines = readLines( io, UTF_8 ); + + assertThat( lines ) + .hasSize( 3 ); + + assertThat( lines ) + .containsSequence( "0,27,abc,willFail", "2,52,abc,method1", "2,110,abc,method3" ); + } + } + + @SuppressWarnings( "checkstyle:magicnumber" ) + public void testMultiLineTestMethodName() throws IOException + { + File data = File.createTempFile( "surefire-unit", "test" ); + RunEntryStatisticsMap reportEntries = RunEntryStatisticsMap.fromFile( data ); + ReportEntry reportEntry = new SimpleReportEntry( "abc", null, "line1\nline2" + NL + " line3", null, 42 ); + reportEntries.add( reportEntries.createNextGeneration( reportEntry ) ); + + reportEntries.serialize( data ); + try ( InputStream io = new FileInputStream( data ) ) + { + List lines = readLines( io, UTF_8 ); + + assertThat( lines ) + .hasSize( 3 ); + + assertThat( lines ) + .containsSequence( "1,42,abc,line1", " line2", " line3" ); + } + + RunEntryStatisticsMap nextRun = RunEntryStatisticsMap.fromFile( data ); + assertThat( data.delete() ).isTrue(); + nextRun.serialize( data ); + try ( InputStream io = new FileInputStream( data ) ) + { + List lines = readLines( io, UTF_8 ); + + assertThat( lines ) + .hasSize( 3 ); + + assertThat( lines ) + .containsSequence( "1,42,abc,line1", " line2", " line3" ); + } + } + + @SuppressWarnings( "checkstyle:magicnumber" ) + public void testCombinedMethodNames() throws IOException + { + File data = File.createTempFile( "surefire-unit", "test" ); + RunEntryStatisticsMap reportEntries = RunEntryStatisticsMap.fromFile( data ); + reportEntries.add( + reportEntries.createNextGeneration( new SimpleReportEntry( "abc", null, "line1\nline2", null, 42 ) ) ); + reportEntries.add( + reportEntries.createNextGeneration( new SimpleReportEntry( "abc", null, "test", null, 10 ) ) ); + + reportEntries.serialize( data ); + try ( InputStream io = new FileInputStream( data ) ) + { + List lines = readLines( io, UTF_8 ); + + assertThat( lines ) + .hasSize( 3 ); + + assertThat( lines ) + .containsSequence( "1,10,abc,test", + "1,42,abc,line1", + " line2" ); + } + + RunEntryStatisticsMap nextRun = RunEntryStatisticsMap.fromFile( data ); + assertThat( data.delete() ).isTrue(); + nextRun.serialize( data ); + try ( InputStream io = new FileInputStream( data ) ) + { + List lines = readLines( io, UTF_8 ); + + assertThat( lines ) + .hasSize( 3 ); + + assertThat( lines ) + .containsSequence( "1,10,abc,test", + "1,42,abc,line1", + " line2" ); + } } class A diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java index e55c6a92e0..48f5e1e69e 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java @@ -19,16 +19,28 @@ * under the License. */ -import junit.framework.TestCase; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.handler.DefaultArtifactHandler; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.surefire.testset.TestListResolver; import org.apache.maven.surefire.util.ScanResult; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; import java.io.File; import java.io.FileOutputStream; -import java.util.*; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -36,12 +48,17 @@ * @author Aslak Knutsen */ public class DependenciesScannerTest - extends TestCase { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + @Test public void testLocateTestClasses() throws Exception { - File testFile = writeTestFile(); + File testFile = writeTestFile( "DependenciesScannerTest-tests.jar", + "org/test/TestA.class", "org/test/TestB.class" ); // use target as people can configure ide to compile in an other place than maven Artifact artifact = @@ -56,11 +73,8 @@ public void testLocateTestClasses() include.add( "**/*A.java" ); List exclude = new ArrayList<>(); - List dependenciesToScan = new ArrayList<>(); - for ( Artifact a : DependencyScanner.filter( Collections.singletonList( artifact ), scanDependencies ) ) - { - dependenciesToScan.add( a.getFile() ); - } + List dependenciesToScan = + filterArtifactsAsFiles( scanDependencies, Collections.singletonList( artifact ) ); DependencyScanner scanner = new DependencyScanner( dependenciesToScan, new TestListResolver( include, exclude ) ); @@ -74,18 +88,152 @@ public void testLocateTestClasses() assertEquals( 1, props.size() ); } - private File writeTestFile() + /** + * Test for artifact with classifier + */ + @Test + public void testLocateTestClassesFromArtifactWithClassifier() + throws Exception + { + File testJarFile = writeTestFile( "DependenciesScannerTest2-1.0-tests-jdk15.jar", "org/test/TestA.class", + "org/test/other/TestAA.class", "org/test/TestB.class" ); + Artifact testArtifact = + new DefaultArtifact( "org.surefire.dependency", "dependent-artifact2", + VersionRange.createFromVersion( "1.0" ), "test", "jar", "tests-jdk15", null ); + testArtifact.setFile( testJarFile ); + + List scanDependencies = new ArrayList<>(); + scanDependencies.add( "org.surefire.dependency:dependent-artifact2:*:*:tests-jdk15" ); + + List include = new ArrayList<>(); + include.add( "**/*A.java" ); + List exclude = new ArrayList<>(); + + + List filesToScan = filterArtifactsAsFiles( scanDependencies, Collections.singletonList( testArtifact ) ); + + DependencyScanner scanner = + new DependencyScanner( filesToScan, new TestListResolver( include, exclude ) ); + + ScanResult classNames = scanner.scan(); + assertNotNull( classNames ); + assertEquals( 2, classNames.size() ); + + Map props = new HashMap<>(); + classNames.writeTo( props ); + assertEquals( 2, props.size() ); + } + + /** + * Test with type when two artifacts are present, should only find the class in jar with correct type + */ + @Test + public void testLocateTestClassesFromMultipleArtifactsWithType() + throws Exception + { + File jarFile = + writeTestFile( "DependenciesScannerTest3-1.0.jar", "org/test/ClassA.class", "org/test/ClassB.class" ); + Artifact mainArtifact = new DefaultArtifact( "org.surefire.dependency", "dependent-artifact3", + VersionRange.createFromVersion( "1.0" ), "test", "jar", null, + new DefaultArtifactHandler() ); + mainArtifact.setFile( jarFile ); + + File testJarFile = + writeTestFile( "DependenciesScannerTest3-1.0-tests.jar", "org/test/TestA.class", "org/test/TestB.class" ); + Artifact testArtifact = new DefaultArtifact( "org.surefire.dependency", "dependent-artifact3", + VersionRange.createFromVersion( "1.0" ), "test", "test-jar", null, + new DefaultArtifactHandler() ); + testArtifact.setFile( testJarFile ); + + List scanDependencies = new ArrayList<>(); + scanDependencies.add( "org.surefire.dependency:dependent-artifact3:test-jar" ); + + List include = new ArrayList(); + include.add( "**/*A.java" ); + List exclude = new ArrayList(); + + List artifacts = Arrays.asList( mainArtifact, testArtifact ); + + List filesToScan = filterArtifactsAsFiles( scanDependencies, artifacts ); + + DependencyScanner scanner = new DependencyScanner( filesToScan, new TestListResolver( include, exclude ) ); + + ScanResult classNames = scanner.scan(); + assertNotNull( classNames ); + assertEquals( 1, classNames.size() ); + assertEquals( "org.test.TestA", classNames.getClassName( 0 ) ); + + Map props = new HashMap<>(); + classNames.writeTo( props ); + assertEquals( 1, props.size() ); + } + + /** + * Test to pick the right version of an artifact to scan + */ + @Test + public void testLocateTestClassesFromMultipleVersionsOfArtifact() + throws Exception + { + File jarFile10 = + writeTestFile( "DependenciesScannerTest4-1.0.jar", "org/test/ClassA.class", "org/test/ClassB.class" ); + Artifact artifact10 = new DefaultArtifact( "org.surefire.dependency", "dependent-artifact4", + VersionRange.createFromVersion( "1.0" ), "test", "jar", null, + new DefaultArtifactHandler() ); + artifact10.setFile( jarFile10 ); + + File jarFile20 = + writeTestFile( "DependenciesScannerTest4-2.0.jar", "org/test2/ClassA.class", "org/test2/ClassB.class" ); + Artifact artifact20 = new DefaultArtifact( "org.surefire.dependency", "dependent-artifact4", + VersionRange.createFromVersion( "2.0" ), "test", "jar", null, + new DefaultArtifactHandler() ); + artifact20.setFile( jarFile20 ); + + List scanDependencies = new ArrayList<>(); + scanDependencies.add( "org.surefire.dependency:dependent-artifact4:*:2.0" ); + + List include = new ArrayList<>(); + include.add( "**/*A.java" ); + List exclude = new ArrayList<>(); + + List artifacts = Arrays.asList( artifact10, artifact20 ); + + List filesToScan = filterArtifactsAsFiles( scanDependencies, artifacts ); + DependencyScanner scanner = new DependencyScanner( filesToScan, new TestListResolver( include, exclude ) ); + + ScanResult classNames = scanner.scan(); + assertNotNull( classNames ); + assertEquals( 1, classNames.size() ); + assertEquals( "org.test2.ClassA", classNames.getClassName( 0 ) ); + + Map props = new HashMap(); + classNames.writeTo( props ); + assertEquals( 1, props.size() ); + assertFalse( props.values().contains( "org.test.ClassA" ) ); + } + + private static List filterArtifactsAsFiles( List scanDependencies, List artifacts ) + { + List filesToScan = new ArrayList<>(); + for ( Artifact a : DependencyScanner.filter( artifacts, scanDependencies ) ) + { + filesToScan.add( a.getFile() ); + } + return filesToScan; + } + + private File writeTestFile( String fileName, String... entries ) throws Exception { - File output = new File( "target/DependenciesScannerTest-tests.jar" ); - output.delete(); + File output = tempFolder.newFile( fileName ); try ( ZipOutputStream out = new ZipOutputStream( new FileOutputStream( output ) ) ) { - out.putNextEntry( new ZipEntry( "org/test/TestA.class" ) ); - out.closeEntry(); - out.putNextEntry( new ZipEntry( "org/test/TestB.class" ) ); - out.closeEntry(); + for ( String entry : entries ) + { + out.putNextEntry( new ZipEntry( entry ) ); + out.closeEntry(); + } return output; } } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java index 02a462bc3c..f19b2a926f 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java @@ -32,8 +32,12 @@ import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.junit.runners.Parameterized.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.runners.Parameterized.Parameter; +import static org.junit.runners.Parameterized.Parameters; /** * @author Kristian Rosenvold @@ -42,20 +46,24 @@ public class DirectoryScannerTest { @Parameters( name = "\"{0}\" should count {1} classes" ) - public static Iterable data() { - return Arrays.asList( new Object[][] { - { "**/*ZT*A.java", is( 3 ) }, - { "**/*ZT*A.java#testMethod", is( 3 ) }, - { "**/*ZT?A.java#testMethod, !*ZT2A", is( 2 ) }, - { "**/*ZT?A.java#testMethod, !*ZT2A#testMethod", is( 3 ) }, - { "#testMethod", is( greaterThanOrEqualTo( 3 ) ) }, - } ); + public static Iterable data() + { + return Arrays.asList( new Object[][] + { + { "**/*ZT*A.java", is( 3 ) }, + { "**/*ZT*A.java#testMethod", is( 3 ) }, + { "**/*ZT?A.java#testMethod, !*ZT2A", is( 2 ) }, + { "**/*ZT?A.java#testMethod, !*ZT2A#testMethod", is( 3 ) }, + { "#testMethod", is( greaterThanOrEqualTo( 3 ) ) } + } ); } @Parameter( 0 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String filter; @Parameter( 1 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public Matcher expectedClassesCount; @Test diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java index 2f1f01f2d0..d28a89cb7c 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/JUnit4SuiteTest.java @@ -25,6 +25,7 @@ import junit.framework.TestSuite; import org.apache.maven.plugin.surefire.AbstractSurefireMojoJava7PlusTest; import org.apache.maven.plugin.surefire.AbstractSurefireMojoTest; +import org.apache.maven.plugin.surefire.CommonReflectorTest; import org.apache.maven.plugin.surefire.MojoMocklessTest; import org.apache.maven.plugin.surefire.SurefireHelperTest; import org.apache.maven.plugin.surefire.SurefireReflectorTest; @@ -38,15 +39,20 @@ import org.apache.maven.plugin.surefire.booterclient.ModularClasspathForkConfigurationTest; import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestLessInputStreamBuilderTest; import org.apache.maven.plugin.surefire.booterclient.lazytestprovider.TestProvidingInputStreamTest; +import org.apache.maven.plugin.surefire.booterclient.output.ForkClientTest; +import org.apache.maven.plugin.surefire.booterclient.output.ForkedChannelDecoderTest; import org.apache.maven.plugin.surefire.report.DefaultReporterFactoryTest; import org.apache.maven.plugin.surefire.report.StatelessXmlReporterTest; +import org.apache.maven.plugin.surefire.report.TestSetStatsTest; import org.apache.maven.plugin.surefire.report.WrappedReportEntryTest; import org.apache.maven.plugin.surefire.runorder.RunEntryStatisticsMapTest; import org.apache.maven.plugin.surefire.util.DependenciesScannerTest; import org.apache.maven.plugin.surefire.util.DirectoryScannerTest; import org.apache.maven.plugin.surefire.util.ScannerUtilTest; import org.apache.maven.plugin.surefire.util.SpecificFileFilterTest; -import org.apache.maven.surefire.report.ConsoleOutputFileReporterTest; +import org.apache.maven.surefire.extensions.ConsoleOutputReporterTest; +import org.apache.maven.surefire.extensions.StatelessReporterTest; +import org.apache.maven.surefire.extensions.StatelessTestsetInfoReporterTest; import org.apache.maven.surefire.report.FileReporterTest; import org.apache.maven.surefire.report.RunStatisticsTest; import org.apache.maven.surefire.spi.SPITest; @@ -66,11 +72,11 @@ public static Test suite() suite.addTestSuite( RelocatorTest.class ); suite.addTestSuite( RunStatisticsTest.class ); suite.addTestSuite( FileReporterTest.class ); - suite.addTestSuite( ConsoleOutputFileReporterTest.class ); + suite.addTestSuite( org.apache.maven.surefire.report.ConsoleOutputFileReporterTest.class ); suite.addTestSuite( SurefirePropertiesTest.class ); suite.addTestSuite( SpecificFileFilterTest.class ); suite.addTest( new JUnit4TestAdapter( DirectoryScannerTest.class ) ); - suite.addTestSuite( DependenciesScannerTest.class ); + suite.addTest( new JUnit4TestAdapter( DependenciesScannerTest.class ) ); suite.addTestSuite( RunEntryStatisticsMapTest.class ); suite.addTestSuite( WrappedReportEntryTest.class ); suite.addTestSuite( StatelessXmlReporterTest.class ); @@ -91,6 +97,13 @@ public static Test suite() suite.addTest( new JUnit4TestAdapter( AbstractSurefireMojoJava7PlusTest.class ) ); suite.addTest( new JUnit4TestAdapter( ScannerUtilTest.class ) ); suite.addTest( new JUnit4TestAdapter( MojoMocklessTest.class ) ); + suite.addTest( new JUnit4TestAdapter( ForkClientTest.class ) ); + suite.addTest( new JUnit4TestAdapter( ForkedChannelDecoderTest.class ) ); + suite.addTest( new JUnit4TestAdapter( ConsoleOutputReporterTest.class ) ); + suite.addTest( new JUnit4TestAdapter( StatelessReporterTest.class ) ); + suite.addTest( new JUnit4TestAdapter( TestSetStatsTest.class ) ); + suite.addTest( new JUnit4TestAdapter( StatelessTestsetInfoReporterTest.class ) ); + suite.addTest( new JUnit4TestAdapter( CommonReflectorTest.class ) ); return suite; } } diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/ConsoleOutputReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/ConsoleOutputReporterTest.java new file mode 100644 index 0000000000..546e554592 --- /dev/null +++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/ConsoleOutputReporterTest.java @@ -0,0 +1,173 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.junit5.JUnit5ConsoleOutputReporter; +import org.apache.maven.plugin.surefire.report.ConsoleOutputFileReporter; +import org.apache.maven.plugin.surefire.report.DirectConsoleOutput; +import org.junit.Test; + +import java.io.File; + +import static org.fest.assertions.Assertions.assertThat; +import static org.powermock.reflect.Whitebox.getInternalState; + +/** + * tests for {@link SurefireConsoleOutputReporter} and {@link JUnit5ConsoleOutputReporter}. + */ +public class ConsoleOutputReporterTest +{ + @Test + public void shouldCloneConsoleReporter() + { + SurefireConsoleOutputReporter extension = new SurefireConsoleOutputReporter(); + extension.setDisable( true ); + extension.setEncoding( "ISO-8859-1" ); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Object clone = extension.clone( classLoader ); + assertThat( clone ) + .isNotSameAs( extension ); + assertThat( clone ) + .isInstanceOf( SurefireConsoleOutputReporter.class ); + assertThat( clone.toString() ) + .isEqualTo( "SurefireConsoleOutputReporter{disable=true, encoding=ISO-8859-1}" ); + assertThat( ( (SurefireConsoleOutputReporter) clone ).isDisable() ) + .isTrue(); + assertThat( ( (SurefireConsoleOutputReporter) clone ).getEncoding() ) + .isEqualTo( "ISO-8859-1" ); + } + + @Test + public void shouldAssertToStringConsoleReporter() + { + SurefireConsoleOutputReporter extension = new SurefireConsoleOutputReporter(); + assertThat( extension.toString() ) + .isEqualTo( "SurefireConsoleOutputReporter{disable=false, encoding=UTF-8}" ); + } + + @Test + public void shouldCreateConsoleListener() + { + ConsoleOutputReporter extension = new SurefireConsoleOutputReporter(); + + ConsoleOutputReportEventListener listener1 = extension.createListener( System.out, System.err ); + assertThat( listener1 ) + .isInstanceOf( DirectConsoleOutput.class ); + assertThat( getInternalState( listener1, "out" ) ) + .isSameAs( System.out ); + assertThat( getInternalState( listener1, "err" ) ) + .isSameAs( System.err ); + + File target = new File( System.getProperty( "user.dir" ), "target" ); + File reportsDirectory = new File( target, "surefire-reports" ); + String reportNameSuffix = "suffix"; + boolean usePhrasedFileName = false; + Integer forkNumber = 1; + String encoding = "ISO-8859-2"; + extension.setEncoding( encoding ); + ConsoleOutputReportEventListener listener2 = + extension.createListener( reportsDirectory, reportNameSuffix, forkNumber ); + assertThat( listener2 ) + .isInstanceOf( ConsoleOutputFileReporter.class ); + assertThat( getInternalState( listener2, "reportsDirectory" ) ) + .isSameAs( reportsDirectory ); + assertThat( getInternalState( listener2, "reportNameSuffix" ) ) + .isSameAs( reportNameSuffix ); + assertThat( getInternalState( listener2, "usePhrasedFileName" ) ) + .isEqualTo( usePhrasedFileName ); + assertThat( getInternalState( listener2, "forkNumber" ) ) + .isSameAs( forkNumber ); + assertThat( getInternalState( listener2, "encoding" ) ) + .isSameAs( encoding ); + assertThat( getInternalState( listener2, "reportEntryName" ) ) + .isNull(); + } + + @Test + public void shouldCloneJUnit5ConsoleReporter() + { + JUnit5ConsoleOutputReporter extension = new JUnit5ConsoleOutputReporter(); + extension.setDisable( true ); + extension.setEncoding( "ISO-8859-1" ); + extension.setUsePhrasedFileName( true ); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Object clone = extension.clone( classLoader ); + assertThat( clone ) + .isNotSameAs( extension ); + assertThat( clone ) + .isInstanceOf( JUnit5ConsoleOutputReporter.class ); + assertThat( clone.toString() ).isEqualTo( + "JUnit5ConsoleOutputReporter{disable=true, encoding=ISO-8859-1, usePhrasedFileName=true}" ); + assertThat( ( (JUnit5ConsoleOutputReporter) clone ).isDisable() ) + .isTrue(); + assertThat( ( (JUnit5ConsoleOutputReporter) clone ).getEncoding() ) + .isEqualTo( "ISO-8859-1" ); + assertThat( ( (JUnit5ConsoleOutputReporter) clone ).isUsePhrasedFileName() ) + .isTrue(); + } + + @Test + public void shouldAssertToStringJUnit5ConsoleReporter() + { + JUnit5ConsoleOutputReporter extension = new JUnit5ConsoleOutputReporter(); + assertThat( extension.toString() ) + .isEqualTo( "JUnit5ConsoleOutputReporter{disable=false, encoding=UTF-8, usePhrasedFileName=false}" ); + } + + @Test + public void shouldCreateJUnit5ConsoleListener() + { + JUnit5ConsoleOutputReporter extension = new JUnit5ConsoleOutputReporter(); + + ConsoleOutputReportEventListener listener1 = extension.createListener( System.out, System.err ); + assertThat( listener1 ) + .isInstanceOf( DirectConsoleOutput.class ); + assertThat( getInternalState( listener1, "out" ) ) + .isSameAs( System.out ); + assertThat( getInternalState( listener1, "err" ) ) + .isSameAs( System.err ); + + File target = new File( System.getProperty( "user.dir" ), "target" ); + File reportsDirectory = new File( target, "surefire-reports" ); + String reportNameSuffix = "suffix"; + boolean usePhrasedFileName = true; + Integer forkNumber = 1; + String encoding = "ISO-8859-1"; + extension.setEncoding( encoding ); + extension.setUsePhrasedFileName( usePhrasedFileName ); + ConsoleOutputReportEventListener listener2 = + extension.createListener( reportsDirectory, reportNameSuffix, forkNumber ); + assertThat( listener2 ) + .isInstanceOf( ConsoleOutputFileReporter.class ); + assertThat( getInternalState( listener2, "reportsDirectory" ) ) + .isSameAs( reportsDirectory ); + assertThat( getInternalState( listener2, "reportNameSuffix" ) ) + .isSameAs( reportNameSuffix ); + assertThat( getInternalState( listener2, "usePhrasedFileName" ) ) + .isEqualTo( usePhrasedFileName ); + assertThat( getInternalState( listener2, "forkNumber" ) ) + .isSameAs( forkNumber ); + assertThat( getInternalState( listener2, "encoding" ) ) + .isSameAs( encoding ); + assertThat( getInternalState( listener2, "reportEntryName" ) ) + .isNull(); + } +} diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/StatelessReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/StatelessReporterTest.java new file mode 100644 index 0000000000..bb06eff0fb --- /dev/null +++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/StatelessReporterTest.java @@ -0,0 +1,244 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.plugin.surefire.extensions.DefaultStatelessReportMojoConfiguration; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.junit5.JUnit5Xml30StatelessReporter; +import org.apache.maven.plugin.surefire.report.StatelessXmlReporter; +import org.apache.maven.plugin.surefire.report.TestSetStats; +import org.apache.maven.plugin.surefire.report.WrappedReportEntry; +import org.junit.Test; + +import java.io.File; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; + +import static org.fest.assertions.Assertions.assertThat; +import static org.powermock.reflect.Whitebox.getInternalState; + +/** + * tests for {@link SurefireStatelessReporter} and {@link JUnit5Xml30StatelessReporter}. + */ +public class StatelessReporterTest +{ + @Test + public void shouldCloneXmlReporter() + { + SurefireStatelessReporter extension = new SurefireStatelessReporter(); + extension.setDisable( true ); + extension.setVersion( "V1" ); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + Object clone = extension.clone( classLoader ); + assertThat( clone ) + .isNotSameAs( extension ); + assertThat( clone ) + .isInstanceOf( SurefireStatelessReporter.class ); + assertThat( clone.toString() ) + .isEqualTo( "SurefireStatelessReporter{version=V1, disable=true}" ); + assertThat( ( (SurefireStatelessReporter) clone ).isDisable() ) + .isTrue(); + assertThat( ( (SurefireStatelessReporter) clone ).getVersion() ) + .isEqualTo( "V1" ); + } + + @Test + public void shouldAssertToStringXmlReporter() + { + SurefireStatelessReporter extension = new SurefireStatelessReporter(); + assertThat( extension.toString() ) + .isEqualTo( "SurefireStatelessReporter{version=3.0, disable=false}" ); + } + + @Test + public void shouldCreateConsoleListener() + { + File target = new File( System.getProperty( "user.dir" ), "target" ); + File reportsDirectory = new File( target, "surefire-reports" ); + String reportNameSuffix = "suffix"; + String schema = "https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report-3.0.xsd"; + Map> testClassMethodRunHistory = new HashMap<>(); + DefaultStatelessReportMojoConfiguration config = + new DefaultStatelessReportMojoConfiguration( reportsDirectory, reportNameSuffix, true, 5, schema, + testClassMethodRunHistory ); + SurefireStatelessReporter extension = new SurefireStatelessReporter(); + + assertThat( extension.getVersion() ) + .isEqualTo( "3.0" ); + extension.setVersion( "V3" ); + assertThat( extension.getVersion() ) + .isEqualTo( "V3" ); + + assertThat( extension.isDisable() ) + .isFalse(); + extension.setDisable( true ); + assertThat( extension.isDisable() ) + .isTrue(); + + StatelessReportEventListener listener = extension.createListener( config ); + assertThat( listener ) + .isInstanceOf( StatelessXmlReporter.class ); + assertThat( getInternalState( listener, "reportsDirectory" ) ) + .isSameAs( reportsDirectory ); + assertThat( getInternalState( listener, "reportNameSuffix" ) ) + .isSameAs( reportNameSuffix ); + assertThat( getInternalState( listener, "trimStackTrace" ) ) + .isEqualTo( true ); + assertThat( getInternalState( listener, "rerunFailingTestsCount" ) ) + .isEqualTo( 5 ); + assertThat( getInternalState( listener, "xsdSchemaLocation" ) ) + .isSameAs( schema ); + assertThat( getInternalState( listener, "xsdVersion" ) ) + .isEqualTo( "V3" ); + assertThat( getInternalState( listener, "testClassMethodRunHistoryMap" ) ) + .isSameAs( testClassMethodRunHistory ); + assertThat( getInternalState( listener, "phrasedFileName" ) ) + .isEqualTo( false ); + assertThat( getInternalState( listener, "phrasedSuiteName" ) ) + .isEqualTo( false ); + assertThat( getInternalState( listener, "phrasedClassName" ) ) + .isEqualTo( false ); + assertThat( getInternalState( listener, "phrasedMethodName" ) ) + .isEqualTo( false ); + } + + @Test + public void shouldCloneJUnit5XmlReporter() + { + JUnit5Xml30StatelessReporter extension = new JUnit5Xml30StatelessReporter(); + extension.setDisable( true ); + extension.setVersion( "V1" ); + extension.setUsePhrasedFileName( true ); + extension.setUsePhrasedTestSuiteClassName( true ); + extension.setUsePhrasedTestCaseClassName( true ); + extension.setUsePhrasedTestCaseMethodName( true ); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + Object clone = extension.clone( classLoader ); + assertThat( clone ) + .isNotSameAs( extension ); + assertThat( clone ) + .isInstanceOf( JUnit5Xml30StatelessReporter.class ); + assertThat( clone.toString() ) + .isEqualTo( "JUnit5Xml30StatelessReporter{version=V1, disable=true, usePhrasedFileName=true, " + + "usePhrasedTestSuiteClassName=true, usePhrasedTestCaseClassName=true, " + + "usePhrasedTestCaseMethodName=true}" ); + assertThat( ( (JUnit5Xml30StatelessReporter) clone ).isDisable() ) + .isTrue(); + assertThat( ( (JUnit5Xml30StatelessReporter) clone ).getVersion() ) + .isEqualTo( "V1" ); + assertThat( ( (JUnit5Xml30StatelessReporter) clone ).getUsePhrasedFileName() ) + .isTrue(); + assertThat( ( (JUnit5Xml30StatelessReporter) clone ).getUsePhrasedTestCaseClassName() ) + .isTrue(); + assertThat( ( (JUnit5Xml30StatelessReporter) clone ).getUsePhrasedTestCaseMethodName() ) + .isTrue(); + assertThat( ( (JUnit5Xml30StatelessReporter) clone ).getUsePhrasedTestSuiteClassName() ) + .isTrue(); + } + + @Test + public void shouldAssertToStringJUnit5ConsoleReporter() + { + JUnit5Xml30StatelessReporter extension = new JUnit5Xml30StatelessReporter(); + assertThat( extension.toString() ) + .isEqualTo( "JUnit5Xml30StatelessReporter{version=3.0, disable=false, " + + "usePhrasedFileName=false, usePhrasedTestSuiteClassName=false, " + + "usePhrasedTestCaseClassName=false, usePhrasedTestCaseMethodName=false}" ); + } + + @Test + public void shouldCreateJUnit5ConsoleListener() + { + File target = new File( System.getProperty( "user.dir" ), "target" ); + File reportsDirectory = new File( target, "surefire-reports" ); + String reportNameSuffix = "suffix"; + String schema = "https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report-3.0.xsd"; + Map> testClassMethodRunHistory = new HashMap<>(); + DefaultStatelessReportMojoConfiguration config = + new DefaultStatelessReportMojoConfiguration( reportsDirectory, reportNameSuffix, true, 5, schema, + testClassMethodRunHistory ); + JUnit5Xml30StatelessReporter extension = new JUnit5Xml30StatelessReporter(); + + assertThat( extension.getVersion() ) + .isEqualTo( "3.0" ); + extension.setVersion( "V3" ); + assertThat( extension.getVersion() ) + .isEqualTo( "V3" ); + + assertThat( extension.isDisable() ) + .isFalse(); + extension.setDisable( true ); + assertThat( extension.isDisable() ) + .isTrue(); + + assertThat( extension.getUsePhrasedFileName() ) + .isFalse(); + extension.setUsePhrasedFileName( true ); + assertThat( extension.getUsePhrasedFileName() ) + .isTrue(); + + assertThat( extension.getUsePhrasedTestSuiteClassName() ) + .isFalse(); + extension.setUsePhrasedTestSuiteClassName( true ); + assertThat( extension.getUsePhrasedTestSuiteClassName() ) + .isTrue(); + + assertThat( extension.getUsePhrasedTestCaseClassName() ) + .isFalse(); + extension.setUsePhrasedTestCaseClassName( true ); + assertThat( extension.getUsePhrasedTestSuiteClassName() ) + .isTrue(); + + assertThat( extension.getUsePhrasedTestCaseMethodName() ) + .isFalse(); + extension.setUsePhrasedTestCaseMethodName( true ); + assertThat( extension.getUsePhrasedTestCaseMethodName() ) + .isTrue(); + + StatelessReportEventListener listener = extension.createListener( config ); + assertThat( listener ) + .isInstanceOf( StatelessXmlReporter.class ); + assertThat( getInternalState( listener, "reportsDirectory" ) ) + .isSameAs( reportsDirectory ); + assertThat( getInternalState( listener, "reportNameSuffix" ) ) + .isSameAs( reportNameSuffix ); + assertThat( getInternalState( listener, "trimStackTrace" ) ) + .isEqualTo( true ); + assertThat( getInternalState( listener, "rerunFailingTestsCount" ) ) + .isEqualTo( 5 ); + assertThat( getInternalState( listener, "xsdSchemaLocation" ) ) + .isSameAs( schema ); + assertThat( getInternalState( listener, "xsdVersion" ) ) + .isEqualTo( "V3" ); + assertThat( getInternalState( listener, "testClassMethodRunHistoryMap" ) ) + .isSameAs( testClassMethodRunHistory ); + assertThat( getInternalState( listener, "phrasedFileName" ) ) + .isEqualTo( true ); + assertThat( getInternalState( listener, "phrasedSuiteName" ) ) + .isEqualTo( true ); + assertThat( getInternalState( listener, "phrasedClassName" ) ) + .isEqualTo( true ); + assertThat( getInternalState( listener, "phrasedMethodName" ) ) + .isEqualTo( true ); + } +} diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoReporterTest.java new file mode 100644 index 0000000000..aa101112be --- /dev/null +++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoReporterTest.java @@ -0,0 +1,229 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; +import org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoReporter; +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.plugin.surefire.report.ConsoleReporter; +import org.apache.maven.plugin.surefire.report.FileReporter; +import org.apache.maven.plugin.surefire.report.TestSetStats; +import org.apache.maven.plugin.surefire.report.WrappedReportEntry; +import org.apache.maven.shared.utils.logging.MessageUtils; +import org.apache.maven.surefire.report.TestSetReportEntry; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.io.File; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static java.util.Collections.singletonList; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; +import static org.powermock.reflect.Whitebox.getInternalState; + +/** + * tests for {@link SurefireStatelessTestsetInfoReporter} and {@link JUnit5StatelessTestsetInfoReporter}. + */ +@RunWith( PowerMockRunner.class ) +@PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } ) +public class StatelessTestsetInfoReporterTest +{ + @Mock + private ConsoleLogger consoleLogger; + + @Mock + private TestSetReportEntry eventTestsetStarting; + + @Mock + private WrappedReportEntry eventTestsetFinished; + + @Test + public void shouldCloneReporter() + { + SurefireStatelessTestsetInfoReporter extension = new SurefireStatelessTestsetInfoReporter(); + extension.setDisable( true ); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + Object clone = extension.clone( classLoader ); + assertThat( clone ) + .isNotSameAs( extension ); + assertThat( clone ) + .isInstanceOf( SurefireStatelessTestsetInfoReporter.class ); + assertThat( clone.toString() ) + .isEqualTo( "SurefireStatelessTestsetInfoReporter{disable=true}" ); + assertThat( ( (SurefireStatelessTestsetInfoReporter) clone ).isDisable() ) + .isTrue(); + } + + @Test + public void shouldAssertToStringReporter() + { + SurefireStatelessTestsetInfoReporter extension = new SurefireStatelessTestsetInfoReporter(); + assertThat( extension.toString() ) + .isEqualTo( "SurefireStatelessTestsetInfoReporter{disable=false}" ); + } + + @Test + public void shouldCreateFileReporterListener() + { + File target = new File( System.getProperty( "user.dir" ), "target" ); + File reportsDirectory = new File( target, "surefire-reports" ); + String reportNameSuffix = "suffix"; + Charset encoding = StandardCharsets.UTF_8; + SurefireStatelessTestsetInfoReporter extension = new SurefireStatelessTestsetInfoReporter(); + + assertThat( extension.isDisable() ) + .isFalse(); + extension.setDisable( true ); + assertThat( extension.isDisable() ) + .isTrue(); + + StatelessTestsetInfoFileReportEventListener listener = + extension.createListener( reportsDirectory, reportNameSuffix, encoding ); + assertThat( listener ) + .isInstanceOf( FileReporter.class ); + assertThat( listener.getReportsDirectory() ) + .isSameAs( reportsDirectory ); + assertThat( listener.getReportNameSuffix() ) + .isSameAs( reportNameSuffix ); + assertThat( listener.getEncoding() ) + .isSameAs( encoding ); + assertThat( getInternalState( listener, "usePhrasedFileName" ) ) + .isEqualTo( false ); + assertThat( getInternalState( listener, "usePhrasedClassNameInRunning" ) ) + .isEqualTo( false ); + assertThat( getInternalState( listener, "usePhrasedClassNameInTestCaseSummary" ) ) + .isEqualTo( false ); + } + + @Test + public void shouldCreateConsoleReporterListener() + { + SurefireStatelessTestsetInfoReporter extension = new SurefireStatelessTestsetInfoReporter(); + + assertThat( extension.isDisable() ) + .isFalse(); + extension.setDisable( true ); + assertThat( extension.isDisable() ) + .isTrue(); + + StatelessTestsetInfoConsoleReportEventListener listener = + extension.createListener( consoleLogger ); + assertThat( listener ) + .isInstanceOf( ConsoleReporter.class ); + assertThat( listener.getConsoleLogger() ) + .isSameAs( consoleLogger ); + assertThat( getInternalState( listener, "usePhrasedClassNameInRunning" ) ) + .isEqualTo( false ); + assertThat( getInternalState( listener, "usePhrasedClassNameInTestCaseSummary" ) ) + .isEqualTo( false ); + } + + @Test + public void shouldCloneJUnit5Reporter() + { + JUnit5StatelessTestsetInfoReporter extension = new JUnit5StatelessTestsetInfoReporter(); + extension.setDisable( true ); + extension.setUsePhrasedFileName( true ); + extension.setUsePhrasedClassNameInTestCaseSummary( true ); + extension.setUsePhrasedClassNameInRunning( true ); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + Object clone = extension.clone( classLoader ); + assertThat( clone ) + .isNotSameAs( extension ); + assertThat( clone ) + .isInstanceOf( JUnit5StatelessTestsetInfoReporter.class ); + assertThat( clone.toString() ) + .isEqualTo( "JUnit5StatelessTestsetInfoReporter{disable=true, usePhrasedFileName=true, " + + "usePhrasedClassNameInRunning=true, usePhrasedClassNameInTestCaseSummary=true}" ); + assertThat( ( (JUnit5StatelessTestsetInfoReporter) clone ).isDisable() ) + .isTrue(); + assertThat( ( (JUnit5StatelessTestsetInfoReporter) clone ).isUsePhrasedFileName() ) + .isTrue(); + assertThat( ( (JUnit5StatelessTestsetInfoReporter) clone ).isUsePhrasedClassNameInTestCaseSummary() ) + .isTrue(); + assertThat( ( (JUnit5StatelessTestsetInfoReporter) clone ).isUsePhrasedClassNameInRunning() ) + .isTrue(); + } + + @Test + public void shouldAssertToStringJUnit5Reporter() + { + JUnit5StatelessTestsetInfoReporter extension = new JUnit5StatelessTestsetInfoReporter(); + assertThat( extension.toString() ) + .isEqualTo( "JUnit5StatelessTestsetInfoReporter{disable=false, usePhrasedFileName=false, " + + "usePhrasedClassNameInRunning=false, usePhrasedClassNameInTestCaseSummary=false}" ); + } + + @Test + public void shouldReportTestsetLifecycle() + { + ConsoleReporter consoleReporter = new ConsoleReporter( consoleLogger, false, false ); + MessageUtils.setColorEnabled( false ); + + when( eventTestsetStarting.getNameWithGroup() ).thenReturn( "pkg.MyTest" ); + when( eventTestsetFinished.getNameWithGroup() ).thenReturn( "pkg.MyTest" ); + when( eventTestsetFinished.getElapsedTimeVerbose() ).thenReturn( "Time elapsed: 1.03 s" ); + + consoleReporter.testSetStarting( eventTestsetStarting ); + ArgumentCaptor logs = ArgumentCaptor.forClass( String.class ); + verify( consoleLogger, times( 1 ) ).info( logs.capture() ); + verifyNoMoreInteractions( consoleLogger ); + assertThat( logs.getAllValues() ) + .hasSize( 1 ) + .contains( "Running pkg.MyTest" ); + + TestSetStats testSetStats = new TestSetStats( false, true ); + testSetStats.testStart(); + testSetStats.testFailure( eventTestsetFinished ); + assertThat( testSetStats.getCompletedCount() ).isEqualTo( 1 ); + assertThat( testSetStats.getFailures() ).isEqualTo( 1 ); + assertThat( testSetStats.getErrors() ).isEqualTo( 0 ); + assertThat( testSetStats.getSkipped() ).isEqualTo( 0 ); + reset( consoleLogger ); + consoleReporter.testSetCompleted( eventTestsetFinished, testSetStats, singletonList( "pkg.MyTest failed" ) ); + consoleReporter.reset(); + verify( consoleLogger, never() ).info( anyString() ); + verify( consoleLogger, never() ).warning( anyString() ); + logs = ArgumentCaptor.forClass( String.class ); + verify( consoleLogger, times( 2 ) ).error( logs.capture() ); + List messages = logs.getAllValues(); + assertThat( messages ) + .hasSize( 2 ) + .containsSequence( + "Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.03 s " + + "<<< FAILURE! - in pkg.MyTest", "pkg.MyTest failed" ); + verifyNoMoreInteractions( consoleLogger ); + } +} diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java index 45b264b670..e8922cff07 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/ConsoleOutputFileReporterTest.java @@ -34,6 +34,9 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import static org.fest.assertions.Assertions.assertThat; +/** + * + */ public class ConsoleOutputFileReporterTest extends TestCase { @@ -45,10 +48,11 @@ public void testFileNameWithoutSuffix() throws IOException File reportDir = new File( new File( System.getProperty( "user.dir" ), "target" ), "tmp1" ); //noinspection ResultOfMethodCallIgnored reportDir.mkdirs(); - ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), getClass().getName() ); - ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null, null ); + TestSetReportEntry reportEntry = + new SimpleReportEntry( getClass().getName(), null, getClass().getName(), null ); + ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null, false, null, "UTF-8" ); reporter.testSetStarting( reportEntry ); - reporter.writeTestOutput( "some text".getBytes( US_ASCII ), 0, 5, true ); + reporter.writeTestOutput( "some ", false, true ); reporter.testSetCompleted( reportEntry ); reporter.close(); @@ -70,13 +74,14 @@ public void testFileNameWithoutSuffix() throws IOException public void testFileNameWithSuffix() throws IOException { File reportDir = new File( new File( System.getProperty( "user.dir" ), "target" ), "tmp2" ); - //noinspection ResultOfMethodCallIgnored - reportDir.mkdirs(); String suffixText = "sampleSuffixText"; - ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), getClass().getName() ); - ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, suffixText, null ); + TestSetReportEntry reportEntry = + new SimpleReportEntry( getClass().getName(), null, getClass().getName(), null ); + ConsoleOutputFileReporter reporter = + new ConsoleOutputFileReporter( reportDir, suffixText, false, null, "UTF-8" ); reporter.testSetStarting( reportEntry ); - reporter.writeTestOutput( "some text".getBytes( US_ASCII ), 0, 5, true ); + reporter.writeTestOutput( null, true, true ); + reporter.writeTestOutput( "some ", true, true ); reporter.testSetCompleted( reportEntry ); reporter.close(); @@ -88,6 +93,9 @@ public void testFileNameWithSuffix() throws IOException assertThat( FileUtils.fileRead( expectedReportFile, US_ASCII.name() ) ) .contains( "some " ); + assertThat( expectedReportFile ) + .hasSize( 9 + 2 * System.lineSeparator().length() ); + //noinspection ResultOfMethodCallIgnored expectedReportFile.delete(); } @@ -95,11 +103,9 @@ public void testFileNameWithSuffix() throws IOException public void testNullReportFile() throws IOException { File reportDir = new File( new File( System.getProperty( "user.dir" ), "target" ), "tmp3" ); - //noinspection ResultOfMethodCallIgnored - reportDir.mkdirs(); - ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null, null ); - reporter.writeTestOutput( "some text".getBytes( US_ASCII ), 0, 5, true ); - reporter.testSetCompleted( new SimpleReportEntry( getClass().getName(), getClass().getName() ) ); + ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null, false, null, "UTF-8" ); + reporter.writeTestOutput( "some text", false, true ); + reporter.testSetCompleted( new SimpleReportEntry( getClass().getName(), null, getClass().getName(), null ) ); reporter.close(); File expectedReportFile = new File( reportDir, "null-output.txt" ); @@ -117,20 +123,19 @@ public void testNullReportFile() throws IOException public void testConcurrentAccessReportFile() throws Exception { File reportDir = new File( new File( System.getProperty( "user.dir" ), "target" ), "tmp4" ); - //noinspection ResultOfMethodCallIgnored - reportDir.mkdirs(); - final ConsoleOutputFileReporter reporter = new ConsoleOutputFileReporter( reportDir, null, null ); - reporter.testSetStarting( new SimpleReportEntry( getClass().getName(), getClass().getName() ) ); + final ConsoleOutputFileReporter reporter = + new ConsoleOutputFileReporter( reportDir, null, false, null, "UTF-8" ); + reporter.testSetStarting( new SimpleReportEntry( getClass().getName(), null, getClass().getName(), null ) ); ExecutorService scheduler = Executors.newFixedThreadPool( 10 ); final ArrayList> jobs = new ArrayList<>(); for ( int i = 0; i < 10; i++ ) { - jobs.add( new Callable() { + jobs.add( new Callable() + { @Override public Void call() { - byte[] stream = "some text\n".getBytes( US_ASCII ); - reporter.writeTestOutput( stream, 0, stream.length, true ); + reporter.writeTestOutput( "some text\n", false, true ); return null; } } ); diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/FileReporterTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/FileReporterTest.java index b733e2a3f7..cbb85cc7a5 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/FileReporterTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/FileReporterTest.java @@ -29,6 +29,9 @@ import junit.framework.TestCase; +/** + * + */ public class FileReporterTest extends TestCase { @@ -37,18 +40,18 @@ public class FileReporterTest private ReportEntry reportEntry; - private static final String testName = "org.apache.maven.surefire.report.FileReporterTest"; + private static final String TEST_NAME = "org.apache.maven.surefire.report.FileReporterTest"; public void testFileNameWithoutSuffix() { File reportDir = new File( "target" ); - reportEntry = new SimpleReportEntry( this.getClass().getName(), testName ); + reportEntry = new SimpleReportEntry( getClass().getName(), null, TEST_NAME, null ); WrappedReportEntry wrappedReportEntry = new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null ); - reporter = new FileReporter( reportDir, null, Charset.defaultCharset() ); + reporter = new FileReporter( reportDir, null, Charset.defaultCharset(), false, false, false ); reporter.testSetCompleted( wrappedReportEntry, createTestSetStats(), new ArrayList() ); - File expectedReportFile = new File( reportDir, testName + ".txt" ); + File expectedReportFile = new File( reportDir, TEST_NAME + ".txt" ); assertTrue( "Report file (" + expectedReportFile.getAbsolutePath() + ") doesn't exist", expectedReportFile.exists() ); //noinspection ResultOfMethodCallIgnored @@ -64,13 +67,13 @@ public void testFileNameWithSuffix() { File reportDir = new File( "target" ); String suffixText = "sampleSuffixText"; - reportEntry = new SimpleReportEntry( this.getClass().getName(), testName ); + reportEntry = new SimpleReportEntry( getClass().getName(), null, TEST_NAME, null ); WrappedReportEntry wrappedReportEntry = new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null ); - reporter = new FileReporter( reportDir, suffixText, Charset.defaultCharset() ); + reporter = new FileReporter( reportDir, suffixText, Charset.defaultCharset(), false, false, false ); reporter.testSetCompleted( wrappedReportEntry, createTestSetStats(), new ArrayList() ); - File expectedReportFile = new File( reportDir, testName + "-" + suffixText + ".txt" ); + File expectedReportFile = new File( reportDir, TEST_NAME + "-" + suffixText + ".txt" ); assertTrue( "Report file (" + expectedReportFile.getAbsolutePath() + ") doesn't exist", expectedReportFile.exists() ); //noinspection ResultOfMethodCallIgnored diff --git a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/RunStatisticsTest.java b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/RunStatisticsTest.java index acb17ccd7c..b05561a2a0 100644 --- a/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/RunStatisticsTest.java +++ b/maven-surefire-common/src/test/java/org/apache/maven/surefire/report/RunStatisticsTest.java @@ -1,24 +1,29 @@ package org.apache.maven.surefire.report; -import junit.framework.TestCase; - /* - * Copyright 2002-2009 the original author or authors. - * - * Licensed 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 + * 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 * - * 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. + * 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 junit.framework.TestCase; + +/** + * + */ public class RunStatisticsTest extends TestCase { diff --git a/maven-surefire-plugin/pom.xml b/maven-surefire-plugin/pom.xml index f93ca21ebf..b1ee87b1f7 100644 --- a/maven-surefire-plugin/pom.xml +++ b/maven-surefire-plugin/pom.xml @@ -24,7 +24,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 org.apache.maven.plugins @@ -35,7 +35,7 @@ Maven Surefire MOJO in maven-surefire-plugin. - 3.0 + ${mavenVersion} @@ -49,6 +49,11 @@ maven-surefire-common ${project.version} + + org.apache.maven + maven-core + provided + org.apache.maven.plugin-tools maven-plugin-annotations @@ -80,13 +85,31 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 diff --git a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java index fdc758ad12..4bc3b6d862 100644 --- a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java +++ b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java @@ -237,7 +237,7 @@ public class SurefirePlugin /** * The character encoding scheme to be applied while generating test report * files (see target/surefire-reports/yourTestName.txt). - * The report output files (*-out.txt) are still encoded with JVM's encoding used in standard out/err pipes. + * The report output files (*-out.txt) are encoded in UTF-8 if not set otherwise. * * @since 3.0.0-M1 */ @@ -245,7 +245,7 @@ public class SurefirePlugin private String encoding; /** - * (JUnit 4+ providers) + * (JUnit 4+ providers and JUnit 5+ providers since 3.0.0-M4) * The number of times each failing test will be rerun. If set larger than 0, rerun failing tests immediately after * they fail. If a failing test passes in any of those reruns, it will be marked as pass and reported as a "flake". * However, all the failing attempts will be recorded. @@ -300,6 +300,8 @@ public class SurefirePlugin * **{@literal /}NotIncludedByDefault.java * %regex[.*Test.*|.*Not.*] * + * + * @since 2.13 */ @Parameter( property = "surefire.includesFile" ) private File includesFile; @@ -312,6 +314,8 @@ public class SurefirePlugin * **{@literal /}DontRunTest.* * %regex[.*Test.*|.*Not.*] * + * + * @since 2.13 */ @Parameter( property = "surefire.excludesFile" ) private File excludesFile; @@ -334,10 +338,11 @@ public class SurefirePlugin * After the plugin process is shutdown by sending SIGTERM signal (CTRL+C), SHUTDOWN command is * received by every forked JVM. *
- * By default ({@code shutdown=testset}) forked JVM would not continue with new test which means that - * the current test may still continue to run. + * The value is set to ({@code shutdown=exit}) by default (changed in version 3.0.0-M4). + *
+ * The parameter can be configured with other two values {@code testset} and {@code kill}. *
- * The parameter can be configured with other two values {@code exit} and {@code kill}. + * With({@code shutdown=testset}) the test set may still continue to run in forked JVM. *
* Using {@code exit} forked JVM executes {@code System.exit(1)} after the plugin process has received * SIGTERM signal. @@ -346,7 +351,7 @@ public class SurefirePlugin * * @since 2.19 */ - @Parameter( property = "surefire.shutdown", defaultValue = "testset" ) + @Parameter( property = "surefire.shutdown", defaultValue = "exit" ) private String shutdown; /** @@ -360,6 +365,63 @@ public class SurefirePlugin @Parameter( property = "surefire.useModulePath", defaultValue = "true" ) private boolean useModulePath; + /** + * You can selectively exclude individual environment variables by enumerating their keys. + *
+ * The environment is a system-dependent mapping from keys to values which is inherited from the Maven process + * to the forked Surefire processes. The keys must literally (case sensitive) match in order to exclude + * their environment variable. + *
+ * Example to exclude three environment variables: + *
+ * mvn test -Dsurefire.excludedEnvironmentVariables=ACME1,ACME2,ACME3 + * + * @since 3.0.0-M4 + */ + @Parameter( property = "surefire.excludedEnvironmentVariables" ) + private String[] excludedEnvironmentVariables; + + /** + * Since 3.0.0-M4 the process checkers are disabled. + * You can enable them namely by setting {@code ping} and {@code native} or {@code all} in this parameter. + *
+ * The checker is useful in situations when you kill the build on CI and you want the Surefire forked JVM to kill + * the tests asap and free all handlers on the file system been previously used by the JVM and by the tests. + * + *
+ * + * The {@code ping} should be safely used together with ZGC or Shenandoah Garbage Collector. + * Due to the {@code ping} relies on timing the PING (triggered every 30 seconds), slow GC may pause + * the timers and pretend that the parent process of the fork JVM does not exist. + * + *
+ * + * The {@code native} is very fast checker. + * It is useful mechanism on Unix based systems, Linux distributions and Alpine/BusyBox Linux. + * See the JIRA SUREFIRE-1631 for Windows issues. + * + *
+ * + * Another useful configuration parameter is {@code forkedProcessTimeoutInSeconds}. + *
+ * See the Frequently Asked Questions page with more details:
+ * + * http://maven.apache.org/surefire/maven-surefire-plugin/faq.html#kill-jvm + *
+ * + * http://maven.apache.org/surefire/maven-failsafe-plugin/faq.html#kill-jvm + * + *
+ * + * Example of use: + *
+ * mvn test -Dsurefire.enableProcessChecker=all + * + * @since 3.0.0-M4 + */ + @Parameter( property = "surefire.enableProcessChecker" ) + private String enableProcessChecker; + @Override protected int getRerunFailingTestsCount() { @@ -736,4 +798,21 @@ protected final boolean hasSuiteXmlFiles() { return suiteXmlFiles != null && suiteXmlFiles.length != 0; } + + @Override + protected final String[] getExcludedEnvironmentVariables() + { + return excludedEnvironmentVariables == null ? new String[0] : excludedEnvironmentVariables; + } + + void setExcludedEnvironmentVariables( String[] excludedEnvironmentVariables ) + { + this.excludedEnvironmentVariables = excludedEnvironmentVariables; + } + + @Override + protected final String getEnableProcessChecker() + { + return enableProcessChecker; + } } diff --git a/maven-surefire-plugin/src/site/apt/examples/configuring-classpath.apt.vm b/maven-surefire-plugin/src/site/apt/examples/configuring-classpath.apt.vm index 75e1e9d9f5..76d9b8776c 100644 --- a/maven-surefire-plugin/src/site/apt/examples/configuring-classpath.apt.vm +++ b/maven-surefire-plugin/src/site/apt/examples/configuring-classpath.apt.vm @@ -103,7 +103,7 @@ Removing Dependency Classpath Elements ${project.version} - org.apache.commons:commons-email + org.apache.commons:commons-email diff --git a/maven-surefire-plugin/src/site/apt/examples/cwd.apt.vm b/maven-surefire-plugin/src/site/apt/examples/cwd.apt.vm new file mode 100644 index 0000000000..36248cd446 --- /dev/null +++ b/maven-surefire-plugin/src/site/apt/examples/cwd.apt.vm @@ -0,0 +1,50 @@ + ------ + Special characters in directories + ------ + Tibor Digana + ------ + 2019-05-10 + ------ + + ~~ 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. + + ~~ NOTE: For help with the syntax of this file, see: + ~~ http://maven.apache.org/doxia/references/apt-format.html + + +Working Directory with special characters + + You can use a colon (<<<:>>>) in the cwd on Linux but you have to turn the path separator from colon to + some other character, see {{{https://issues.apache.org/jira/browse/SUREFIRE-1617}SUREFIRE-1617}} + + You should change the classpath separator (we do not guarantee that your application and test would run seamlessly) + in order to avoid collisions with paths within the forked JVM: + ++---+ +-Dpath.separator=; ++---+ + + For more information about the configuration parameter <<>> + see the chapter {{{./fork-options-and-parallel-execution.html#Forked_Test_Execution}Forked Test Execution}}. + + +Local Repository with special characters + + The plugin supports special characters (i.e. a colon (<<<:>>>)) in the path of Maven local repository. + The compiler does not support it and therefore the sources have to be compiled by another command in advance. + diff --git a/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm b/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm index e5d3408b95..15c72ef688 100644 --- a/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm +++ b/maven-surefire-plugin/src/site/apt/examples/inclusion-exclusion.apt.vm @@ -209,4 +209,44 @@ Inclusions and Exclusions of Tests Multiple formats can be additionally combined. This syntax can be used in parameters: <<>>, <<>>, <<>>, <<>>, <<>>. +* Tests from dependencies + + By default, ${thisPlugin} will only scan for test classes to execute in the configured <<>>. To + have the plugin scan dependencies to find test classes to execute, use the <<>> configuration. + Dependencies can be specified using the <<>> format, and must already + be <<>> elements in scope. + + Support for version, type and classifier was introduced in version <<<3.0.0-M4>>>. When using earlier versions, + ${thisPlugin} will fail with an <<>> if more than groupId and artifactId are specified. + ++---+ + + [...] + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + org.acme:project-a + org.acme:project-b:test-jar + org.acme:project-c:*:tests-jdk15 + + + + + + [...] + ++---+ + + The configuration above will search for test classes in: + + * All dependencies with the groupId <<>> and artifactId <<>> + + * All dependencies with the groupId <<>> and artifactId <<>> and type <<>> + + * All dependencies with the groupId <<>> and artifactId <<>> and classifier <<>> diff --git a/maven-surefire-plugin/src/site/apt/examples/junit-platform.apt.vm b/maven-surefire-plugin/src/site/apt/examples/junit-platform.apt.vm index f0cc7b4b5c..58741b42d4 100644 --- a/maven-surefire-plugin/src/site/apt/examples/junit-platform.apt.vm +++ b/maven-surefire-plugin/src/site/apt/examples/junit-platform.apt.vm @@ -40,7 +40,7 @@ Using JUnit 5 Platform org.junit.jupiter junit-jupiter-engine - 5.3.1 + 5.4.0 test [...] @@ -63,7 +63,7 @@ Using JUnit 5 Platform org.junit.vintage junit-vintage-engine - 5.3.1 + 5.4.0 test [...] @@ -74,6 +74,112 @@ Using JUnit 5 Platform see the {{{https://junit.org/junit5/}JUnit 5 web site}} and the {{{https://junit.org/junit5/docs/current/user-guide/}JUnit 5 User Guide}}. +* Smart Resolution of Jupiter Engine and Vintage Engine for JUnit4 (since plugin version 3.0.0-M4) + + JUnit5 API artifact and your test sources become isolated from engine. + + Normally the developer does not want to access internal classes of JUnit5 engine (e.g. <<<5.4.0>>>). In this example + the POM has only Jupiter API dependency in test classpath. + ++---+ + + [...] + + org.junit.jupiter + junit-jupiter-api + 5.4.0 + test + + [...] + +... + + + [...] + + ${project.groupId} + ${project.artifactId} + ${project.version} + [... configuration or goals and executions ...] + + [...] + + +... ++---+ + + In the following example the engine artifact appears in plugin dependencies and the engine is resolved by the plugin + and downloaded from a remote repository for plugins. You may want to update the version of engine with fixed bugs in + <<<5.3.2>>> but the API version <<<5.3.0>>> stays intact! + ++---+ + + [...] + + org.junit.jupiter + junit-jupiter-api + 5.3.0 + test + + [...] + +... + + + [...] + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + org.junit.jupiter + junit-jupiter-engine + 5.3.2 + + + + [...] + + +... ++---+ + + + Similar with JUnit4 in test dependencies of your project POM. The Vintage engine artifact is in plugin dependencies. + ++---+ + + [...] + + junit + junit + 4.12 + test + + [...] + +... + + + ... + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + org.junit.vintage + junit-vintage-engine + 5.4.0 + + + + + +... ++---+ + * Provider Selection If nothing is configured, Surefire detects which JUnit version to use by the following algorithm: @@ -103,11 +209,12 @@ else you can execute <<>> from the command line. -* Filtering by Test Class Names +* Filtering by Test Class Names for Maven ${thisPlugin} - The Maven Surefire Plugin will scan for test classes whose fully qualified names match + The Maven ${thisPlugin} Plugin will scan for test classes whose fully qualified names match the following patterns. +#{if}(${project.artifactId}=="maven-surefire-plugin") * <<<**/Test*.java>>> * <<<**/*Test.java>>> @@ -115,14 +222,21 @@ else * <<<**/*Tests.java>>> * <<<**/*TestCase.java>>> +#{else} + * <<<**/IT*.java>>> + + * <<<**/*IT.java>>> + + * <<<**/*ITCase.java>>> +#{end} Moreover, it will exclude all nested classes (including static member classes) by default. Note, however, that you can override this default behavior by configuring explicit - `include` and `exclude` rules in your `pom.xml` file. For example, to keep Maven Surefire + `include` and `exclude` rules in your `pom.xml` file. For example, to keep Maven ${thisPlugin} from excluding static member classes, you can override its exclude rules. -* Overriding exclude rules of Maven Surefire +* Overriding exclude rules of Maven ${thisPlugin} +---+ ... @@ -203,3 +317,56 @@ else ... +---+ + + +* Surefire Extensions and Reports Configuration for @DisplayName + + Since plugin version 3.0.0-M4 you can use fine grained configuration of reports and enable phrased names together + with <<<@DisplayName>>> in you tests. + This is the complete list of attributes of particular objects. You do not have to specify e.g. <<>>, + <<>> and <<>>. The boolean values reach default values <<>> if not specified otherwise. + ++---+ +... + + + ... + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + false + 3.0 + false + true + true + true + + + false + UTF-8 + false + + + false + false + true + true + + + + + +... ++---+ + + Default implementations of these extensions are + <<>>, + <<>>, and + <<>>. + + The aim of extensions is to let the users customizing the default behavior. We are keen on listing useful + extensions on Apache Maven Surefire site if you propagate your extensions on GitHub. + diff --git a/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm b/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm index 26c7e428e2..cd082c5ecf 100644 --- a/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm +++ b/maven-surefire-plugin/src/site/apt/examples/shutdown.apt.vm @@ -70,6 +70,10 @@ Shutdown of Forked JVM (pressed CTRL+C, received SIGTERM signal), forked JVM is killed after timing out waiting period. + + NOTICE: After version <<<3.0.0-M4>>> this feature has to be enabled by setting the configuration + parameter <<>> to <<>> or <<>>. + * Shutdown of forked JVM by stopping the build After the master process of the build is shutdown by sending SIGTERM signal @@ -103,6 +107,10 @@ Shutdown of Forked JVM +---+ + + NOTICE: After version <<<3.0.0-M4>>> this feature has to be enabled by setting the configuration + parameter <<>> to <<>> or <<>> or <<>>. + * Shutdown of forked JVM after certain timeout Using parameter <<>> forked JVMs diff --git a/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm b/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm index 06ed15067f..258f88b693 100644 --- a/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm +++ b/maven-surefire-plugin/src/site/apt/examples/skip-after-failure.apt.vm @@ -44,7 +44,7 @@ Prerequisite Use ${project.artifactId} 2.19 or higher, JUnit 4.0 or higher, or TestNG 5.10 or higher. - If version of TestNG is lover than 5.10 while the parameter + If version of TestNG is lower than 5.10 while the parameter <<>> is set, the plugin fails with error: <<<[ERROR] Failed to execute goal ...: Parameter "skipAfterFailureCount" @@ -53,7 +53,7 @@ Prerequisite - If version of JUnit is lover than 4.0 while the parameter + If version of JUnit is lower than 4.0 while the parameter <<>> is set, the plugin fails with error: <<<[ERROR] Failed to execute goal ...: Parameter "skipAfterFailureCount" diff --git a/maven-surefire-plugin/src/site/apt/featurematrix.apt.vm b/maven-surefire-plugin/src/site/apt/featurematrix.apt.vm index d4024a211e..05d13bc9e4 100644 --- a/maven-surefire-plugin/src/site/apt/featurematrix.apt.vm +++ b/maven-surefire-plugin/src/site/apt/featurematrix.apt.vm @@ -39,6 +39,14 @@ Feature Matrix | run >1 individual test method in a class | N | Y | Y | Y | N | ?(*1) | *---------------------------------------------+------------+----------+------------+-----------+----------+----------------------+ | parallel support | N | N | Y | Y | N | N | +*---------------------------------------------+------------+----------+------------+-----------+----------+----------------------+ +| custom run-listener | N | Y | Y | Y | - | N | +*---------------------------------------------+------------+----------+------------+-----------+----------+----------------------+ +| re-run count | N | Y | Y | N | N | Y(*3) | +*---------------------------------------------+------------+----------+------------+-----------+----------+----------------------+ +| skip after failure count | N | Y | Y | Y | N | N | +*---------------------------------------------+------------+----------+------------+-----------+----------+----------------------+ +| Surefire Extensions | Y | Y | Y | Y | Y | Y(*2) | *---------------------------------------------+------------+----------+------------+-----------+----------+----------------------+ @@ -50,4 +58,9 @@ Feature Matrix (*1) The JUnit 5 Platform supports running multiple individual test methods in a single class, but there are some corner cases that are not supported, yet: {{{https://github.com/junit-team/junit5/issues/1343}junit-team/junit5#1343}} - and {{{https://github.com/junit-team/junit5/issues/1406}junit-team/junit5#1406)}}. \ No newline at end of file + and {{{https://github.com/junit-team/junit5/issues/1406}junit-team/junit5#1406)}}. + + (*2) 3 extensions related to JUnit5 annotation <<>>. + + (*3) Since 3.0.0-M4 + \ No newline at end of file diff --git a/maven-surefire-plugin/src/site/apt/index.apt.vm b/maven-surefire-plugin/src/site/apt/index.apt.vm index 90bc72f4bc..3be247f94b 100644 --- a/maven-surefire-plugin/src/site/apt/index.apt.vm +++ b/maven-surefire-plugin/src/site/apt/index.apt.vm @@ -34,46 +34,74 @@ Maven ${thisPlugin} Plugin Requirements: Maven 3.x and JDK 1.7 or higher. Due to wrong formatting of console text messages in Maven Version prior to 3.1.0 it is highly recommended to use Maven 3.1.0 or higher. -*---------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -||Roadmap ||Release Targets | -*---------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | Maven API 3.0 and Java 1.7 \ | -| | \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1493}Maven Plugin API 3.0}} \ | -| 3.0.0-M1 | {{{https://issues.apache.org/jira/browse/SUREFIRE-1474}Java 1.7 as minimum}} \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1212}@Component is deprecated. @Parameter should be used instead}} \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1588}Surefire manifest jar classloading broken on latest Debian/Ubuntu Java8}} \ | -| | {{{https://issues.apache.org/jira/projects/SUREFIRE/versions/12342871}See the Release Notes for the version 3.0.0-M1}} \ | -*---------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | Fixed: JDK9 and Windows Class-Path issues, 3.0 and Legacy Report XSD, 3.0.0-M2 shadefire \ | -| | \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1568}Fixed JDK9+ (Jigsaw) modular paths (module-info.java) having white spaces on file system}} \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1593}Windows slashes appear in relative paths of Class-Path in MANIFEST.MF (Boot Manifest-JAR)}} \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1602}Surefire fails loading class ForkedBooter when using a sub-directory pom file}} \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1605}Plugin fails if used Toolchains together with JDK9+ and (Jigsaw) modular paths (module-info.java)}} \ | -| 3.0.0-M2 | {{{https://issues.apache.org/jira/browse/SUREFIRE-1590}3.0 and Legacy Report XSD}} \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1600}3.0.0-M2 shadefire}} \ | -| | \ | -| | Feature: Option to switch-off Java 9 modules \ | -| | \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1531}Option to switch-off Java 9 modules}} \ | -| | \ | -| | {{{https://issues.apache.org/jira/projects/SUREFIRE/versions/12344396}See the Release Notes for the version 3.0.0-M2}} \ | -*---------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| | Fixed: maven-surefire-report-plugin supports JDK11, JUnit5 issues, deprecated skipTests in Failsafe plugin, used ShadeFire 3.0.0-M2 \ | -| | \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1613}maven-surefire-report-plugin fails on JDK 11}} \ | -| 3.0.0-M3 | {{{https://issues.apache.org/jira/browse/SUREFIRE-1614}JUnit Runner that writes to System.out corrupts Surefire's STDOUT when using JUnit's Vintage Engine}} \ | -| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1616}Smart stacktrace in test summary should not print JUnit5 assertion exception type}} \ | -| | {{https://issues.apache.org/jira/browse/SUREFIRE-1611}Deprecate skipTests in Failsafe Plugin}} \ | -| | {{{https://issues.apache.org/jira/projects/SUREFIRE/versions/12342872}See the Release Notes for the version 3.0.0-M3}} \ | -*---------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 3.0.0-M4 | New interprocess communication and TCP/IP which fixes current blocker and critical bugs. | -*---------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 3.0.0-M5 | Extensions API | -*---------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| 3.0.0-M6 | Breaking backwards compatibility with system properties in configuration parameters, removing deprecated configuration parameters and removing deprecated code, etc. | -*---------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + This is the road map of the development, see the {{{https://github.com/apache/maven-surefire/pull/251}GH}}. + +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +||Versions ||Release Targets | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Maven API 3.0 and Java 1.7 \ | +| | \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1493}Maven Plugin API 3.0}} \ | +| 3.0.0-M1 | {{{https://issues.apache.org/jira/browse/SUREFIRE-1474}Java 1.7 as minimum}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1212}@Component is deprecated. @Parameter should be used instead}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1588}Surefire manifest jar classloading broken on latest Debian/Ubuntu Java8}} \ | +| | {{{https://issues.apache.org/jira/projects/SUREFIRE/versions/12342871}See the Release Notes for the version 3.0.0-M1}} \ | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Fixed: JDK9 and Windows Class-Path issues, 3.0 and Legacy Report XSD, 3.0.0-M2 shadefire \ | +| | \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1568}Fixed JDK9+ (Jigsaw) modular paths (module-info.java) having white spaces on file system}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1593}Windows slashes appear in relative paths of Class-Path in MANIFEST.MF (Boot Manifest-JAR)}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1602}Surefire fails loading class ForkedBooter when using a sub-directory pom file}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1605}Plugin fails if used Toolchains together with JDK9+ and (Jigsaw) modular paths (module-info.java)}} \ | +| 3.0.0-M2 | {{{https://issues.apache.org/jira/browse/SUREFIRE-1590}3.0 and Legacy Report XSD}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1600}3.0.0-M2 shadefire}} \ | +| | \ | +| | Feature: Option to switch-off Java 9 modules \ | +| | \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1531}Option to switch-off Java 9 modules}} \ | +| | \ | +| | {{{https://issues.apache.org/jira/projects/SUREFIRE/versions/12344396}See the Release Notes for the version 3.0.0-M2}} \ | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Fixed: maven-surefire-report-plugin supports JDK11, JUnit5 issues, deprecated skipTests in Failsafe plugin, used ShadeFire 3.0.0-M2 \ | +| | \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1613}maven-surefire-report-plugin fails on JDK 11}} \ | +| 3.0.0-M3 | {{{https://issues.apache.org/jira/browse/SUREFIRE-1614}JUnit Runner that writes to System.out corrupts Surefire's STDOUT when using JUnit's Vintage Engine}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1616}Smart stacktrace in test summary should not print JUnit5 assertion exception type}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1611}Deprecate skipTests in Failsafe Plugin}} \ | +| | {{{https://issues.apache.org/jira/projects/SUREFIRE/versions/12342872}See the Release Notes for the version 3.0.0-M3}} \ | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Provided 3 extensions of reporters which can be used to customize XML report, console and file reporters. It is very useful for JUnit5 users. \ | +| | We reworked the internal implementation so that new commands and events can be easily added. The impl is located in a center point and it is a prerequisite in next versions. \ | +| 3.0.0-M4 | Provided bug fixes for Docker Alpine/BusyBox Linux, JUnit5 and 43 more. \ | +| | \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1222}ForkClient attempts to consume unrelated lines}} \ | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Test Report tasks (prerequisite: SUREFIRE-1222 in 3.0.0-M4) \ | +| | New interprocess communication with TCP/IP which fixed current blocker and critical bugs. \ | +| | Provided extensions which can be used to customize this interprocess communication in plugin configuration. It is internally used to switch over the pipes and TCP connector. \ | +| | (1) We will identify the test by UniqueId in SimpleReportEntry and not by the traditional combination of class/method name. (ready for parameterized tests and a coherent re-run) \ | +| | (2) TestSetRunListener should not cache test event and make any guess about the impl in StatelessXmlReporter. TestSetRunListener should only forward events to multiple reporters.\ | +| 3.0.0-M5 | (3) Fire and consume more events (normal run start/end, re-run start/end) \ | +| | (4) StatelessXmlReporter repeatedly generates XML report. It is stateful report and won't work if re-run or parallel executions send test events out of order. Prerequisite: 1-3 \ | +| | \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1658}TCP/IP Channel for forked Surefire JVM. Extensions API and SPI. Polymorphism for remote and local process communication.}} \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1661}ConsoleOutputFileReporter should support parallel execution of test-sets}} \ | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Providers implementation and API \ | +| | More test events used to negotiate tests to run on particular fork JVM. It is useful in situations when the tests are filtered by group/category or classpath scan with file \ | +| 3.0.0-M6 | filter (fork JVM is preferable over Maven JVM) and used in Test List Processor (3.0.0-M7). We will keep IsolatedClassLoader for extension 'Test List Processor' so that the user \ | +| | can decide the JVM where the tests will be searched. Possibly JUnit5 provider will be able to scan classes by annotations, see launcher.discover(), and negotiate over the forks. \ | \ | +| | \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-1535}Surefire unable to run testng suites in parallel}} \ | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Extensions API to customize test-set with test list processor (prerequisite: 3.0.0-M6) \ | +| 3.0.0-M7 | (possibly the scan of classpath based on annotations, currently the scan is done based on pattern of file name e.g. -Dtest=MyTest) \ | +| | \ | +| | {{{https://issues.apache.org/jira/browse/SUREFIRE-726}Test list preprocessor support for tests to be run}} \ | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| 3.0.0-M8 | Breaking backwards compatibility with system properties in configuration parameters, removing deprecated configuration parameters and removing deprecated code, etc. \ | +*---------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ #{if}(${project.artifactId}=="maven-surefire-plugin") The Surefire Plugin is used during the <<>> phase of the build @@ -165,10 +193,8 @@ mvn verify * Usage General instructions on how to use the ${thisPlugin} Plugin can be found on the {{{./usage.html}usage page}}. Some more - specific use cases are described in the examples listed below. - #{if}(${project.artifactId}=="maven-surefire-plugin") Last but not least, users occasionally contribute - additional examples, tips or errata to the - {{{http://docs.codehaus.org/display/MAVENUSER/Surefire+Plugin}plugin's wiki page}}.#{end} + specific use cases are described in the examples listed below. Additionally, users can contribute to the + {{{https://github.com/apache/maven-surefire}GitHub project}}. In case you still have questions regarding the plugin's usage, please have a look at the {{{./faq.html}FAQ}} and feel free to contact the {{{./mail-lists.html}user mailing list}}. The posts to the mailing list are archived and could diff --git a/maven-surefire-plugin/src/site/fml/faq.fml b/maven-surefire-plugin/src/site/fml/faq.fml index 96053cf171..83f3655073 100644 --- a/maven-surefire-plugin/src/site/fml/faq.fml +++ b/maven-surefire-plugin/src/site/fml/faq.fml @@ -44,9 +44,8 @@ under the License.

Visit this link for your reference, - - | Attaching tests - + Attaching tests. + Also see the examples for Inclusions and Exclusions of Tests.

@@ -157,5 +156,19 @@ under the License.

+ + The files cannot be deleted when Jenkins CI killed Maven process and the tests still continue running. + +

+ Surefire and Failsafe plugin may kill forked Surefire JVM when the standard-input stream is closed. + This works when you stop Maven process by CTRL+C but it is not guaranteed on all platforms and this mechanism + will be removed after the version 3.0.0-M5 (setup of TCP sockets for interprocess communication). + The Surefire and Failsafe 3.0.0-M4 disabled mechanism PINGing parent process and natively killing mechanism. + In order to enable these mechanisms, see the documentation of the configuration parameter + "enableProcessChecker" and enable these mechanisms. These mechanisms have some drawbacks regarding your + OS systems and GC, therefore see the documentation for the parameter "enableProcessChecker". +

+
+
diff --git a/maven-surefire-plugin/src/site/site.xml b/maven-surefire-plugin/src/site/site.xml index fb60c3bb7d..87efd78fc8 100644 --- a/maven-surefire-plugin/src/site/site.xml +++ b/maven-surefire-plugin/src/site/site.xml @@ -43,6 +43,7 @@ + diff --git a/maven-surefire-plugin/src/test/java/org/apache/maven/plugin/surefire/SurefirePluginTest.java b/maven-surefire-plugin/src/test/java/org/apache/maven/plugin/surefire/SurefirePluginTest.java index 4cbbf0047d..3c759b1bd2 100644 --- a/maven-surefire-plugin/src/test/java/org/apache/maven/plugin/surefire/SurefirePluginTest.java +++ b/maven-surefire-plugin/src/test/java/org/apache/maven/plugin/surefire/SurefirePluginTest.java @@ -1,4 +1,5 @@ package org.apache.maven.plugin.surefire; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,99 +19,89 @@ * under the License. */ - -import java.lang.reflect.Field; -import org.apache.maven.toolchain.Toolchain; - import junit.framework.TestCase; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.surefire.suite.RunResult; -public class SurefirePluginTest - extends TestCase -{ +import static org.fest.assertions.Assertions.assertThat; - public void testForkMode() - throws NoSuchFieldException, IllegalAccessException +/** + * + */ +public class SurefirePluginTest extends TestCase +{ + public void testDefaultIncludes() { - SurefirePlugin surefirePlugin = new SurefirePlugin(); - setFieldValue( surefirePlugin, "toolchain", new MyToolChain() ); - setFieldValue( surefirePlugin, "forkMode", "never" ); - assertEquals( "once", surefirePlugin.getEffectiveForkMode() ); + assertThat( new SurefirePlugin().getDefaultIncludes() ) + .containsOnly( "**/Test*.java", "**/*Test.java", "**/*Tests.java", "**/*TestCase.java" ); } - public void testForkCountComputation() + public void testReportSchemaLocation() { - SurefirePlugin surefirePlugin = new SurefirePlugin(); - assertConversionFails( surefirePlugin, "nothing" ); - - assertConversionFails( surefirePlugin, "5,0" ); - assertConversionFails( surefirePlugin, "5.0" ); - assertConversionFails( surefirePlugin, "5,0C" ); - assertConversionFails( surefirePlugin, "5.0CC" ); - - assertForkCount( surefirePlugin, 5, "5" ); - - int availableProcessors = Runtime.getRuntime().availableProcessors(); - assertForkCount( surefirePlugin, 3*availableProcessors, "3C" ); - assertForkCount( surefirePlugin, (int) ( 2.5*availableProcessors ), "2.5C" ); - assertForkCount( surefirePlugin, availableProcessors, "1.0001 C" ); - assertForkCount( surefirePlugin, 1, 1d / ( (double) availableProcessors + 1 ) + "C" ); - assertForkCount( surefirePlugin, 0, "0 C" ); + assertThat( new SurefirePlugin().getReportSchemaLocation() ) + .isEqualTo( "https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report-3.0.xsd" ); } - private void assertForkCount( SurefirePlugin surefirePlugin, int expected, String value ) + public void testFailIfNoTests() throws Exception { - assertEquals( expected, surefirePlugin.convertWithCoreCount( value )); + RunResult runResult = new RunResult( 0, 0, 0, 0 ); + try + { + SurefirePlugin plugin = new SurefirePlugin(); + plugin.setFailIfNoTests( true ); + plugin.handleSummary( runResult, null ); + } + catch ( MojoFailureException e ) + { + assertThat( e.getLocalizedMessage() ) + .isEqualTo( "No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)" ); + return; + } + fail( "Expected MojoFailureException with message " + + "'No tests were executed! (Set -DfailIfNoTests=false to ignore this error.)'" ); } - private void assertConversionFails( SurefirePlugin surefirePlugin, String value ) + public void testTestFailure() throws Exception { - try { - surefirePlugin.convertWithCoreCount( value ); - } catch (NumberFormatException nfe) + RunResult runResult = new RunResult( 1, 0, 1, 0 ); + try + { + SurefirePlugin plugin = new SurefirePlugin(); + plugin.handleSummary( runResult, null ); + } + catch ( MojoFailureException e ) { + assertThat( e.getLocalizedMessage() ) + .isEqualTo( "There are test failures.\n\nPlease refer to null " + + "for the individual test results.\nPlease refer to dump files (if any exist) " + + "[date].dump, [date]-jvmRun[N].dump and [date].dumpstream." ); return; } - fail( "Expected NumberFormatException when converting " + value ); + fail( "Expected MojoFailureException with message " + + "'There are test failures.\n\nPlease refer to null " + + "for the individual test results.\nPlease refer to dump files (if any exist) " + + "[date].dump, [date]-jvmRun[N].dump and [date].dumpstream.'" ); } - private void setFieldValue( SurefirePlugin plugin, String fieldName, Object value ) - throws NoSuchFieldException, IllegalAccessException + public void testPluginName() { - Field field = findField( plugin.getClass(), fieldName ); - field.setAccessible( true ); - field.set( plugin, value ); - + assertThat( new SurefirePlugin().getPluginName() ) + .isEqualTo( "surefire" ); } - private Field findField( Class clazz, String fieldName ) + public void testShouldGetNullEnv() { - while ( clazz != null ) - { - try - { - return clazz.getDeclaredField( fieldName ); - } - catch ( NoSuchFieldException e ) - { - clazz = clazz.getSuperclass(); - } - } - throw new IllegalArgumentException( "Field not found" ); + SurefirePlugin plugin = new SurefirePlugin(); + assertThat( plugin.getExcludedEnvironmentVariables() ) + .hasSize( 0 ); } - private class MyToolChain - implements Toolchain + public void testShouldGetEnv() { - @Override - public String getType() - { - return null; - } - - @Override - public String findTool( String s ) - { - return null; - } + SurefirePlugin plugin = new SurefirePlugin(); + plugin.setExcludedEnvironmentVariables( new String[] { "ABC", "KLM" } ); + assertThat( plugin.getExcludedEnvironmentVariables() ) + .hasSize( 2 ) + .contains( "ABC", "KLM" ); } } diff --git a/maven-surefire-report-plugin/pom.xml b/maven-surefire-report-plugin/pom.xml index 0262374913..8ab8e7127f 100644 --- a/maven-surefire-report-plugin/pom.xml +++ b/maven-surefire-report-plugin/pom.xml @@ -24,7 +24,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 org.apache.maven.plugins @@ -57,11 +57,6 @@ maven-core provided
- - org.apache.maven - maven-model - provided - org.apache.maven maven-plugin-api @@ -183,13 +178,39 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin + ${jvm.args.tests} ${jacoco.agent} + + **/JUnit4SuiteTest.java + org.fusesource.jansi:jansi + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + diff --git a/maven-surefire-report-plugin/src/site/apt/index.apt b/maven-surefire-report-plugin/src/site/apt/index.apt index e1895a1b44..738b286b55 100644 --- a/maven-surefire-report-plugin/src/site/apt/index.apt +++ b/maven-surefire-report-plugin/src/site/apt/index.apt @@ -53,10 +53,7 @@ Maven Surefire Report Plugin * Goals Overview - The Surefire Report Plugin only has one goal (the other is a workaround): - - * {{{./failsafe-report-only-mojo.html}surefire-report:failsafe-report-only}} This goal does not - run the tests, it only builds the IT reports. See {{{https://issues.apache.org/jira/browse/SUREFIRE-257}SUREFIRE-257}} + The Surefire Report Plugin has three goals: * {{{./report-mojo.html}surefire-report:report}} Generates the test results report into HTML format. @@ -65,6 +62,9 @@ Maven Surefire Report Plugin not run the tests, it only builds the reports. It is provided as a work around for {{{https://issues.apache.org/jira/browse/SUREFIRE-257}SUREFIRE-257}} + * {{{./failsafe-report-only-mojo.html}surefire-report:failsafe-report-only}} This goal does not + run the tests, it only builds the IT reports. See {{{https://issues.apache.org/jira/browse/SUREFIRE-257}SUREFIRE-257}} + [] As of version 2.8 this plugin requires Maven Site Plugin 2.1 or newer to work properly. Version 2.7.2 and @@ -73,9 +73,8 @@ Maven Surefire Report Plugin * Usage General instructions on how to use the Surefire Report Plugin can be found on the {{{./usage.html}usage page}}. Some more - specific use cases are described in the examples listed below. Last but not least, users occasionally contribute - additional examples, tips or errata to the - {{{http://docs.codehaus.org/display/MAVENUSER/Surefire+Report+Plugin}plugin's wiki page}}. + specific use cases are described in the examples listed below. Additionally, users can contribute to the + {{{https://github.com/apache/maven-surefire}GitHub project}}. In case you still have questions regarding the plugin's usage, please have a look at the {{{./faq.html}FAQ}} and feel free to contact the {{{./mail-lists.html}user mailing list}}. The posts to the mailing list are archived and could diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/JUnit4SuiteTest.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/JUnit4SuiteTest.java new file mode 100644 index 0000000000..bcf63cb3d5 --- /dev/null +++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/JUnit4SuiteTest.java @@ -0,0 +1,44 @@ +package org.apache.maven.plugins.surefire.report; + +/* + * 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 junit.framework.JUnit4TestAdapter; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class JUnit4SuiteTest extends TestCase +{ + public static Test suite() + { + TestSuite suite = new TestSuite(); + suite.addTest( new JUnit4TestAdapter( Surefire597Test.class ) ); + suite.addTest( new JUnit4TestAdapter( SurefireSchemaValidationTest.class ) ); + suite.addTestSuite( Surefire1183Test.class ); + suite.addTestSuite( SurefireReportMojoTest.class ); + return suite; + } +} diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire1183Test.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire1183Test.java index 7a47e16b20..2ce686d997 100644 --- a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire1183Test.java +++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire1183Test.java @@ -1,3 +1,5 @@ +package org.apache.maven.plugins.surefire.report; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -package org.apache.maven.plugins.surefire.report; - import org.apache.maven.doxia.site.decoration.DecorationModel; import org.apache.maven.doxia.siterenderer.Renderer; import org.apache.maven.doxia.siterenderer.RendererException; @@ -117,6 +117,6 @@ public void testCustomTitleAndDescriptionReport() assertTrue( report.exists() ); String htmlContent = FileUtils.fileRead ( report ); - assertTrue( htmlContent.contains ( "

Acceptance Test

" ) ); + assertTrue( htmlContent.contains ( "

Acceptance Test

" ) ); } } diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java index 02af6c4dfb..2f40a9f603 100644 --- a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java +++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Surefire597Test.java @@ -19,10 +19,11 @@ * under the License. */ -import org.apache.maven.doxia.module.xhtml.XhtmlSink; +import junit.framework.TestCase; +import org.apache.maven.doxia.module.xhtml5.Xhtml5Sink; +import org.apache.maven.doxia.sink.Sink; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger; -import org.junit.Test; import java.io.File; import java.io.StringWriter; @@ -37,9 +38,10 @@ * Prevent fom NPE if failure type and message is null however detail presents. */ public class Surefire597Test + extends TestCase { - @Test - public void corruptedTestCaseFailureWithMissingErrorTypeAndMessage() + @SuppressWarnings( "checkstyle:linelength" ) + public void testCorruptedTestCaseFailureWithMissingErrorTypeAndMessage() throws Exception { File basedir = new File( "." ).getCanonicalFile(); @@ -47,7 +49,9 @@ public void corruptedTestCaseFailureWithMissingErrorTypeAndMessage() ConsoleLogger log = new NullConsoleLogger(); SurefireReportGenerator gen = new SurefireReportGenerator( singletonList( report ), ENGLISH, true, null, log ); StringWriter writer = new StringWriter(); - gen.doGenerateReport( new SurefireReportMojo().getBundle( ENGLISH ), new XhtmlSink( writer ) {} ); + Sink sink = new Xhtml5Sink( writer ) + { }; + gen.doGenerateReport( new SurefireReportMojo().getBundle( ENGLISH ), sink ); String xml = writer.toString(); assertThat( xml, containsString( toSystemNewLine( "\n" @@ -97,7 +101,7 @@ public void corruptedTestCaseFailureWithMissingErrorTypeAndMessage() + "\n" + "\n" + "\n" - + "\n" + + "\n" + "\n" + "\n" + "\n" @@ -108,7 +112,7 @@ public void corruptedTestCaseFailureWithMissingErrorTypeAndMessage() assertThat( xml, containsString( toSystemNewLine( "
Success RateTime
\"\"
\"\"
MyTest11
\n" + "\n" - + "\n" + + "\n" + "\n" + "\n" + "\n" diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportMojoTest.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportMojoTest.java index 64c583e1e5..d4dedd1f17 100644 --- a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportMojoTest.java +++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportMojoTest.java @@ -44,6 +44,7 @@ /** * @author Allan Ramirez */ +@SuppressWarnings( "checkstyle:linelength" ) public class SurefireReportMojoTest extends AbstractMojoTestCase { @@ -198,7 +199,8 @@ public void testBasicSurefireReportIfReportingIsNull() assertTrue( idx < 0 ); } - + + @SuppressWarnings( "checkstyle:methodname" ) public void testBasicSurefireReport_AnchorTestCases() throws Exception { @@ -261,7 +263,7 @@ public void testSurefireReportSingleError() containsString( toSystemNewLine( "\n" + "\n" + "\n" @@ -346,7 +348,7 @@ public void testSurefireReportNestedClassTrimStackTrace() containsString( toSystemNewLine( "\n" + "\n" + "\n" @@ -409,7 +411,7 @@ public void testSurefireReportNestedClass() containsString( toSystemNewLine( "\n" + "\n" + "\n" @@ -496,7 +498,7 @@ public void testSurefireReportEnclosedTrimStackTrace() containsString( toSystemNewLine( "\n" + "\n" + "\n" @@ -558,7 +560,7 @@ public void testSurefireReportEnclosed() containsString( toSystemNewLine( "\n" + "\n" + "\n" diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireSchemaValidationTest.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireSchemaValidationTest.java index 008f2062ba..c8fe52f31d 100644 --- a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireSchemaValidationTest.java +++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/SurefireSchemaValidationTest.java @@ -28,20 +28,23 @@ import javax.xml.transform.stream.StreamSource; +import junit.framework.TestCase; import org.apache.maven.shared.utils.io.DirectoryScanner; import org.fest.assertions.Assertions; import org.junit.Assert; -import org.junit.Test; import org.xmlunit.validation.Languages; import org.xmlunit.validation.ValidationProblem; import org.xmlunit.validation.ValidationResult; import org.xmlunit.validation.Validator; +/** + * + */ public class SurefireSchemaValidationTest + extends TestCase { - - @Test - public void validate_XMLs_against_schema() + @SuppressWarnings( "checkstyle:methodname" ) + public void testValidate_XMLs_against_schema() throws Exception { File basedir = getProjectBasedir(); diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Utils.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Utils.java index d2cb04e5c4..0c689de3bb 100644 --- a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Utils.java +++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/Utils.java @@ -19,6 +19,9 @@ * under the License. */ +/** + * + */ public final class Utils { private Utils() diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/stubs/SurefireRepMavenProjectStub.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/stubs/SurefireRepMavenProjectStub.java index 155b68362a..d1f2c113bf 100644 --- a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/stubs/SurefireRepMavenProjectStub.java +++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/stubs/SurefireRepMavenProjectStub.java @@ -35,7 +35,7 @@ public class SurefireRepMavenProjectStub * {@inheritDoc} */ @Override - public List getReportPlugins() + public List getReportPlugins() { Reporting reporting = new Reporting(); diff --git a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/stubs/SurefireRepMavenProjectStub2.java b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/stubs/SurefireRepMavenProjectStub2.java index 23b1e4e7c4..0a41412505 100644 --- a/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/stubs/SurefireRepMavenProjectStub2.java +++ b/maven-surefire-report-plugin/src/test/java/org/apache/maven/plugins/surefire/report/stubs/SurefireRepMavenProjectStub2.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.List; + +import org.apache.maven.model.ReportPlugin; import org.apache.maven.plugin.testing.stubs.MavenProjectStub; /** @@ -33,8 +35,8 @@ public class SurefireRepMavenProjectStub2 * {@inheritDoc} */ @Override - public List getReportPlugins() + public List getReportPlugins() { - return new ArrayList(); + return new ArrayList<>(); } } diff --git a/pom.xml b/pom.xml index 3a8e07ad96..0506a8954c 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 pom Apache Maven Surefire @@ -50,6 +50,7 @@ surefire-logger-api surefire-api + surefire-extensions-api surefire-booter surefire-grouper surefire-providers @@ -60,13 +61,14 @@ maven-failsafe-plugin maven-surefire-report-plugin surefire-its + surefire-shared-utils ${maven.surefire.scm.devConnection} ${maven.surefire.scm.devConnection} https://github.com/apache/maven-surefire/tree/${project.scm.tag} - surefire-3.0.0-M3_vote-1 + surefire-3.0.0-M4_vote-1 jira @@ -88,12 +90,14 @@ 3.0 3.8.1 + 1.19 2.6 - 1.8 - 1.8.1 + 1.9 + 1.9.1 3.1.0 - 2.0.0-RC.1 + 2.0.4 + 0.8.5 scm:git:https://gitbox.apache.org/repos/asf/maven-surefire.git surefire-archives/surefire-LATEST @@ -105,6 +109,11 @@ + + org.apache.commons + commons-compress + ${commonsCompress} + org.apache.commons commons-lang3 @@ -191,16 +200,63 @@ org.apache.maven maven-toolchain 3.0-alpha-2 + + + org.apache.maven + maven-core + + + org.apache.maven + maven-compat + + org.apache.maven.shared maven-common-artifact-filters - 3.0.1 + 3.1.0 org.apache.maven.shared maven-plugin-testing-harness + + org.apache.maven.shared + maven-shared-utils + + + + + + commons-codec + commons-codec + 1.11 + + + org.apache.maven.shared + maven-artifact-transfer + 0.11.0 + + + org.apache.maven + maven-core + + + org.apache.maven + maven-artifact + + + org.codehaus.plexus + plexus-component-annotations + + + org.codehaus.plexus + plexus-utils + + + org.slf4j + slf4j-api + @@ -272,22 +328,27 @@ org.codehaus.plexus plexus-java - 1.0.1 + 1.0.3 org.junit.platform junit-platform-launcher - 1.3.1 + 1.3.2 org.junit.jupiter junit-jupiter-engine - 5.3.1 + 5.3.2 + + + org.junit.jupiter + junit-jupiter-params + 5.3.2 org.mockito mockito-core - 2.21.0 + 2.27.0 org.hamcrest @@ -314,6 +375,16 @@ powermock-api-mockito2 ${powermockVersion} + + org.powermock + powermock-reflect + ${powermockVersion} + + + org.javassist + javassist + 3.22.0-GA + junit @@ -334,12 +405,24 @@ org.assertj assertj-core 3.9.1 + com.google.code.findbugs jsr305 2.0.3 + + org.jacoco + org.jacoco.agent + runtime + ${jacocoVersion} + + + com.googlecode.junit-toolbox + junit-toolbox + 1.11 + @@ -421,6 +504,7 @@ -Xdoclint:all + UTF-8 @@ -428,29 +512,14 @@ org.codehaus.mojo animal-sniffer-maven-plugin 1.17 - - - signature-check - - check - - - - org.codehaus.mojo.signature - java17 - 1.0 - - - - maven-surefire-plugin - 3.0.0-M2 + 3.0.0-M3 false - ${jvm.args.tests} ${jacoco.agent} -Dnet.bytebuddy.experimental=true + ${jvm.args.tests} false false ${jdk.home}/bin/java @@ -471,40 +540,75 @@ maven-invoker-plugin - 3.0.1 + 3.2.0 org.jacoco jacoco-maven-plugin - 0.8.2 + ${jacocoVersion} + + + + **/failsafe/* + **/failsafe/**/* + **/surefire/* + **/surefire/**/* + + + **/HelpMojo.class + **/shadefire/**/* + org/jacoco/**/* + com/vladium/emma/rt/* + + + + + maven-site-plugin + 3.8.2 - org.jacoco - jacoco-maven-plugin + org.apache.rat + apache-rat-plugin - jacoco-agent + rat-check - prepare-agent + check + + + Jenkinsfile + README.md + .gitignore + .git/**/* + **/.github/** + **/.idea + **/.svn/**/* + **/*.iml + **/*.ipr + **/*.iws + **/*.versionsBackup + **/dependency-reduced-pom.xml + .repository/** + src/test/resources/**/* + src/test/resources/**/*.css + **/*.jj + src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider + + DEPENDENCIES + .m2/** + .m2 + .travis.yml + + - - jacoco.agent - true - true - false - false - - **/failsafe/* - **/failsafe/**/* - **/surefire/* - **/surefire/**/* - - org.apache.maven.plugins @@ -563,44 +667,33 @@ org.codehaus.mojo animal-sniffer-maven-plugin - - - org.apache.rat - apache-rat-plugin - rat-check + signature-check check - - Jenkinsfile - README.md - .gitignore - .git/**/* - **/.idea - **/.svn/**/* - **/*.iml - **/*.ipr - **/*.iws - **/*.versionsBackup - **/dependency-reduced-pom.xml - .repository/** - src/test/resources/**/* - src/test/resources/**/*.css - **/*.jj - src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider - - DEPENDENCIES - .m2/** - .m2 - .travis.yml - + + org.codehaus.mojo.signature + java17 + 1.0 + + + org.apache.maven.plugins + maven-checkstyle-plugin + + true + + + + org.jacoco + jacoco-maven-plugin + maven-deploy-plugin @@ -615,7 +708,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.0.0-M2 + 3.0.0-M3 diff --git a/src/site/site.xml b/src/site/site.xml index 447f71b24a..669e5425e0 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -33,7 +33,7 @@ org.apache.maven.skins maven-fluido-skin - 1.7 + 1.8 diff --git a/surefire-api/pom.xml b/surefire-api/pom.xml index f79930a79c..6a69c515cf 100644 --- a/surefire-api/pom.xml +++ b/surefire-api/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 surefire-api @@ -41,18 +41,43 @@ org.apache.maven.shared maven-shared-utils + + commons-codec + commons-codec + com.google.code.findbugs jsr305 provided + + org.mockito + mockito-core + test + + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin + ${jvm.args.tests} ${jacoco.agent} **/JUnit4SuiteTest.java @@ -61,7 +86,7 @@ org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 @@ -78,12 +103,17 @@ org.apache.maven.shared:maven-shared-utils + commons-codec:commons-codec - org.apache.maven.shared - org.apache.maven.surefire.shade.api.org.apache.maven.shared + org.apache.maven.shared.utils + org.apache.maven.surefire.shade.api.org.apache.maven.shared.utils + + + org.apache.commons.codec + org.apache.maven.surefire.shade.api.org.apache.commons.codec diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java index 7c794dc7fa..1ccc4eee58 100644 --- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatistics.java @@ -19,8 +19,7 @@ * under the License. */ -import java.util.StringTokenizer; -import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.util.internal.ClassMethod; /** * @author Kristian Rosenvold @@ -31,39 +30,33 @@ public class RunEntryStatistics private final int successfulBuilds; - private final String testName; + private final ClassMethod classMethod; - private RunEntryStatistics( int runTime, int successfulBuilds, String testName ) + RunEntryStatistics( int runTime, int successfulBuilds, String clazz, String method ) { - this.runTime = runTime; - this.successfulBuilds = successfulBuilds; - this.testName = testName; + this( runTime, successfulBuilds, new ClassMethod( clazz, method ) ); } - public static RunEntryStatistics fromReportEntry( ReportEntry previous ) + RunEntryStatistics( int runTime, int successfulBuilds, ClassMethod classMethod ) { - final Integer elapsed = previous.getElapsed(); - return new RunEntryStatistics( elapsed != null ? elapsed : 0, 0, previous.getName() ); + this.runTime = runTime; + this.successfulBuilds = successfulBuilds; + this.classMethod = classMethod; } - public static RunEntryStatistics fromValues( int runTime, int successfulBuilds, Class clazz, String testName ) + public ClassMethod getClassMethod() { - return new RunEntryStatistics( runTime, successfulBuilds, testName + "(" + clazz.getName() + ")" ); + return classMethod; } public RunEntryStatistics nextGeneration( int runTime ) { - return new RunEntryStatistics( runTime, this.successfulBuilds + 1, this.testName ); + return new RunEntryStatistics( runTime, successfulBuilds + 1, classMethod ); } public RunEntryStatistics nextGenerationFailure( int runTime ) { - return new RunEntryStatistics( runTime, 0, this.testName ); - } - - public String getTestName() - { - return testName; + return new RunEntryStatistics( runTime, 0, classMethod ); } public int getRunTime() @@ -75,20 +68,4 @@ public int getSuccessfulBuilds() { return successfulBuilds; } - - public static RunEntryStatistics fromString( String line ) - { - StringTokenizer tok = new StringTokenizer( line, "," ); - int successfulBuilds = Integer.parseInt( tok.nextToken() ); - int runTime = Integer.parseInt( tok.nextToken() ); - String className = tok.nextToken(); - return new RunEntryStatistics( runTime, successfulBuilds, className ); - } - - @Override - public String toString() - { - return successfulBuilds + "," + runTime + "," + testName; - } - } diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java index 1a685dc8bf..09a4445deb 100644 --- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java @@ -19,38 +19,41 @@ * under the License. */ - import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.util.internal.ClassMethod; -import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.File; -import java.io.FileNotFoundException; +import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; -import java.io.PrintWriter; -import java.io.Reader; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import java.util.Scanner; +import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import static java.lang.Integer.parseInt; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.sort; -import static org.apache.maven.plugin.surefire.runorder.RunEntryStatistics.fromReportEntry; -import static org.apache.maven.plugin.surefire.runorder.RunEntryStatistics.fromString; +import static org.apache.maven.surefire.util.internal.StringUtils.NL; /** * @author Kristian Rosenvold */ public final class RunEntryStatisticsMap { - private final Map runEntryStatistics; + private final Map runEntryStatistics; - public RunEntryStatisticsMap( Map runEntryStatistics ) + private RunEntryStatisticsMap( Map runEntryStatistics ) { this.runEntryStatistics = new ConcurrentHashMap<>( runEntryStatistics ); } @@ -66,7 +69,7 @@ public static RunEntryStatisticsMap fromFile( File file ) { try { - return fromReader( new FileReader( file ) ); + return fromStream( new FileInputStream( file ) ); } catch ( IOException e ) { @@ -79,62 +82,124 @@ public static RunEntryStatisticsMap fromFile( File file ) } } - static RunEntryStatisticsMap fromReader( Reader fileReader ) - throws IOException + static RunEntryStatisticsMap fromStream( InputStream fileReader ) { - Map result = new HashMap<>(); - BufferedReader bufferedReader = new BufferedReader( fileReader ); - String line = bufferedReader.readLine(); - while ( line != null ) + Map result = new HashMap<>(); + try ( Scanner scanner = new Scanner( fileReader, "UTF-8" ) ) { - if ( !line.startsWith( "#" ) ) + RunEntryStatistics previous = null; + while ( scanner.hasNextLine() ) { - final RunEntryStatistics stats = fromString( line ); - result.put( stats.getTestName(), stats ); + String line = scanner.nextLine(); + + if ( line.charAt( 0 ) == ' ' ) + { + previous = new RunEntryStatistics( previous.getRunTime(), + previous.getSuccessfulBuilds(), + previous.getClassMethod().getClazz(), + previous.getClassMethod().getMethod() + NL + line.substring( 1 ) ); + } + else + { + if ( previous != null ) + { + result.put( previous.getClassMethod(), previous ); + } + StringTokenizer tokenizer = new StringTokenizer( line, "," ); + + int methodIndex = 3; + + String successfulBuildsString = tokenizer.nextToken(); + int successfulBuilds = parseInt( successfulBuildsString ); + + methodIndex += successfulBuildsString.length(); + + String runTimeString = tokenizer.nextToken(); + int runTime = parseInt( runTimeString ); + + methodIndex += runTimeString.length(); + + String className = tokenizer.nextToken(); + + methodIndex += className.length(); + + String methodName = line.substring( methodIndex ); + + ClassMethod classMethod = new ClassMethod( className, methodName ); + previous = new RunEntryStatistics( runTime, successfulBuilds, classMethod ); + } + } + if ( previous != null ) + { + result.put( previous.getClassMethod(), previous ); } - line = bufferedReader.readLine(); } return new RunEntryStatisticsMap( result ); } - public void serialize( File file ) - throws FileNotFoundException + public void serialize( File statsFile ) + throws IOException { - FileOutputStream fos = new FileOutputStream( file ); - try ( PrintWriter printWriter = new PrintWriter( fos ) ) + if ( statsFile.isFile() ) + { + //noinspection ResultOfMethodCallIgnored + statsFile.delete(); + } + OutputStream os = new FileOutputStream( statsFile ); + try ( BufferedWriter writer = new BufferedWriter( new OutputStreamWriter( os, UTF_8 ), 64 * 1024 ) ) { List items = new ArrayList<>( runEntryStatistics.values() ); sort( items, new RunCountComparator() ); - for ( RunEntryStatistics item : items ) + for ( Iterator it = items.iterator(); it.hasNext(); ) { - printWriter.println( item.toString() ); + RunEntryStatistics item = it.next(); + ClassMethod test = item.getClassMethod(); + String line = item.getSuccessfulBuilds() + "," + item.getRunTime() + "," + test.getClazz() + ","; + writer.write( line ); + boolean wasFirstLine = false; + for ( Scanner scanner = new Scanner( test.getMethod() ); scanner.hasNextLine(); wasFirstLine = true ) + { + String methodLine = scanner.nextLine(); + if ( wasFirstLine ) + { + writer.write( ' ' ); + } + writer.write( methodLine ); + if ( scanner.hasNextLine() ) + { + writer.newLine(); + } + } + if ( it.hasNext() ) + { + writer.newLine(); + } } } } - public RunEntryStatistics findOrCreate( ReportEntry reportEntry ) + private RunEntryStatistics findOrCreate( ReportEntry reportEntry ) { - final RunEntryStatistics item = runEntryStatistics.get( reportEntry.getName() ); - return item != null ? item : fromReportEntry( reportEntry ); + ClassMethod classMethod = new ClassMethod( reportEntry.getSourceName(), reportEntry.getName() ); + RunEntryStatistics item = runEntryStatistics.get( classMethod ); + return item != null ? item : new RunEntryStatistics( reportEntry.getElapsed( 0 ), 0, classMethod ); } public RunEntryStatistics createNextGeneration( ReportEntry reportEntry ) { - final RunEntryStatistics newItem = findOrCreate( reportEntry ); - final Integer elapsed = reportEntry.getElapsed(); - return newItem.nextGeneration( elapsed != null ? elapsed : 0 ); + RunEntryStatistics newItem = findOrCreate( reportEntry ); + return newItem.nextGeneration( reportEntry.getElapsed( 0 ) ); } public RunEntryStatistics createNextGenerationFailure( ReportEntry reportEntry ) { - final RunEntryStatistics newItem = findOrCreate( reportEntry ); - final Integer elapsed = reportEntry.getElapsed(); - return newItem.nextGenerationFailure( elapsed != null ? elapsed : 0 ); + RunEntryStatistics newItem = findOrCreate( reportEntry ); + return newItem.nextGenerationFailure( reportEntry.getElapsed( 0 ) ); } public void add( RunEntryStatistics item ) { - runEntryStatistics.put( item.getTestName(), item ); + runEntryStatistics.put( item.getClassMethod(), item ); } static final class RunCountComparator @@ -169,12 +234,12 @@ public List> getPrioritizedTestsByFailureFirst( List> testsToR private List getPrioritizedTests( List> testsToRun, Comparator priorityComparator ) { - Map classPriorities = getPriorities( priorityComparator ); + Map classPriorities = getPriorities( priorityComparator ); List tests = new ArrayList<>(); for ( Class clazz : testsToRun ) { - Priority pri = (Priority) classPriorities.get( clazz.getName() ); + Priority pri = classPriorities.get( clazz.getName() ); if ( pri == null ) { pri = Priority.newTestClassPriority( clazz.getName() ); @@ -186,7 +251,7 @@ private List getPrioritizedTests( List> testsToRun, return tests; } - private List> transformToClasses( List tests ) + private static List> transformToClasses( List tests ) { List> result = new ArrayList<>(); for ( PrioritizedTest test : tests ) @@ -196,22 +261,19 @@ private List> transformToClasses( List tests ) return result; } - private Map getPriorities( Comparator priorityComparator ) + private Map getPriorities( Comparator priorityComparator ) { Map priorities = new HashMap<>(); - for ( Object o : runEntryStatistics.keySet() ) + for ( Entry testNames : runEntryStatistics.entrySet() ) { - String testNames = (String) o; - String clazzName = extractClassName( testNames ); + String clazzName = testNames.getKey().getClazz(); Priority priority = priorities.get( clazzName ); if ( priority == null ) { priority = new Priority( clazzName ); priorities.put( clazzName, priority ); } - - RunEntryStatistics itemStat = runEntryStatistics.get( testNames ); - priority.addItem( itemStat ); + priority.addItem( testNames.getValue() ); } List items = new ArrayList<>( priorities.values() ); @@ -255,16 +317,4 @@ public int compare( Priority o, Priority o1 ) return o.getMinSuccessRate() - o1.getMinSuccessRate(); } } - - - private static final Pattern PARENS = Pattern.compile( "^" + "[^\\(\\)]+" //non-parens - + "\\((" // then an open-paren (start matching a group) - + "[^\\\\(\\\\)]+" //non-parens - + ")\\)" + "$" ); // then a close-paren (end group match) - - String extractClassName( String displayName ) - { - Matcher m = PARENS.matcher( displayName ); - return m.find() ? m.group( 1 ) : displayName; - } } diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java index 09ea1221d7..aa37b3d1f7 100644 --- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java +++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionScheduler.java @@ -42,7 +42,7 @@ public ThreadedExecutionScheduler( int numThreads ) lists = new List[numThreads]; for ( int i = 0; i < numThreads; i++ ) { - lists[i] = new ArrayList>(); + lists[i] = new ArrayList<>(); } } @@ -56,7 +56,7 @@ public void addTest( PrioritizedTest prioritizedTest ) public List> getResult() { - List> result = new ArrayList>(); + List> result = new ArrayList<>(); int index = 0; boolean added; do diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java index 2b329ee5db..ec05580814 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/BaseProviderFactory.java @@ -36,7 +36,6 @@ import org.apache.maven.surefire.util.RunOrderCalculator; import org.apache.maven.surefire.util.ScanResult; -import java.io.PrintStream; import java.util.Collections; import java.util.List; import java.util.Map; @@ -51,12 +50,12 @@ public class BaseProviderFactory ProviderPropertiesAware, ProviderParameters, TestArtifactInfoAware, RunOrderParametersAware, MainCliOptionsAware, FailFastAware, ShutdownAware { - private static final int ROOT_CHANNEL = 0; - private final ReporterFactory reporterFactory; private final boolean insideFork; + private ForkedChannelEncoder forkedChannelEncoder; + private List mainCliOptions = emptyList(); private Map providerProperties; @@ -142,9 +141,8 @@ public void setClassLoaders( ClassLoader testClassLoader ) @Override public ConsoleStream getConsoleLogger() { - boolean trim = reporterConfiguration.isTrimStackTrace(); - PrintStream out = reporterConfiguration.getOriginalSystemOut(); - return insideFork ? new ForkingRunListener( out, ROOT_CHANNEL, trim ) : new DefaultDirectConsoleReporter( out ); + return insideFork ? new ForkingRunListener( forkedChannelEncoder, reporterConfiguration.isTrimStackTrace() ) + : new DefaultDirectConsoleReporter( reporterConfiguration.getOriginalSystemOut() ); } @Override @@ -259,4 +257,15 @@ public void setSystemExitTimeout( Integer systemExitTimeout ) { this.systemExitTimeout = systemExitTimeout; } + + @Override + public ForkedChannelEncoder getForkedChannelEncoder() + { + return forkedChannelEncoder; + } + + public void setForkedChannelEncoder( ForkedChannelEncoder forkedChannelEncoder ) + { + this.forkedChannelEncoder = forkedChannelEncoder; + } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java index be39ba7914..b71aec0751 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/CommandReader.java @@ -26,7 +26,6 @@ import java.io.DataInputStream; import java.io.EOFException; import java.io.IOException; -import java.io.PrintStream; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; @@ -42,7 +41,6 @@ import static java.lang.Thread.State.TERMINATED; import static java.lang.StrictMath.max; import static org.apache.maven.surefire.booter.Command.toShutdown; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_NEXT_TEST; import static org.apache.maven.surefire.booter.MasterProcessCommand.BYE_ACK; import static org.apache.maven.surefire.booter.MasterProcessCommand.NOOP; import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS; @@ -51,7 +49,6 @@ import static org.apache.maven.surefire.booter.MasterProcessCommand.TEST_SET_FINISHED; import static org.apache.maven.surefire.booter.MasterProcessCommand.decode; import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThread; -import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication; import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; import static org.apache.maven.surefire.util.internal.StringUtils.isNotBlank; @@ -189,7 +186,7 @@ public void removeListener( CommandListener listener ) } /** - * @return test classes which have been retrieved by {@link CommandReader#getIterableClasses(PrintStream)}. + * @return test classes which have been retrieved by {@link CommandReader#getIterableClasses(ForkedChannelEncoder)}. */ Iterator iterated() { @@ -200,18 +197,19 @@ Iterator iterated() * The iterator can be used only in one Thread. * Two simultaneous instances are not allowed for sake of only one {@link #nextCommandNotifier}. * - * @param originalOutStream original stream in current JVM process + * @param eventChannel original stream in current JVM process * @return Iterator with test classes lazily loaded as commands from the main process */ - Iterable getIterableClasses( PrintStream originalOutStream ) + Iterable getIterableClasses( ForkedChannelEncoder eventChannel ) { - return new ClassesIterable( originalOutStream ); + return new ClassesIterable( eventChannel ); } public void stop() { - if ( state.compareAndSet( NEW, TERMINATED ) || state.compareAndSet( RUNNABLE, TERMINATED ) ) + if ( !isStopped() ) { + state.set( TERMINATED ); makeQueueFull(); listeners.clear(); commandThread.interrupt(); @@ -253,32 +251,32 @@ private boolean insertToQueue( String test ) private final class ClassesIterable implements Iterable { - private final PrintStream originalOutStream; + private final ForkedChannelEncoder eventChannel; - ClassesIterable( PrintStream originalOutStream ) + ClassesIterable( ForkedChannelEncoder eventChannel ) { - this.originalOutStream = originalOutStream; + this.eventChannel = eventChannel; } @Override public Iterator iterator() { - return new ClassesIterator( originalOutStream ); + return new ClassesIterator( eventChannel ); } } private final class ClassesIterator implements Iterator { - private final PrintStream originalOutStream; + private final ForkedChannelEncoder eventChannel; private String clazz; private int nextQueueIndex; - private ClassesIterator( PrintStream originalOutStream ) + private ClassesIterator( ForkedChannelEncoder eventChannel ) { - this.originalOutStream = originalOutStream; + this.eventChannel = eventChannel; } @Override @@ -344,12 +342,7 @@ private void popUnread() private void requestNextTest() { - byte[] encoded = encodeStringForForkCommunication( ( (char) BOOTERCODE_NEXT_TEST ) + ",0,want more!\n" ); - synchronized ( originalOutStream ) - { - originalOutStream.write( encoded, 0, encoded.length ); - originalOutStream.flush(); - } + eventChannel.acquireNextTest(); } private boolean shouldFinish() @@ -405,22 +398,22 @@ public void run() if ( inserted ) { CommandReader.this.wakeupIterator(); - insertToListeners( command ); + callListeners( command ); } break; case TEST_SET_FINISHED: CommandReader.this.makeQueueFull(); isTestSetFinished = true; CommandReader.this.wakeupIterator(); - insertToListeners( command ); + callListeners( command ); break; case SHUTDOWN: CommandReader.this.makeQueueFull(); CommandReader.this.wakeupIterator(); - insertToListeners( command ); + callListeners( command ); break; default: - insertToListeners( command ); + callListeners( command ); break; } } @@ -462,7 +455,7 @@ public void run() } } - private void insertToListeners( Command cmd ) + private void callListeners( Command cmd ) { MasterProcessCommand expectedCommandType = cmd.getCommandType(); for ( BiProperty listenerWrapper : CommandReader.this.listeners ) @@ -483,18 +476,8 @@ private void exitByConfiguration() { CommandReader.this.makeQueueFull(); CommandReader.this.wakeupIterator(); - insertToListeners( toShutdown( shutdown ) ); - if ( shutdown.isExit() ) - { - System.exit( 1 ); - } - else if ( shutdown.isKill() ) - { - Runtime.getRuntime().halt( 1 ); - } - // else is default: other than Shutdown.DEFAULT should not happen; otherwise you missed enum case + callListeners( toShutdown( shutdown ) ); } } } - } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkedChannelEncoder.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkedChannelEncoder.java new file mode 100644 index 0000000000..f66e1374e9 --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkedChannelEncoder.java @@ -0,0 +1,408 @@ +package org.apache.maven.surefire.booter; + +/* + * 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.commons.codec.binary.Base64; +import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerUtils; +import org.apache.maven.surefire.report.ReportEntry; +import org.apache.maven.surefire.report.RunMode; +import org.apache.maven.surefire.report.SafeThrowable; +import org.apache.maven.surefire.report.StackTraceWriter; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.Map.Entry; + +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.MAGIC_NUMBER; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_SYSPROPS; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STDERR; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STDERR_NEW_LINE; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STDOUT; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STDOUT_NEW_LINE; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_BYE; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_CONSOLE_ERROR; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_CONSOLE_DEBUG; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_CONSOLE_INFO; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_CONSOLE_WARNING; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_NEXT_TEST; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_STOP_ON_NEXT_TEST; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_ASSUMPTIONFAILURE; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_ERROR; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_FAILED; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_SKIPPED; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_STARTING; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TEST_SUCCEEDED; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TESTSET_COMPLETED; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_TESTSET_STARTING; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_JVM_EXIT_ERROR; +import static org.apache.maven.surefire.report.RunMode.NORMAL_RUN; +import static org.apache.maven.surefire.report.RunMode.RERUN_TEST_AFTER_FAILURE; +import static java.util.Objects.requireNonNull; + +/** + * magic number : opcode : run mode [: opcode specific data]* + *
+ * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public final class ForkedChannelEncoder +{ + private static final Base64 BASE64 = new Base64(); + private static final Charset STREAM_ENCODING = US_ASCII; + private static final Charset STRING_ENCODING = UTF_8; + + private final OutputStream out; + private final RunMode runMode; + private volatile boolean trouble; + + public ForkedChannelEncoder( OutputStream out ) + { + this( out, NORMAL_RUN ); + } + + private ForkedChannelEncoder( OutputStream out, RunMode runMode ) + { + this.out = requireNonNull( out ); + this.runMode = requireNonNull( runMode ); + } + + public ForkedChannelEncoder asRerunMode() // todo apply this and rework providers + { + return new ForkedChannelEncoder( out, RERUN_TEST_AFTER_FAILURE ); + } + + public ForkedChannelEncoder asNormalMode() + { + return new ForkedChannelEncoder( out, NORMAL_RUN ); + } + + public boolean checkError() + { + return trouble; + } + + public void sendSystemProperties( Map sysProps ) + { + for ( Entry entry : sysProps.entrySet() ) + { + String key = entry.getKey(); + String value = entry.getValue(); + StringBuilder event = encode( BOOTERCODE_SYSPROPS, runMode, key, value ); + encodeAndPrintEvent( event ); + } + } + + public void testSetStarting( ReportEntry reportEntry, boolean trimStackTraces ) + { + encode( BOOTERCODE_TESTSET_STARTING, runMode, reportEntry, trimStackTraces ); + } + + public void testSetCompleted( ReportEntry reportEntry, boolean trimStackTraces ) + { + encode( BOOTERCODE_TESTSET_COMPLETED, runMode, reportEntry, trimStackTraces ); + } + + public void testStarting( ReportEntry reportEntry, boolean trimStackTraces ) + { + encode( BOOTERCODE_TEST_STARTING, runMode, reportEntry, trimStackTraces ); + } + + public void testSucceeded( ReportEntry reportEntry, boolean trimStackTraces ) + { + encode( BOOTERCODE_TEST_SUCCEEDED, runMode, reportEntry, trimStackTraces ); + } + + public void testFailed( ReportEntry reportEntry, boolean trimStackTraces ) + { + encode( BOOTERCODE_TEST_FAILED, runMode, reportEntry, trimStackTraces ); + } + + public void testSkipped( ReportEntry reportEntry, boolean trimStackTraces ) + { + encode( BOOTERCODE_TEST_SKIPPED, runMode, reportEntry, trimStackTraces ); + } + + public void testError( ReportEntry reportEntry, boolean trimStackTraces ) + { + encode( BOOTERCODE_TEST_ERROR, runMode, reportEntry, trimStackTraces ); + } + + public void testAssumptionFailure( ReportEntry reportEntry, boolean trimStackTraces ) + { + encode( BOOTERCODE_TEST_ASSUMPTIONFAILURE, runMode, reportEntry, trimStackTraces ); + } + + public void stdOut( String msg, boolean newLine ) + { + ForkedProcessEvent event = newLine ? BOOTERCODE_STDOUT_NEW_LINE : BOOTERCODE_STDOUT; + setOutErr( event.getOpcode(), msg ); + } + + public void stdErr( String msg, boolean newLine ) + { + ForkedProcessEvent event = newLine ? BOOTERCODE_STDERR_NEW_LINE : BOOTERCODE_STDERR; + setOutErr( event.getOpcode(), msg ); + } + + private void setOutErr( String eventType, String message ) + { + String base64Message = toBase64( message ); + StringBuilder event = encodeMessage( eventType, runMode.geRunName(), base64Message ); + encodeAndPrintEvent( event ); + } + + public void consoleInfoLog( String msg ) + { + StringBuilder event = print( BOOTERCODE_CONSOLE_INFO.getOpcode(), msg ); + encodeAndPrintEvent( event ); + } + + public void consoleErrorLog( String msg ) + { + StringBuilder event = print( BOOTERCODE_CONSOLE_ERROR.getOpcode(), msg ); + encodeAndPrintEvent( event ); + } + + public void consoleErrorLog( Throwable t ) + { + consoleErrorLog( t.getLocalizedMessage(), t ); + } + + public void consoleErrorLog( String msg, Throwable t ) + { + StringBuilder encoded = encodeHeader( BOOTERCODE_CONSOLE_ERROR.getOpcode(), null ); + encode( encoded, msg, null, ConsoleLoggerUtils.toString( t ) ); + encodeAndPrintEvent( encoded ); + } + + public void consoleErrorLog( StackTraceWriter stackTraceWriter, boolean trimStackTraces ) + { + error( stackTraceWriter, trimStackTraces, BOOTERCODE_CONSOLE_ERROR ); + } + + public void consoleDebugLog( String msg ) + { + StringBuilder event = print( BOOTERCODE_CONSOLE_DEBUG.getOpcode(), msg ); + encodeAndPrintEvent( event ); + } + + public void consoleWarningLog( String msg ) + { + StringBuilder event = print( BOOTERCODE_CONSOLE_WARNING.getOpcode(), msg ); + encodeAndPrintEvent( event ); + } + + public void bye() + { + encodeOpcode( BOOTERCODE_BYE ); + } + + public void stopOnNextTest() + { + encodeOpcode( BOOTERCODE_STOP_ON_NEXT_TEST ); + } + + public void acquireNextTest() + { + encodeOpcode( BOOTERCODE_NEXT_TEST ); + } + + public void sendExitEvent( StackTraceWriter stackTraceWriter, boolean trimStackTraces ) + { + error( stackTraceWriter, trimStackTraces, BOOTERCODE_JVM_EXIT_ERROR ); + } + + private void error( StackTraceWriter stackTraceWriter, boolean trimStackTraces, ForkedProcessEvent event ) + { + StringBuilder encoded = encodeHeader( event.getOpcode(), null ); + encode( encoded, stackTraceWriter, trimStackTraces ); + encodeAndPrintEvent( encoded ); + } + + private void encode( ForkedProcessEvent operation, RunMode runMode, ReportEntry reportEntry, + boolean trimStackTraces ) + { + StringBuilder event = encode( operation.getOpcode(), runMode.geRunName(), reportEntry, trimStackTraces ); + encodeAndPrintEvent( event ); + } + + private void encodeOpcode( ForkedProcessEvent operation ) + { + StringBuilder event = encodeOpcode( operation.getOpcode(), null ); + encodeAndPrintEvent( event ); + } + + private void encodeAndPrintEvent( StringBuilder command ) + { + byte[] array = command.append( '\n' ).toString().getBytes( STREAM_ENCODING ); + synchronized ( out ) + { + try + { + out.write( array ); + out.flush(); + } + catch ( IOException e ) + { + DumpErrorSingleton.getSingleton().dumpException( e ); + trouble = true; + } + } + } + + static StringBuilder encode( ForkedProcessEvent operation, RunMode runMode, String... args ) + { + StringBuilder encodedTo = encodeHeader( operation.getOpcode(), runMode.geRunName() ) + .append( ':' ); + + for ( int i = 0; i < args.length; ) + { + String arg = args[i++]; + encodedTo.append( toBase64( arg ) ); + if ( i != args.length ) + { + encodedTo.append( ':' ); + } + } + return encodedTo; + } + + static void encode( StringBuilder encoded, StackTraceWriter stw, boolean trimStackTraces ) + { + SafeThrowable throwable = stw == null ? null : stw.getThrowable(); + String message = throwable == null ? null : throwable.getLocalizedMessage(); + String smartStackTrace = stw == null ? null : stw.smartTrimmedStackTrace(); + String stackTrace = stw == null ? null : toStackTrace( stw, trimStackTraces ); + encode( encoded, message, smartStackTrace, stackTrace ); + } + + private static void encode( StringBuilder encoded, String message, String smartStackTrace, String stackTrace ) + { + encoded.append( ':' ) + .append( toBase64( message ) ) + .append( ':' ) + .append( toBase64( smartStackTrace ) ) + .append( ':' ) + .append( toBase64( stackTrace ) ); + } + + /** + * Used operations:
+ *
    + *
  • {@link ForkedProcessEvent#BOOTERCODE_TESTSET_STARTING},
  • + *
  • {@link ForkedProcessEvent#BOOTERCODE_TESTSET_COMPLETED},
  • + *
  • {@link ForkedProcessEvent#BOOTERCODE_TEST_STARTING},
  • + *
  • {@link ForkedProcessEvent#BOOTERCODE_TEST_SUCCEEDED},
  • + *
  • {@link ForkedProcessEvent#BOOTERCODE_TEST_FAILED},
  • + *
  • {@link ForkedProcessEvent#BOOTERCODE_TEST_ERROR},
  • + *
  • {@link ForkedProcessEvent#BOOTERCODE_TEST_SKIPPED},
  • + *
  • {@link ForkedProcessEvent#BOOTERCODE_TEST_ASSUMPTIONFAILURE}.
  • + *
+ */ + static StringBuilder encode( String operation, String runMode, ReportEntry reportEntry, + boolean trimStackTraces ) + { + StringBuilder encodedTo = encodeHeader( operation, runMode ) + .append( ':' ) + .append( toBase64( reportEntry.getSourceName() ) ) + .append( ':' ) + .append( toBase64( reportEntry.getSourceText() ) ) + .append( ':' ) + .append( toBase64( reportEntry.getName() ) ) + .append( ':' ) + .append( toBase64( reportEntry.getNameText() ) ) + .append( ':' ) + .append( toBase64( reportEntry.getGroup() ) ) + .append( ':' ) + .append( toBase64( reportEntry.getMessage() ) ) + .append( ':' ) + .append( reportEntry.getElapsed() == null ? "-" : reportEntry.getElapsed().toString() ); + + encode( encodedTo, reportEntry.getStackTraceWriter(), trimStackTraces ); + + return encodedTo; + } + + /** + * Used in {@link #consoleInfoLog(String)}, {@link #consoleErrorLog(String)}, {@link #consoleDebugLog(String)}, + * {@link #consoleWarningLog(String)} and private methods extending the buffer. + */ + StringBuilder print( String operation, String... msgs ) + { + String[] encodedMsgs = new String[msgs.length]; + for ( int i = 0; i < encodedMsgs.length; i++ ) + { + String msg = msgs[i]; + encodedMsgs[i] = toBase64( msg ); + } + return encodeMessage( operation, null, encodedMsgs ); + } + + static StringBuilder encodeMessage( String operation, String runMode, String... encodedMsgs ) + { + StringBuilder builder = encodeHeader( operation, runMode ); + for ( String encodedMsg : encodedMsgs ) + { + builder.append( ':' ) + .append( encodedMsg ); + + } + return builder; + } + + static StringBuilder encodeHeader( String operation, String runMode ) + { + return encodeOpcode( operation, runMode ) + .append( ':' ) + .append( STRING_ENCODING.name() ); + } + + /** + * Used in {@link #bye()}, {@link #stopOnNextTest()} and {@link #encodeOpcode(ForkedProcessEvent)} + * and private methods extending the buffer. + * + * @param operation opcode + * @param runMode run mode + * @return encoded command + */ + static StringBuilder encodeOpcode( String operation, String runMode ) + { + StringBuilder s = new StringBuilder( 128 ) + .append( MAGIC_NUMBER ) + .append( operation ); + + return runMode == null ? s : s.append( ':' ).append( runMode ); + } + + private static String toStackTrace( StackTraceWriter stw, boolean trimStackTraces ) + { + return trimStackTraces ? stw.writeTrimmedTraceToString() : stw.writeTraceToString(); + } + + static String toBase64( String msg ) + { + return msg == null ? "-" : new String( BASE64.encode( msg.getBytes( STRING_ENCODING ) ), STREAM_ENCODING ); + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkedProcessEvent.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkedProcessEvent.java new file mode 100644 index 0000000000..74b9eb941b --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkedProcessEvent.java @@ -0,0 +1,132 @@ +package org.apache.maven.surefire.booter; + +/* + * 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.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static java.util.Collections.unmodifiableMap; + +/** + * Events sent back to the plugin process. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public enum ForkedProcessEvent +{ + BOOTERCODE_SYSPROPS( "sys-prop" ), + + BOOTERCODE_TESTSET_STARTING( "testset-starting" ), + BOOTERCODE_TESTSET_COMPLETED( "testset-completed" ), + BOOTERCODE_TEST_STARTING( "test-starting" ), + BOOTERCODE_TEST_SUCCEEDED( "test-succeeded" ), + BOOTERCODE_TEST_FAILED( "test-failed" ), + BOOTERCODE_TEST_SKIPPED( "test-skipped" ), + BOOTERCODE_TEST_ERROR( "test-error" ), + BOOTERCODE_TEST_ASSUMPTIONFAILURE( "test-assumption-failure" ), + + BOOTERCODE_STDOUT( "std-out-stream" ), + BOOTERCODE_STDOUT_NEW_LINE( "std-out-stream-new-line" ), + BOOTERCODE_STDERR( "std-err-stream" ), + BOOTERCODE_STDERR_NEW_LINE( "std-err-stream-new-line" ), + + BOOTERCODE_CONSOLE_INFO( "console-info-log" ), + BOOTERCODE_CONSOLE_DEBUG( "console-debug-log" ), + BOOTERCODE_CONSOLE_WARNING( "console-warning-log" ), + BOOTERCODE_CONSOLE_ERROR( "console-error-log" ), + + BOOTERCODE_BYE( "bye" ), + BOOTERCODE_STOP_ON_NEXT_TEST( "stop-on-next-test" ), + BOOTERCODE_NEXT_TEST( "next-test" ), + + BOOTERCODE_JVM_EXIT_ERROR( "jvm-exit-error" ); + + public static final String MAGIC_NUMBER = ":maven:surefire:std:out:"; + + public static final Map EVENTS = events(); + + private static Map events() + { + Map events = new ConcurrentHashMap<>(); + for ( ForkedProcessEvent event : values() ) + { + events.put( event.getOpcode(), event ); + } + return unmodifiableMap( events ); + } + + private final String opcode; + + ForkedProcessEvent( String opcode ) + { + this.opcode = opcode; + } + + public String getOpcode() + { + return opcode; + } + + public boolean isSysPropCategory() + { + return this == BOOTERCODE_SYSPROPS; + } + + public boolean isTestCategory() + { + return this == BOOTERCODE_TESTSET_STARTING + || this == BOOTERCODE_TESTSET_COMPLETED + || this == BOOTERCODE_TEST_STARTING + || this == BOOTERCODE_TEST_SUCCEEDED + || this == BOOTERCODE_TEST_FAILED + || this == BOOTERCODE_TEST_SKIPPED + || this == BOOTERCODE_TEST_ERROR + || this == BOOTERCODE_TEST_ASSUMPTIONFAILURE; + } + + public boolean isStandardStreamCategory() + { + return this == BOOTERCODE_STDOUT || this == BOOTERCODE_STDOUT_NEW_LINE + || this == BOOTERCODE_STDERR || this == BOOTERCODE_STDERR_NEW_LINE; + } + + public boolean isConsoleCategory() + { + return this == BOOTERCODE_CONSOLE_INFO + || this == BOOTERCODE_CONSOLE_DEBUG + || this == BOOTERCODE_CONSOLE_WARNING; + } + + public boolean isConsoleErrorCategory() + { + return this == BOOTERCODE_CONSOLE_ERROR; + } + + public boolean isControlCategory() + { + return this == BOOTERCODE_BYE || this == BOOTERCODE_STOP_ON_NEXT_TEST || this == BOOTERCODE_NEXT_TEST; + } + + public boolean isJvmExitError() + { + return this == BOOTERCODE_JVM_EXIT_ERROR; + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java index 7459ad9840..5bb16ee1cf 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingReporterFactory.java @@ -19,9 +19,6 @@ * under the License. */ -import java.io.PrintStream; -import java.util.concurrent.atomic.AtomicInteger; - import org.apache.maven.surefire.report.ReporterFactory; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.suite.RunResult; @@ -35,22 +32,20 @@ public class ForkingReporterFactory implements ReporterFactory { - private final boolean isTrimstackTrace; - - private final PrintStream originalSystemOut; + private final boolean trimstackTrace; - private final AtomicInteger testSetChannelId = new AtomicInteger( 1 ); + private final ForkedChannelEncoder eventChannel; - public ForkingReporterFactory( boolean trimstackTrace, PrintStream originalSystemOut ) + public ForkingReporterFactory( boolean trimstackTrace, ForkedChannelEncoder eventChannel ) { - isTrimstackTrace = trimstackTrace; - this.originalSystemOut = originalSystemOut; + this.trimstackTrace = trimstackTrace; + this.eventChannel = eventChannel; } @Override public RunListener createReporter() { - return new ForkingRunListener( originalSystemOut, testSetChannelId.getAndIncrement(), isTrimstackTrace ); + return new ForkingRunListener( eventChannel, trimstackTrace ); } @Override diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java index ce806b922f..528b6072a8 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/ForkingRunListener.java @@ -20,27 +20,15 @@ */ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; -import org.apache.maven.plugin.surefire.log.api.ConsoleLoggerUtils; import org.apache.maven.surefire.report.ConsoleOutputReceiver; import org.apache.maven.surefire.report.ConsoleStream; import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.RunListener; -import org.apache.maven.surefire.report.SafeThrowable; -import org.apache.maven.surefire.report.SimpleReportEntry; -import org.apache.maven.surefire.report.StackTraceWriter; +import org.apache.maven.surefire.report.RunMode; import org.apache.maven.surefire.report.TestSetReportEntry; -import org.apache.maven.surefire.util.internal.StringUtils.EncodedArray; -import java.io.PrintStream; -import java.util.Map.Entry; - -import static java.lang.Integer.toHexString; -import static java.nio.charset.Charset.defaultCharset; -import static org.apache.maven.surefire.util.internal.ObjectUtils.systemProps; -import static org.apache.maven.surefire.util.internal.ObjectUtils.useNonNull; -import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication; -import static org.apache.maven.surefire.util.internal.StringUtils.escapeBytesToPrintable; -import static org.apache.maven.surefire.util.internal.StringUtils.escapeToPrintable; +import static org.apache.maven.surefire.report.RunMode.NORMAL_RUN; +import static java.util.Objects.requireNonNull; /** * Encodes the full output of the test run to the stdout stream. @@ -55,188 +43,98 @@ * The synchronization in the underlying PrintStream (target instance) * is used to preserve thread safety of the output stream. To perform * multiple writes/prints for a single request, they must - * synchronize on "target" variable in this class. + * synchronize on "target.out" variable in this class. * * @author Kristian Rosenvold */ public class ForkingRunListener implements RunListener, ConsoleLogger, ConsoleOutputReceiver, ConsoleStream { - public static final byte BOOTERCODE_TESTSET_STARTING = (byte) '1'; - - public static final byte BOOTERCODE_TESTSET_COMPLETED = (byte) '2'; - - public static final byte BOOTERCODE_STDOUT = (byte) '3'; - - public static final byte BOOTERCODE_STDERR = (byte) '4'; - - public static final byte BOOTERCODE_TEST_STARTING = (byte) '5'; - - public static final byte BOOTERCODE_TEST_SUCCEEDED = (byte) '6'; - - public static final byte BOOTERCODE_TEST_ERROR = (byte) '7'; - - public static final byte BOOTERCODE_TEST_FAILED = (byte) '8'; - - public static final byte BOOTERCODE_TEST_SKIPPED = (byte) '9'; - - public static final byte BOOTERCODE_TEST_ASSUMPTIONFAILURE = (byte) 'G'; - - /** - * INFO logger - * @see ConsoleLogger#info(String) - */ - public static final byte BOOTERCODE_CONSOLE = (byte) 'H'; - - public static final byte BOOTERCODE_SYSPROPS = (byte) 'I'; - - public static final byte BOOTERCODE_NEXT_TEST = (byte) 'N'; - - public static final byte BOOTERCODE_STOP_ON_NEXT_TEST = (byte) 'S'; - - /** - * ERROR logger - * @see ConsoleLogger#error(String) - */ - public static final byte BOOTERCODE_ERROR = (byte) 'X'; - - public static final byte BOOTERCODE_BYE = (byte) 'Z'; - - /** - * DEBUG logger - * @see ConsoleLogger#debug(String) - */ - public static final byte BOOTERCODE_DEBUG = (byte) 'D'; - - /** - * WARNING logger - * @see ConsoleLogger#warning(String) - */ - public static final byte BOOTERCODE_WARNING = (byte) 'W'; - - - private final PrintStream target; - - private final int testSetChannelId; + private final ForkedChannelEncoder target; - private final boolean trimStackTraces; + private final boolean trim; - private final byte[] stdOutHeader; + private volatile RunMode runMode = NORMAL_RUN; - private final byte[] stdErrHeader; - - public ForkingRunListener( PrintStream target, int testSetChannelId, boolean trimStackTraces ) + public ForkingRunListener( ForkedChannelEncoder target, boolean trim ) { this.target = target; - this.testSetChannelId = testSetChannelId; - this.trimStackTraces = trimStackTraces; - stdOutHeader = createHeader( BOOTERCODE_STDOUT, testSetChannelId ); - stdErrHeader = createHeader( BOOTERCODE_STDERR, testSetChannelId ); - sendProps(); + this.trim = trim; } @Override public void testSetStarting( TestSetReportEntry report ) { - encodeAndWriteToTarget( toString( BOOTERCODE_TESTSET_STARTING, report, testSetChannelId ) ); + target.testSetStarting( report, trim ); } @Override public void testSetCompleted( TestSetReportEntry report ) { - encodeAndWriteToTarget( toString( BOOTERCODE_TESTSET_COMPLETED, report, testSetChannelId ) ); + target.sendSystemProperties( report.getSystemProperties() ); + target.testSetCompleted( report, trim ); } @Override public void testStarting( ReportEntry report ) { - encodeAndWriteToTarget( toString( BOOTERCODE_TEST_STARTING, report, testSetChannelId ) ); + target.testStarting( report, trim ); } @Override public void testSucceeded( ReportEntry report ) { - encodeAndWriteToTarget( toString( BOOTERCODE_TEST_SUCCEEDED, report, testSetChannelId ) ); + target.testSucceeded( report, trim ); } @Override public void testAssumptionFailure( ReportEntry report ) { - encodeAndWriteToTarget( toString( BOOTERCODE_TEST_ASSUMPTIONFAILURE, report, testSetChannelId ) ); + target.testAssumptionFailure( report, trim ); } @Override public void testError( ReportEntry report ) { - encodeAndWriteToTarget( toString( BOOTERCODE_TEST_ERROR, report, testSetChannelId ) ); + target.testError( report, trim ); } @Override public void testFailed( ReportEntry report ) { - encodeAndWriteToTarget( toString( BOOTERCODE_TEST_FAILED, report, testSetChannelId ) ); + target.testFailed( report, trim ); } @Override public void testSkipped( ReportEntry report ) { - encodeAndWriteToTarget( toString( BOOTERCODE_TEST_SKIPPED, report, testSetChannelId ) ); + target.testSkipped( report, trim ); } @Override public void testExecutionSkippedByUser() { - encodeAndWriteToTarget( toString( BOOTERCODE_STOP_ON_NEXT_TEST, new SimpleReportEntry(), testSetChannelId ) ); + target.stopOnNextTest(); } - private void sendProps() + @Override + public RunMode markAs( RunMode currentRunMode ) { - for ( Entry entry : systemProps().entrySet() ) - { - String value = entry.getValue(); - encodeAndWriteToTarget( toPropertyString( entry.getKey(), useNonNull( value, "null" ) ) ); - } + RunMode runMode = this.runMode; + this.runMode = requireNonNull( currentRunMode ); + return runMode; } @Override - public void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) + public void writeTestOutput( String output, boolean newLine, boolean stdout ) { - EncodedArray encodedArray = escapeBytesToPrintable( stdout ? stdOutHeader : stdErrHeader, buf, off, len ); - - synchronized ( target ) // See notes about synchronization/thread safety in class javadoc + if ( stdout ) { - target.write( encodedArray.getArray(), 0, encodedArray.getSize() ); - target.flush(); - if ( target.checkError() ) - { - // We MUST NOT throw any exception from this method; otherwise we are in loop and CPU goes up: - // ForkingRunListener -> Exception -> JUnit Notifier and RunListener -> ForkingRunListener -> Exception - DumpErrorSingleton.getSingleton() - .dumpStreamText( "Unexpected IOException with stream: " + new String( buf, off, len ) ); - } + target.stdOut( output, newLine ); } - } - - public static byte[] createHeader( byte booterCode, int testSetChannel ) - { - return encodeStringForForkCommunication( String.valueOf( (char) booterCode ) - + ',' - + Integer.toString( testSetChannel, 16 ) - + ',' + defaultCharset().name() - + ',' ); - } - - private void log( byte bootCode, String message ) - { - if ( message != null ) + else { - StringBuilder sb = new StringBuilder( 7 + message.length() * 5 ); - append( sb, bootCode ); comma( sb ); - append( sb, toHexString( testSetChannelId ) ); comma( sb ); - escapeToPrintable( sb, message ); - - sb.append( '\n' ); - encodeAndWriteToTarget( sb.toString() ); + target.stdErr( output, newLine ); } } @@ -249,7 +147,7 @@ public boolean isDebugEnabled() @Override public void debug( String message ) { - log( BOOTERCODE_DEBUG, message ); + target.consoleDebugLog( message ); } @Override @@ -261,7 +159,7 @@ public boolean isInfoEnabled() @Override public void info( String message ) { - log( BOOTERCODE_CONSOLE, message ); + target.consoleInfoLog( message ); } @Override @@ -273,7 +171,7 @@ public boolean isWarnEnabled() @Override public void warning( String message ) { - log( BOOTERCODE_WARNING, message ); + target.consoleWarningLog( message ); } @Override @@ -285,13 +183,13 @@ public boolean isErrorEnabled() @Override public void error( String message ) { - log( BOOTERCODE_ERROR, message ); + target.consoleErrorLog( message ); } @Override public void error( String message, Throwable t ) { - error( ConsoleLoggerUtils.toString( message, t ) ); + target.consoleErrorLog( message, t ); } @Override @@ -300,130 +198,9 @@ public void error( Throwable t ) error( null, t ); } - private void encodeAndWriteToTarget( String string ) - { - byte[] encodeBytes = encodeStringForForkCommunication( string ); - synchronized ( target ) // See notes about synchronization/thread safety in class javadoc - { - target.write( encodeBytes, 0, encodeBytes.length ); - target.flush(); - if ( target.checkError() ) - { - // We MUST NOT throw any exception from this method; otherwise we are in loop and CPU goes up: - // ForkingRunListener -> Exception -> JUnit Notifier and RunListener -> ForkingRunListener -> Exception - DumpErrorSingleton.getSingleton().dumpStreamText( "Unexpected IOException: " + string ); - } - } - } - - private String toPropertyString( String key, String value ) - { - StringBuilder stringBuilder = new StringBuilder(); - - append( stringBuilder, BOOTERCODE_SYSPROPS ); comma( stringBuilder ); - append( stringBuilder, toHexString( testSetChannelId ) ); comma( stringBuilder ); - - escapeToPrintable( stringBuilder, key ); - comma( stringBuilder ); - escapeToPrintable( stringBuilder, value ); - stringBuilder.append( "\n" ); - return stringBuilder.toString(); - } - - private String toString( byte operationCode, ReportEntry reportEntry, int testSetChannelId ) - { - StringBuilder stringBuilder = new StringBuilder(); - append( stringBuilder, operationCode ); comma( stringBuilder ); - append( stringBuilder, toHexString( testSetChannelId ) ); comma( stringBuilder ); - - nullableEncoding( stringBuilder, reportEntry.getSourceName() ); - comma( stringBuilder ); - nullableEncoding( stringBuilder, reportEntry.getName() ); - comma( stringBuilder ); - nullableEncoding( stringBuilder, reportEntry.getGroup() ); - comma( stringBuilder ); - nullableEncoding( stringBuilder, reportEntry.getMessage() ); - comma( stringBuilder ); - nullableEncoding( stringBuilder, reportEntry.getElapsed() ); - encode( stringBuilder, reportEntry.getStackTraceWriter() ); - stringBuilder.append( "\n" ); - return stringBuilder.toString(); - } - - private static void comma( StringBuilder stringBuilder ) - { - stringBuilder.append( "," ); - } - - private void append( StringBuilder stringBuilder, String message ) - { - stringBuilder.append( encode( message ) ); - } - - private void append( StringBuilder stringBuilder, byte b ) - { - stringBuilder.append( (char) b ); - } - - private void nullableEncoding( StringBuilder stringBuilder, Integer source ) - { - stringBuilder.append( source == null ? "null" : source.toString() ); - } - - private String encode( String source ) - { - return source; - } - - - private static void nullableEncoding( StringBuilder stringBuilder, String source ) - { - if ( source == null || source.isEmpty() ) - { - stringBuilder.append( "null" ); - } - else - { - escapeToPrintable( stringBuilder, source ); - } - } - - private void encode( StringBuilder stringBuilder, StackTraceWriter stackTraceWriter ) - { - encode( stringBuilder, stackTraceWriter, trimStackTraces ); - } - - public static void encode( StringBuilder stringBuilder, StackTraceWriter stackTraceWriter, boolean trimStackTraces ) - { - if ( stackTraceWriter != null ) - { - comma( stringBuilder ); - //noinspection ThrowableResultOfMethodCallIgnored - final SafeThrowable throwable = stackTraceWriter.getThrowable(); - if ( throwable != null ) - { - String message = throwable.getLocalizedMessage(); - nullableEncoding( stringBuilder, message ); - } - comma( stringBuilder ); - nullableEncoding( stringBuilder, stackTraceWriter.smartTrimmedStackTrace() ); - comma( stringBuilder ); - nullableEncoding( stringBuilder, trimStackTraces - ? stackTraceWriter.writeTrimmedTraceToString() - : stackTraceWriter.writeTraceToString() ); - } - } - @Override public void println( String message ) { - byte[] buf = message.getBytes(); - println( buf, 0, buf.length ); - } - - @Override - public void println( byte[] buf, int off, int len ) - { - writeTestOutput( buf, off, len, true ); + writeTestOutput( message, true, true ); } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java index 1f95179c66..7c4520f8ab 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/MasterProcessCommand.java @@ -22,11 +22,9 @@ import java.io.DataInputStream; import java.io.IOException; -import static java.lang.String.format; -import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.US_ASCII; import static java.util.Objects.requireNonNull; -import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication; +import static java.lang.String.format; /** * Commands which are sent from plugin to the forked jvm. @@ -146,7 +144,6 @@ String toDataTypeAsString( byte... data ) switch ( this ) { case RUN_CLASS: - return new String( data, ISO_8859_1 ); case SHUTDOWN: return new String( data, US_ASCII ); default: @@ -159,7 +156,6 @@ byte[] fromDataType( String data ) switch ( this ) { case RUN_CLASS: - return encodeStringForForkCommunication( data ); case SHUTDOWN: return data.getBytes( US_ASCII ); default: diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java index 360c8025c6..5cc1415e9a 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java @@ -34,10 +34,8 @@ import org.apache.maven.surefire.util.RunOrder; import org.apache.maven.surefire.util.SurefireReflectionException; -import javax.annotation.Nonnull; import java.io.File; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; @@ -147,32 +145,9 @@ public Object convertIfRunResult( Object result ) int getSkipped = (Integer) invokeGetter( result, "getSkipped" ); int getFailures = (Integer) invokeGetter( result, "getFailures" ); return new RunResult( getCompletedCount1, getErrors, getFailures, getSkipped ); - - } - - class ClassLoaderProxy - implements InvocationHandler - { - private final Object target; - - /** - * @param delegate a target - */ - ClassLoaderProxy( Object delegate ) - { - this.target = delegate; - } - - @Override - public Object invoke( Object proxy, Method method, Object[] args ) - throws Throwable - { - Method delegateMethod = target.getClass().getMethod( method.getName(), method.getParameterTypes() ); - return delegateMethod.invoke( target, args ); - } } - Object createTestRequest( TestRequest suiteDefinition ) + private Object createTestRequest( TestRequest suiteDefinition ) { if ( suiteDefinition == null ) { @@ -191,7 +166,7 @@ Object createTestRequest( TestRequest suiteDefinition ) } } - Object createTestListResolver( TestListResolver resolver ) + private Object createTestListResolver( TestListResolver resolver ) { if ( resolver == null ) { @@ -204,7 +179,7 @@ Object createTestListResolver( TestListResolver resolver ) } } - Object createDirectoryScannerParameters( DirectoryScannerParameters directoryScannerParameters ) + private Object createDirectoryScannerParameters( DirectoryScannerParameters directoryScannerParameters ) { if ( directoryScannerParameters == null ) { @@ -222,8 +197,7 @@ Object createDirectoryScannerParameters( DirectoryScannerParameters directorySca RunOrder.asString( directoryScannerParameters.getRunOrder() ) ); } - - Object createRunOrderParameters( RunOrderParameters runOrderParameters ) + private Object createRunOrderParameters( RunOrderParameters runOrderParameters ) { if ( runOrderParameters == null ) { @@ -236,7 +210,7 @@ Object createRunOrderParameters( RunOrderParameters runOrderParameters ) return newInstance( constructor, RunOrder.asString( runOrderParameters.getRunOrder() ), runStatisticsFile ); } - Object createTestArtifactInfo( TestArtifactInfo testArtifactInfo ) + private Object createTestArtifactInfo( TestArtifactInfo testArtifactInfo ) { if ( testArtifactInfo == null ) { @@ -247,7 +221,7 @@ Object createTestArtifactInfo( TestArtifactInfo testArtifactInfo ) return newInstance( constructor, testArtifactInfo.getVersion(), testArtifactInfo.getClassifier() ); } - Object createReporterConfiguration( ReporterConfiguration reporterConfig ) + private Object createReporterConfiguration( ReporterConfiguration reporterConfig ) { Constructor constructor = getConstructor( reporterConfiguration, File.class, boolean.class ); return newInstance( constructor, reporterConfig.getReportsDirectory(), reporterConfig.isTrimStackTrace() ); @@ -315,7 +289,7 @@ public void setSystemExitTimeout( Object o, Integer systemExitTimeout ) invokeSetter( o, "setSystemExitTimeout", Integer.class, systemExitTimeout ); } - public void setDirectoryScannerParameters( Object o, DirectoryScannerParameters dirScannerParams ) + void setDirectoryScannerParameters( Object o, DirectoryScannerParameters dirScannerParams ) { Object param = createDirectoryScannerParameters( dirScannerParams ); invokeSetter( o, "setDirectoryScannerParameters", directoryScannerParameters, param ); @@ -362,8 +336,7 @@ public void setReporterConfigurationAware( Object o, ReporterConfiguration repor } } - - void setReporterConfiguration( Object o, ReporterConfiguration reporterConfiguration ) + private void setReporterConfiguration( Object o, ReporterConfiguration reporterConfiguration ) { Object param = createReporterConfiguration( reporterConfiguration ); invokeSetter( o, "setReporterConfiguration", this.reporterConfiguration, param ); @@ -402,11 +375,6 @@ private boolean isRunResult( Object o ) return runResult.isAssignableFrom( o.getClass() ); } - public Object createConsoleLogger( @Nonnull ConsoleLogger consoleLogger ) - { - return createConsoleLogger( consoleLogger, surefireClassLoader ); - } - private static Collection toOrdinals( Collection enums ) { Collection ordinals = new ArrayList<>( enums.size() ); @@ -429,5 +397,4 @@ public static Object createConsoleLogger( ConsoleLogger consoleLogger, ClassLoad throw new SurefireReflectionException( e ); } } - } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java index b487f06589..0fea537c87 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/providerapi/ProviderParameters.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.surefire.booter.ForkedChannelEncoder; import org.apache.maven.surefire.booter.Shutdown; import org.apache.maven.surefire.cli.CommandLineOption; import org.apache.maven.surefire.report.ConsoleStream; @@ -149,4 +150,6 @@ public interface ProviderParameters Shutdown getShutdown(); Integer getSystemExitTimeout(); + + ForkedChannelEncoder getForkedChannelEncoder(); } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/CategorizedReportEntry.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/CategorizedReportEntry.java index 47b0c48b0e..c35d6d54c8 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/report/CategorizedReportEntry.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/CategorizedReportEntry.java @@ -21,15 +21,15 @@ import java.util.Collections; import java.util.Map; +import java.util.Objects; /** * @author Kristian Rosenvold */ public class CategorizedReportEntry extends SimpleReportEntry - implements ReportEntry { - private static final String GROUP_PREFIX = " (of "; + public static final String GROUP_PREFIX = " (of "; private static final String GROUP_SUFIX = ")"; @@ -43,30 +43,35 @@ public CategorizedReportEntry( String source, String name, String group ) public CategorizedReportEntry( String source, String name, String group, StackTraceWriter stackTraceWriter, Integer elapsed ) { - super( source, name, stackTraceWriter, elapsed ); + super( source, null, name, null, stackTraceWriter, elapsed ); this.group = group; } public CategorizedReportEntry( String source, String name, String group, StackTraceWriter stackTraceWriter, Integer elapsed, String message ) { - this( source, name, group, stackTraceWriter, elapsed, message, Collections.emptyMap() ); + this( source, null, name, null, + group, stackTraceWriter, elapsed, message, Collections.emptyMap() ); } - public CategorizedReportEntry( String source, String name, String group, StackTraceWriter stackTraceWriter, + public CategorizedReportEntry( String source, String sourceText, String name, String nameText, + String group, StackTraceWriter stackTraceWriter, Integer elapsed, String message, Map systemProperties ) { - super( source, name, stackTraceWriter, elapsed, message, systemProperties ); + super( source, sourceText, name, nameText, stackTraceWriter, elapsed, message, systemProperties ); this.group = group; } - public static TestSetReportEntry reportEntry( String source, String name, String group, + public static TestSetReportEntry reportEntry( String source, String sourceText, String name, String nameText, + String group, StackTraceWriter stackTraceWriter, Integer elapsed, String message, Map systemProperties ) { return group != null - ? new CategorizedReportEntry( source, name, group, stackTraceWriter, elapsed, message, systemProperties ) - : new SimpleReportEntry( source, name, stackTraceWriter, elapsed, message, systemProperties ); + ? new CategorizedReportEntry( source, sourceText, name, nameText, + group, stackTraceWriter, elapsed, message, systemProperties ) + : new SimpleReportEntry( source, sourceText, name, nameText, + stackTraceWriter, elapsed, message, systemProperties ); } @Override @@ -78,7 +83,13 @@ public String getGroup() @Override public String getNameWithGroup() { - return isNameWithGroup() ? getName() + GROUP_PREFIX + getGroup() + GROUP_SUFIX : getName(); + return isNameWithGroup() ? getSourceName() + GROUP_PREFIX + getGroup() + GROUP_SUFIX : getSourceName(); + } + + @Override + public String getReportNameWithGroup() + { + return isNameWithGroup() ? getSourceText() + GROUP_PREFIX + getGroup() + GROUP_SUFIX : getSourceText(); } @Override @@ -99,8 +110,7 @@ public boolean equals( Object o ) CategorizedReportEntry that = (CategorizedReportEntry) o; - return !( group != null ? !group.equals( that.group ) : that.group != null ); - + return Objects.equals( group, that.group ); } @Override @@ -113,6 +123,6 @@ public int hashCode() private boolean isNameWithGroup() { - return getGroup() != null && !getGroup().equals( getName() ); + return getGroup() != null && !getGroup().equals( getSourceName() ); } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java index df44f63ed2..00051fc378 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputCapture.java @@ -25,7 +25,6 @@ import static java.lang.System.setErr; import static java.lang.System.setOut; -import static org.apache.maven.surefire.util.internal.StringUtils.NL; /** * Deals with system.out/err. @@ -55,16 +54,14 @@ private static final class ForwardingPrintStream @Override public void write( byte[] buf, int off, int len ) { - // Note: At this point the supplied "buf" instance is reused, which means - // data must be copied out of the buffer - target.writeTestOutput( buf, off, len, isStdout ); + target.writeTestOutput( new String( buf, off, len ), false, isStdout ); } @Override public void write( byte[] b ) throws IOException { - target.writeTestOutput( b, 0, b.length, isStdout ); + write( b, 0, b.length ); } @Override @@ -80,15 +77,140 @@ public void write( int b ) } } + @Override + public void println( boolean x ) + { + println( x ? "true" : "false" ); + } + + @Override + public void println( char x ) + { + println( String.valueOf( x ) ); + } + + @Override + public void println( int x ) + { + println( String.valueOf( x ) ); + } + + @Override + public void println( long x ) + { + println( String.valueOf( x ) ); + } + + @Override + public void println( float x ) + { + println( String.valueOf( x ) ); + } + + @Override + public void println( double x ) + { + println( String.valueOf( x ) ); + } + + @Override + public void println( char[] x ) + { + println( String.valueOf( x ) ); + } + + @Override + public void println( Object x ) + { + println( String.valueOf( x ) ); + } + @Override public void println( String s ) { - if ( s == null ) - { - s = "null"; // Shamelessly taken from super.print - } - final byte[] bytes = ( s + NL ).getBytes(); - target.writeTestOutput( bytes, 0, bytes.length, isStdout ); + target.writeTestOutput( s == null ? "null" : s, true, isStdout ); + } + + @Override + public void println() + { + target.writeTestOutput( "", true, isStdout ); + } + + @Override + public void print( boolean x ) + { + print( x ? "true" : "false" ); + } + + @Override + public void print( char x ) + { + print( String.valueOf( x ) ); + } + + @Override + public void print( int x ) + { + print( String.valueOf( x ) ); + } + + @Override + public void print( long x ) + { + print( String.valueOf( x ) ); + } + + @Override + public void print( float x ) + { + print( String.valueOf( x ) ); + } + + @Override + public void print( double x ) + { + print( String.valueOf( x ) ); + } + + @Override + public void print( char[] x ) + { + print( String.valueOf( x ) ); + } + + @Override + public void print( Object x ) + { + print( String.valueOf( x ) ); + } + + @Override + public void print( String s ) + { + target.writeTestOutput( s == null ? "null" : s, false, isStdout ); + } + + @Override + public PrintStream append( CharSequence csq ) + { + print( csq == null ? "null" : csq.toString() ); + return this; + } + + @Override + public PrintStream append( CharSequence csq, int start, int end ) + { + CharSequence s = csq == null ? "null" : csq; + print( s.subSequence( start, end ).toString() ); + return this; + } + + @Override + public PrintStream append( char c ) + { + print( c ); + return this; } @Override @@ -106,9 +228,8 @@ private static final class NullOutputStream extends OutputStream { @Override - public void write( int b ) throws IOException + public void write( int b ) { - } } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputReceiver.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputReceiver.java index 06d6414a95..8bc39d0343 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputReceiver.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleOutputReceiver.java @@ -29,11 +29,10 @@ public interface ConsoleOutputReceiver /** * Forwards process output from the running test-case into the reporting system * - * @param buf the buffer to write - * @param off offset - * @param len len + * @param output stdout/sterr output from running tests + * @param newLine print on new line * @param stdout Indicates if this is stdout */ - void writeTestOutput( byte[] buf, int off, int len, boolean stdout ); + void writeTestOutput( String output, boolean newLine, boolean stdout ); } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleStream.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleStream.java index 8a22ef0a99..0fc491811d 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleStream.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/ConsoleStream.java @@ -1 +1 @@ -package org.apache.maven.surefire.report; /* * 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. */ /** * Delegates to {@link System#out}. */ public interface ConsoleStream { void println( String message ); void println( byte[] buf, int off, int len ); } \ No newline at end of file +package org.apache.maven.surefire.report; /* * 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. */ /** * Delegates to {@link System#out}. */ public interface ConsoleStream { void println( String message ); } \ No newline at end of file diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java index 5298ad95b9..6cb61c3b43 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/DefaultDirectConsoleReporter.java @@ -39,10 +39,4 @@ public void println( String message ) { systemOut.println( message ); } - - @Override - public void println( byte[] buf, int off, int len ) - { - println( new String( buf, off, len ) ); - } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/ReportEntry.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/ReportEntry.java index ec0f782e09..6bc96187b7 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/report/ReportEntry.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/ReportEntry.java @@ -32,6 +32,13 @@ public interface ReportEntry */ String getSourceName(); + /** + * Human readable {@link #getSourceName() test class}. + * + * @return source text + */ + String getSourceText(); + /** * The name of the test case * @@ -39,6 +46,13 @@ public interface ReportEntry */ String getName(); + /** + * Human readable {@link #getName() test case}. + * + * @return name text + */ + String getNameText(); + /** * The group/category of the testcase * @@ -61,6 +75,14 @@ public interface ReportEntry */ Integer getElapsed(); + /** + * Returns same value as {@link #getElapsed()} and fallbacks to {@code fallback} for null elapsed timed. + * + * @param fallback usually 0 + * @return elapsed time if {@link #getElapsed()} is not null; otherwise returns {@code fallback} + */ + int getElapsed( int fallback ); + /** * A message relating to a non-successful termination. @@ -71,9 +93,16 @@ public interface ReportEntry String getMessage(); /** - * A name of the test case together with the group or category (if any exists). + * A source name of the test case together with the group or category (if any exists). * * @return A string with the test case name and group/category, or just the name. */ String getNameWithGroup(); + + /** + * A source text of the test case together with the group or category (if any exists). + * + * @return A string with the test case text and group/category, or just the source text. + */ + String getReportNameWithGroup(); } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java index 32c0abd1fd..396b277410 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/RunListener.java @@ -93,4 +93,13 @@ public interface RunListener * (The event is fired after the Nth test failed to signal skipping the rest of test-set.) */ void testExecutionSkippedByUser(); + + /** + * Marks the listener with run mode, e.g. normal run or re-run. + * + * @param currentRunMode set current run + * @return previous run mode; never returns null + * @throws NullPointerException if currentRunMode is null + */ + RunMode markAs( RunMode currentRunMode ); } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/RunMode.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/RunMode.java new file mode 100644 index 0000000000..efd78a322f --- /dev/null +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/RunMode.java @@ -0,0 +1,64 @@ +package org.apache.maven.surefire.report; + +/* + * 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.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static java.util.Collections.unmodifiableMap; + +/** + * Determines the purpose the provider started the tests. It can be either normal run or a kind of re-run type. + *
+ * This is important in the logic of {@code StatelessXmlReporter}. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public enum RunMode +{ + NORMAL_RUN( "normal-run" ), + RERUN_TEST_AFTER_FAILURE( "rerun-test-after-failure" ); + //todo add here RERUN_TESTSET, see https://github.com/apache/maven-surefire/pull/221 + + public static final Map MODES = modes(); + + private static Map modes() + { + Map modes = new ConcurrentHashMap<>(); + for ( RunMode mode : values() ) + { + modes.put( mode.geRunName(), mode ); + } + return unmodifiableMap( modes ); + } + + private final String runName; + + RunMode( String runName ) + { + this.runName = runName; + } + + public String geRunName() + { + return runName; + } +} diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java b/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java index 241c874d65..df7b4c4dcc 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/report/SimpleReportEntry.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.Map; +import java.util.Objects; /** * @author Kristian Rosenvold @@ -34,93 +35,88 @@ public class SimpleReportEntry private final String source; + private final String sourceText; + private final String name; + private final String nameText; + private final StackTraceWriter stackTraceWriter; private final Integer elapsed; private final String message; - public SimpleReportEntry() - { - this( null, null ); - } - - public SimpleReportEntry( String source, String name ) + public SimpleReportEntry( String source, String sourceText, String name, String nameText ) { - this( source, name, null, null ); + this( source, sourceText, name, nameText, null, null ); } - public SimpleReportEntry( String source, String name, Map systemProperties ) + public SimpleReportEntry( String source, String sourceText, String name, String nameText, + Map systemProperties ) { - this( source, name, null, null, systemProperties ); + this( source, sourceText, name, nameText, null, null, systemProperties ); } - private SimpleReportEntry( String source, String name, StackTraceWriter stackTraceWriter ) + private SimpleReportEntry( String source, String sourceText, String name, String nameText, + StackTraceWriter stackTraceWriter ) { - this( source, name, stackTraceWriter, null ); + this( source, sourceText, name, nameText, stackTraceWriter, null ); } - public SimpleReportEntry( String source, String name, Integer elapsed ) + public SimpleReportEntry( String source, String sourceText, String name, String nameText, Integer elapsed ) { - this( source, name, null, elapsed ); + this( source, sourceText, name, nameText, null, elapsed ); } - public SimpleReportEntry( String source, String name, String message ) + public SimpleReportEntry( String source, String sourceText, String name, String nameText, String message ) { - this( source, name, null, null, message, Collections.emptyMap() ); + this( source, sourceText, name, nameText, null, null, message, Collections.emptyMap() ); } - protected SimpleReportEntry( String source, String name, StackTraceWriter stackTraceWriter, Integer elapsed, - String message, Map systemProperties ) + public SimpleReportEntry( String source, String sourceText, String name, String nameText, + StackTraceWriter stackTraceWriter, Integer elapsed, String message, + Map systemProperties ) { - if ( source == null ) - { - source = "null"; - } - if ( name == null ) - { - name = "null"; - } - this.source = source; - + this.sourceText = sourceText; this.name = name; - + this.nameText = nameText; this.stackTraceWriter = stackTraceWriter; - this.message = message; - this.elapsed = elapsed; - this.systemProperties = new ImmutableMap<>( systemProperties ); } - public SimpleReportEntry( String source, String name, StackTraceWriter stackTraceWriter, Integer elapsed ) + public SimpleReportEntry( String source, String sourceText, String name, String nameText, + StackTraceWriter stackTraceWriter, Integer elapsed ) { - this( source, name, stackTraceWriter, elapsed, Collections.emptyMap() ); + this( source, sourceText, name, nameText, stackTraceWriter, elapsed, Collections.emptyMap() ); } - public SimpleReportEntry( String source, String name, StackTraceWriter stackTraceWriter, Integer elapsed, - Map systemProperties ) + public SimpleReportEntry( String source, String sourceText, String name, String nameText, + StackTraceWriter stackTraceWriter, Integer elapsed, Map systemProperties ) { - this( source, name, stackTraceWriter, elapsed, safeGetMessage( stackTraceWriter ), systemProperties ); + this( source, sourceText, name, nameText, + stackTraceWriter, elapsed, safeGetMessage( stackTraceWriter ), systemProperties ); } - public static SimpleReportEntry assumption( String source, String name, String message ) + public static SimpleReportEntry assumption( String source, String sourceText, String name, String nameText, + String message ) { - return new SimpleReportEntry( source, name, message ); + return new SimpleReportEntry( source, sourceText, name, nameText, message ); } - public static SimpleReportEntry ignored( String source, String name, String message ) + public static SimpleReportEntry ignored( String source, String sourceText, String name, String nameText, + String message ) { - return new SimpleReportEntry( source, name, message ); + return new SimpleReportEntry( source, sourceText, name, nameText, message ); } - public static SimpleReportEntry withException( String source, String name, StackTraceWriter stackTraceWriter ) + public static SimpleReportEntry withException( String source, String sourceText, String name, String nameText, + StackTraceWriter stackTraceWriter ) { - return new SimpleReportEntry( source, name, stackTraceWriter ); + return new SimpleReportEntry( source, sourceText, name, nameText, stackTraceWriter ); } private static String safeGetMessage( StackTraceWriter stackTraceWriter ) @@ -142,12 +138,24 @@ public String getSourceName() return source; } + @Override + public String getSourceText() + { + return sourceText; + } + @Override public String getName() { return name; } + @Override + public String getNameText() + { + return nameText; + } + @Override public String getGroup() { @@ -166,11 +174,18 @@ public Integer getElapsed() return elapsed; } + @Override + public int getElapsed( int fallback ) + { + return elapsed == null ? fallback : elapsed; + } + @Override public String toString() { - return "ReportEntry{" + "source='" + source + '\'' + ", name='" + name + '\'' + ", stackTraceWriter=" - + stackTraceWriter + ", elapsed=" + elapsed + ",message=" + message + '}'; + return "ReportEntry{" + "source='" + source + "', sourceText='" + sourceText + + "', name='" + name + "', nameText='" + nameText + "', stackTraceWriter='" + + stackTraceWriter + "', elapsed='" + elapsed + "', message='" + message + "'}"; } @Override @@ -192,23 +207,38 @@ public boolean equals( Object o ) } SimpleReportEntry that = (SimpleReportEntry) o; - return isElapsedTimeEqual( that ) && isNameEqual( that ) && isSourceEqual( that ) && isStackEqual( that ); + return isSourceEqual( that ) && isSourceTextEqual( that ) + && isNameEqual( that ) && isNameTextEqual( that ) + && isStackEqual( that ) + && isElapsedTimeEqual( that ) + && isSystemPropertiesEqual( that ) + && isMessageEqual( that ); } @Override public int hashCode() { - int result = source != null ? source.hashCode() : 0; - result = 31 * result + ( name != null ? name.hashCode() : 0 ); - result = 31 * result + ( stackTraceWriter != null ? stackTraceWriter.hashCode() : 0 ); - result = 31 * result + ( elapsed != null ? elapsed.hashCode() : 0 ); + int result = Objects.hashCode( getSourceName() ); + result = 31 * result + Objects.hashCode( getSourceText() ); + result = 31 * result + Objects.hashCode( getName() ); + result = 31 * result + Objects.hashCode( getNameText() ); + result = 31 * result + Objects.hashCode( getStackTraceWriter() ); + result = 31 * result + Objects.hashCode( getElapsed() ); + result = 31 * result + Objects.hashCode( getSystemProperties() ); + result = 31 * result + Objects.hashCode( getMessage() ); return result; } @Override public String getNameWithGroup() { - return getName(); + return getSourceName(); + } + + @Override + public String getReportNameWithGroup() + { + return getSourceText(); } @Override @@ -219,21 +249,41 @@ public Map getSystemProperties() private boolean isElapsedTimeEqual( SimpleReportEntry en ) { - return elapsed != null ? elapsed.equals( en.elapsed ) : en.elapsed == null; + return Objects.equals( getElapsed(), en.getElapsed() ); + } + + private boolean isNameTextEqual( SimpleReportEntry en ) + { + return Objects.equals( getNameText(), en.getNameText() ); } private boolean isNameEqual( SimpleReportEntry en ) { - return name != null ? name.equals( en.name ) : en.name == null; + return Objects.equals( getName(), en.getName() ); } private boolean isSourceEqual( SimpleReportEntry en ) { - return source != null ? source.equals( en.source ) : en.source == null; + return Objects.equals( getSourceName(), en.getSourceName() ); + } + + private boolean isSourceTextEqual( SimpleReportEntry en ) + { + return Objects.equals( getSourceText(), en.getSourceText() ); } private boolean isStackEqual( SimpleReportEntry en ) { - return stackTraceWriter != null ? stackTraceWriter.equals( en.stackTraceWriter ) : en.stackTraceWriter == null; + return Objects.equals( getStackTraceWriter(), en.getStackTraceWriter() ); + } + + private boolean isSystemPropertiesEqual( SimpleReportEntry en ) + { + return Objects.equals( getSystemProperties(), en.getSystemProperties() ); + } + + private boolean isMessageEqual( SimpleReportEntry en ) + { + return Objects.equals( getMessage(), en.getMessage() ); } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java index edc0e8ad33..266d06a8b9 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java @@ -257,7 +257,7 @@ public String getPluginParameterTest() } aggregatedTest += aggregatedTest( "!", getExcludedPatterns() ); - return aggregatedTest.length() == 0 ? "" : aggregatedTest; + return aggregatedTest.isEmpty() ? "" : aggregatedTest; } @Override diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultDirectoryScanner.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultDirectoryScanner.java index ee5ee5c687..fdb60f7a4c 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultDirectoryScanner.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultDirectoryScanner.java @@ -68,7 +68,7 @@ public DefaultDirectoryScanner( File basedir, List includes, List> result = new LinkedHashSet>(); + Set> result = new LinkedHashSet<>(); String[] specific = specificTests == null ? new String[0] : processIncludesExcludes( specificTests ); SpecificTestClassFilter specificTestFilter = new SpecificTestClassFilter( specific ); diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultRunOrderCalculator.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultRunOrderCalculator.java index dea10a69a5..22a219d25a 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultRunOrderCalculator.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultRunOrderCalculator.java @@ -57,7 +57,7 @@ public DefaultRunOrderCalculator( RunOrderParameters runOrderParameters, int thr @SuppressWarnings( "checkstyle:magicnumber" ) public TestsToRun orderTestClasses( TestsToRun scannedClasses ) { - List> result = new ArrayList>( 512 ); + List> result = new ArrayList<>( 512 ); for ( Class scannedClass : scannedClasses ) { @@ -65,7 +65,7 @@ public TestsToRun orderTestClasses( TestsToRun scannedClasses ) } orderTestClasses( result, runOrder.length != 0 ? runOrder[0] : null ); - return new TestsToRun( new LinkedHashSet>( result ) ); + return new TestsToRun( new LinkedHashSet<>( result ) ); } private void orderTestClasses( List> testClasses, RunOrder runOrder ) diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java index fc62f30959..943aaa75c1 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/DefaultScanResult.java @@ -90,7 +90,7 @@ public List getClasses() @Override public TestsToRun applyFilter( ScannerFilter scannerFilter, ClassLoader testClassLoader ) { - Set> result = new LinkedHashSet>(); + Set> result = new LinkedHashSet<>(); int size = size(); for ( int i = 0; i < size; i++ ) @@ -111,7 +111,7 @@ public TestsToRun applyFilter( ScannerFilter scannerFilter, ClassLoader testClas @Override public List> getClassesSkippedByValidation( ScannerFilter scannerFilter, ClassLoader testClassLoader ) { - List> result = new ArrayList>(); + List> result = new ArrayList<>(); int size = size(); for ( int i = 0; i < size; i++ ) diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/ReflectionUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/ReflectionUtils.java index 63b30ffed8..57e9ea72c2 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/ReflectionUtils.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/ReflectionUtils.java @@ -223,6 +223,12 @@ public static Class loadClass( ClassLoader classLoader, String className ) } } + public static Class reloadClass( ClassLoader classLoader, Object source ) + throws ReflectiveOperationException + { + return classLoader.loadClass( source.getClass().getName() ); + } + /** * Invoker of public static no-argument method. * diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/TestsToRun.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/TestsToRun.java index 8a264ca8fe..9957f5ea44 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/TestsToRun.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/TestsToRun.java @@ -51,7 +51,7 @@ public class TestsToRun implements Iterable> */ public TestsToRun( Set> locatedClasses ) { - this.locatedClasses = new ArrayList>( locatedClasses ); + this.locatedClasses = new ArrayList<>( locatedClasses ); } public static TestsToRun fromClass( Class clazz ) @@ -183,7 +183,7 @@ public Class[] getLocatedClasses() { throw new IllegalStateException( "Cannot eagerly read" ); } - Collection> result = new ArrayList>(); + Collection> result = new ArrayList<>(); for ( Class clazz : this ) { result.add( clazz ); diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/ClassMethod.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ClassMethod.java similarity index 63% rename from surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/ClassMethod.java rename to surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ClassMethod.java index a3ccccaf6e..03f9620166 100644 --- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/ClassMethod.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/ClassMethod.java @@ -1,4 +1,4 @@ -package org.apache.maven.surefire.common.junit4; +package org.apache.maven.surefire.util.internal; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,7 +19,9 @@ * under the License. */ -import org.apache.maven.surefire.util.internal.StringUtils; +import java.util.Objects; + +import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; /** * Data transfer object of class and method literals. @@ -36,9 +38,9 @@ public ClassMethod( String clazz, String method ) this.method = method; } - public boolean isValid() + public boolean isValidTest() { - return !StringUtils.isBlank( clazz ) && !StringUtils.isBlank( method ); + return !isBlank( clazz ) && !isBlank( method ); } public String getClazz() @@ -50,4 +52,26 @@ public String getMethod() { return method; } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + ClassMethod that = ( ClassMethod ) o; + return Objects.equals( clazz, that.clazz ) + && Objects.equals( method, that.method ); + } + + @Override + public int hashCode() + { + return Objects.hash( clazz, method ); + } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java index 86c09e3f1d..6f496900f4 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/StringUtils.java @@ -19,14 +19,9 @@ * under the License. */ -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; import java.util.StringTokenizer; import static java.lang.System.lineSeparator; -import static java.nio.charset.StandardCharsets.ISO_8859_1; /** *

@@ -57,11 +52,6 @@ public final class StringUtils { public static final String NL = lineSeparator(); - private static final byte[] HEX_CHARS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - - private static final Charset DEFAULT_CHARSET = Charset.defaultCharset(); - private StringUtils() { throw new IllegalStateException( "no instantiable constructor" ); @@ -115,215 +105,6 @@ public static boolean isNotBlank( String str ) return !isBlank( str ); } - /** - * Escape the specified string to a representation that only consists of nicely printable characters, without any - * newlines and without a comma. - *

- * The reverse-method is {@link #unescapeString(StringBuilder, CharSequence)}. - * - * @param target target string buffer. The required space will be up to {@code str.getBytes().length * 5} chars. - * @param str String to escape values in, may be {@code null}. - */ - @SuppressWarnings( "checkstyle:magicnumber" ) - public static void escapeToPrintable( StringBuilder target, CharSequence str ) - { - if ( target == null ) - { - throw new IllegalArgumentException( "The target buffer must not be null" ); - } - if ( str == null ) - { - return; - } - - for ( int i = 0; i < str.length(); i++ ) - { - char c = str.charAt( i ); - - // handle non-nicely printable chars and the comma - if ( c < 32 || c > 126 || c == '\\' || c == ',' ) - { - target.append( '\\' ); - target.append( (char) HEX_CHARS[( 0xF000 & c ) >> 12] ); - target.append( (char) HEX_CHARS[( 0x0F00 & c ) >> 8] ); - target.append( (char) HEX_CHARS[( 0x00F0 & c ) >> 4] ); - target.append( (char) HEX_CHARS[( 0x000F & c )] ); - } - else - { - target.append( c ); - } - } - } - - /** - * Reverses the effect of {@link #escapeToPrintable(StringBuilder, CharSequence)}. - * - * @param target target string buffer - * @param str the String to un-escape, as created by {@link #escapeToPrintable(StringBuilder, CharSequence)} - */ - public static void unescapeString( StringBuilder target, CharSequence str ) - { - if ( target == null ) - { - throw new IllegalArgumentException( "The target buffer must not be null" ); - } - if ( str == null ) - { - return; - } - - for ( int i = 0; i < str.length(); i++ ) - { - char ch = str.charAt( i ); - - if ( ch == '\\' ) - { - target.append( (char) ( - digit( str.charAt( ++i ) ) << 12 - | digit( str.charAt( ++i ) ) << 8 - | digit( str.charAt( ++i ) ) << 4 - | digit( str.charAt( ++i ) ) - ) ); - } - else - { - target.append( ch ); - } - } - } - - private static int digit( char ch ) - { - if ( ch >= 'a' ) - { - return 10 + ch - 'a'; - } - else if ( ch >= 'A' ) - { - return 10 + ch - 'A'; - } - else - { - return ch - '0'; - } - } - - /** - * Escapes the bytes in the array {@code input} to contain only 'printable' bytes. - *
- * Escaping is done by encoding the non-nicely printable bytes to {@code '\' + upperCaseHexBytes(byte)}. - *
- * The reverse-method is {@link #unescapeBytes(String, String)}. - *
- * The returned byte array is started with aligned sequence {@code header} and finished by {@code \n}. - * - * @param header prefix header - * @param input input buffer - * @param off offset in the input buffer - * @param len number of bytes to copy from the input buffer - * @return number of bytes written to {@code out} - * @throws NullPointerException if the specified parameter {@code header} or {@code input} is null - * @throws IndexOutOfBoundsException if {@code off} or {@code len} is out of range - * ({@code off < 0 || len < 0 || off >= input.length || len > input.length || off + len > input.length}) - */ - @SuppressWarnings( "checkstyle:magicnumber" ) - public static EncodedArray escapeBytesToPrintable( final byte[] header, final byte[] input, final int off, - final int len ) - { - if ( input.length == 0 ) - { - return EncodedArray.EMPTY; - } - if ( off < 0 || len < 0 || off >= input.length || len > input.length || off + len > input.length ) - { - throw new IndexOutOfBoundsException( - "off < 0 || len < 0 || off >= input.length || len > input.length || off + len > input.length" ); - } - // Hex-escaping can be up to 3 times length of a regular byte. Last character is '\n', see (+1). - final byte[] encodeBytes = new byte[header.length + 3 * len + 1]; - System.arraycopy( header, 0, encodeBytes, 0, header.length ); - int outputPos = header.length; - final int end = off + len; - for ( int i = off; i < end; i++ ) - { - final byte b = input[i]; - - // handle non-nicely printable bytes - if ( b < 32 || b > 126 || b == '\\' || b == ',' ) - { - final int upper = ( 0xF0 & b ) >> 4; - final int lower = ( 0x0F & b ); - encodeBytes[outputPos++] = '\\'; - encodeBytes[outputPos++] = HEX_CHARS[upper]; - encodeBytes[outputPos++] = HEX_CHARS[lower]; - } - else - { - encodeBytes[outputPos++] = b; - } - } - encodeBytes[outputPos++] = (byte) '\n'; - - return new EncodedArray( encodeBytes, outputPos ); - } - - /** - * Reverses the effect of {@link #escapeBytesToPrintable(byte[], byte[], int, int)}. - * - * @param str the input String - * @param charsetName the charset name - * @return the number of bytes written to {@code out} - */ - public static ByteBuffer unescapeBytes( String str, String charsetName ) - { - int outPos = 0; - - if ( str == null ) - { - return ByteBuffer.wrap( new byte[0] ); - } - - byte[] out = new byte[str.length()]; - for ( int i = 0; i < str.length(); i++ ) - { - char ch = str.charAt( i ); - - if ( ch == '\\' ) - { - int upper = digit( str.charAt( ++i ) ); - int lower = digit( str.charAt( ++i ) ); - out[outPos++] = (byte) ( upper << 4 | lower ); - } - else - { - out[outPos++] = (byte) ch; - } - } - - Charset sourceCharset = Charset.forName( charsetName ); - if ( !DEFAULT_CHARSET.equals( sourceCharset ) ) - { - CharBuffer decodedFromSourceCharset; - try - { - decodedFromSourceCharset = sourceCharset.newDecoder().decode( ByteBuffer.wrap( out, 0, outPos ) ); - return DEFAULT_CHARSET.encode( decodedFromSourceCharset ); - } - catch ( CharacterCodingException e ) - { - // ignore and fall through to the non-recoded version - } - } - - return ByteBuffer.wrap( out, 0, outPos ); - } - - public static byte[] encodeStringForForkCommunication( String string ) - { - return string.getBytes( ISO_8859_1 ); - } - /** * Determines if {@code buffer} starts with specific literal(s). * @@ -349,31 +130,4 @@ public static boolean startsWith( StringBuffer buffer, String pattern ) return true; } } - - /** - * Escaped string to byte array with offset 0 and certain length. - */ - public static final class EncodedArray - { - private static final EncodedArray EMPTY = new EncodedArray( new byte[]{}, 0 ); - - private final byte[] array; - private final int size; - - private EncodedArray( byte[] array, int size ) - { - this.array = array; - this.size = size; - } - - public byte[] getArray() - { - return array; - } - - public int getSize() - { - return size; - } - } } diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/TestClassMethodNameUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/TestClassMethodNameUtils.java index 23e72e1011..94bf4c8c79 100644 --- a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/TestClassMethodNameUtils.java +++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/TestClassMethodNameUtils.java @@ -19,24 +19,15 @@ * under the License. */ -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * JUnit Description parser. - * Used by JUnit Version lower than 4.7. + * Used by JUnit4+. * * @author Tibor Digana (tibor17) * @since 2.20 */ public final class TestClassMethodNameUtils { - /** - * This pattern is verbatim copy from JUnit's code in class {@code Description}. - * Parsing class and method from junit description would provide identical result to JUnit internal parser. - */ - private static final Pattern METHOD_CLASS_PATTERN = Pattern.compile( "([\\s\\S]*)\\((.*)\\)" ); - private TestClassMethodNameUtils() { throw new IllegalStateException( "no instantiable constructor" ); @@ -44,13 +35,26 @@ private TestClassMethodNameUtils() public static String extractClassName( String displayName ) { - Matcher m = METHOD_CLASS_PATTERN.matcher( displayName ); - return m.matches() ? m.group( 2 ) : displayName; + String clazz = displayName; + if ( displayName.endsWith( ")" ) ) + { + int paren = displayName.lastIndexOf( '(' ); + if ( paren != -1 ) + { + clazz = displayName.substring( paren + 1, displayName.length() - 1 ); + } + } + return clazz; } public static String extractMethodName( String displayName ) { - Matcher m = METHOD_CLASS_PATTERN.matcher( displayName ); - return m.matches() ? m.group( 1 ) : displayName; + String method = null; + int parent = displayName.lastIndexOf( '(' ); + if ( parent != -1 ) + { + method = displayName.substring( 0, parent ); + } + return method; } } diff --git a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java index dad6079eda..38f0c48301 100644 --- a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java +++ b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java @@ -23,6 +23,8 @@ import junit.framework.Test; import org.apache.maven.plugin.surefire.runorder.ThreadedExecutionSchedulerTest; import org.apache.maven.surefire.SpecificTestClassFilterTest; +import org.apache.maven.surefire.booter.CommandReaderTest; +import org.apache.maven.surefire.booter.ForkedChannelEncoderTest; import org.apache.maven.surefire.booter.ForkingRunListenerTest; import org.apache.maven.surefire.booter.MasterProcessCommandTest; import org.apache.maven.surefire.booter.SurefireReflectorTest; @@ -39,7 +41,6 @@ import org.apache.maven.surefire.util.TestsToRunTest; import org.apache.maven.surefire.util.internal.ConcurrencyUtilsTest; import org.apache.maven.surefire.util.internal.ImmutableMapTest; -import org.apache.maven.surefire.util.internal.StringUtilsTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -50,6 +51,7 @@ * @since 2.19 */ @Suite.SuiteClasses( { + CommandReaderTest.class, ThreadedExecutionSchedulerTest.class, ForkingRunListenerTest.class, MasterProcessCommandTest.class, @@ -59,7 +61,6 @@ ResolvedTestTest.class, TestListResolverTest.class, ConcurrencyUtilsTest.class, - StringUtilsTest.class, DefaultDirectoryScannerTest.class, RunOrderCalculatorTest.class, RunOrderTest.class, @@ -68,7 +69,8 @@ SpecificTestClassFilterTest.class, FundamentalFilterTest.class, ImmutableMapTest.class, - ReflectionUtilsTest.class + ReflectionUtilsTest.class, + ForkedChannelEncoderTest.class } ) @RunWith( Suite.class ) public class JUnit4SuiteTest diff --git a/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionSchedulerTest.java b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionSchedulerTest.java index 15963d776e..5c607ef651 100644 --- a/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionSchedulerTest.java +++ b/surefire-api/src/test/java/org/apache/maven/plugin/surefire/runorder/ThreadedExecutionSchedulerTest.java @@ -1,4 +1,5 @@ package org.apache.maven.plugin.surefire.runorder; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -21,6 +22,7 @@ import java.util.List; import junit.framework.TestCase; +import org.apache.maven.surefire.util.internal.ClassMethod; /** * @author Kristian Rosenvold @@ -29,24 +31,23 @@ public class ThreadedExecutionSchedulerTest extends TestCase { - private final RunEntryStatistics a1 = RunEntryStatistics.fromValues( 200, 2, A.class, "at1" ); + private final RunEntryStatistics a1 = fromValues( 200, 2, A.class, "at1" ); - private final RunEntryStatistics a2 = RunEntryStatistics.fromValues( 300, 2, A.class, "at2" ); + private final RunEntryStatistics a2 = fromValues( 300, 2, A.class, "at2" ); - private final RunEntryStatistics b1 = RunEntryStatistics.fromValues( 400, 2, B.class, "bt1" ); + private final RunEntryStatistics b1 = fromValues( 400, 2, B.class, "bt1" ); - private final RunEntryStatistics b2 = RunEntryStatistics.fromValues( 300, 2, B.class, "bt2" ); + private final RunEntryStatistics b2 = fromValues( 300, 2, B.class, "bt2" ); - private final RunEntryStatistics c1 = RunEntryStatistics.fromValues( 400, 2, C.class, "ct1" ); + private final RunEntryStatistics c1 = fromValues( 400, 2, C.class, "ct1" ); - private final RunEntryStatistics c2 = RunEntryStatistics.fromValues( 200, 2, C.class, "ct2" ); + private final RunEntryStatistics c2 = fromValues( 200, 2, C.class, "ct2" ); - private final RunEntryStatistics d1 = RunEntryStatistics.fromValues( 401, 2, D.class, "ct2" ); + private final RunEntryStatistics d1 = fromValues( 401, 2, D.class, "ct2" ); - private final RunEntryStatistics e1 = RunEntryStatistics.fromValues( 200, 2, E.class, "ct2" ); + private final RunEntryStatistics e1 = fromValues( 200, 2, E.class, "ct2" ); public void testAddTest() - throws Exception { ThreadedExecutionScheduler threadedExecutionScheduler = new ThreadedExecutionScheduler( 2 ); addPrioritizedTests( threadedExecutionScheduler ); @@ -57,17 +58,14 @@ public void testAddTest() assertEquals( D.class, result.get( 2 ) ); assertEquals( A.class, result.get( 3 ) ); assertEquals( E.class, result.get( 4 ) ); - } public void testAddTestJaggedResult() - throws Exception { ThreadedExecutionScheduler threadedExecutionScheduler = new ThreadedExecutionScheduler( 4 ); addPrioritizedTests( threadedExecutionScheduler ); final List result = threadedExecutionScheduler.getResult(); assertEquals( 5, result.size() ); - } private void addPrioritizedTests( ThreadedExecutionScheduler threadedExecutionScheduler ) @@ -94,6 +92,11 @@ private Priority createPriority( RunEntryStatistics runEntryStatistics, RunEntry return priority; } + private static RunEntryStatistics fromValues( int runTime, int successfulBuilds, Class clazz, String testName ) + { + ClassMethod classMethod = new ClassMethod( clazz.getName(), testName ); + return new RunEntryStatistics( runTime, successfulBuilds, classMethod ); + } class A { diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/SpecificTestClassFilterTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/SpecificTestClassFilterTest.java index 905c7feb18..0cb8da0c59 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/SpecificTestClassFilterTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/SpecificTestClassFilterTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,40 +21,40 @@ import junit.framework.TestCase; -public class SpecificTestClassFilterTest - extends TestCase +/** + * + */ +public class SpecificTestClassFilterTest extends TestCase { - public void testMatchSingleCharacterWildcard() { - SpecificTestClassFilter filter = - new SpecificTestClassFilter( new String[]{ "org/apache/maven/surefire/?pecificTestClassFilter.class" } ); + SpecificTestClassFilter filter = new SpecificTestClassFilter( + new String[] {"org/apache/maven/surefire/?pecificTestClassFilter.class"} ); assertTrue( filter.accept( SpecificTestClassFilter.class ) ); } public void testMatchSingleSegmentWordWildcard() { - SpecificTestClassFilter filter = - new SpecificTestClassFilter( new String[]{ "org/apache/maven/surefire/*TestClassFilter.class" } ); + SpecificTestClassFilter filter = new SpecificTestClassFilter( + new String[] {"org/apache/maven/surefire/*TestClassFilter.class"} ); assertTrue( filter.accept( SpecificTestClassFilter.class ) ); } public void testMatchMultiSegmentWildcard() { - SpecificTestClassFilter filter = - new SpecificTestClassFilter( new String[]{ "org/**/SpecificTestClassFilter.class" } ); + SpecificTestClassFilter filter = new SpecificTestClassFilter( + new String[] {"org/**/SpecificTestClassFilter.class"} ); assertTrue( filter.accept( SpecificTestClassFilter.class ) ); } public void testMatchSingleSegmentWildcard() { - SpecificTestClassFilter filter = - new SpecificTestClassFilter( new String[]{ "org/*/maven/surefire/SpecificTestClassFilter.class" } ); + SpecificTestClassFilter filter = new SpecificTestClassFilter( + new String[] {"org/*/maven/surefire/SpecificTestClassFilter.class"} ); assertTrue( filter.accept( SpecificTestClassFilter.class ) ); } - } diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/CommandReaderTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/CommandReaderTest.java similarity index 83% rename from surefire-booter/src/test/java/org/apache/maven/surefire/booter/CommandReaderTest.java rename to surefire-api/src/test/java/org/apache/maven/surefire/booter/CommandReaderTest.java index 740b46d9af..40c02432f1 100644 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/CommandReaderTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/booter/CommandReaderTest.java @@ -57,20 +57,27 @@ @RunWith( NewClassLoaderRunner.class ) public class CommandReaderTest { + private static final long DELAY = 200L; + private static final long TEST_TIMEOUT = 15_000L; + private final BlockingQueue blockingStream = new LinkedBlockingQueue<>(); private InputStream realInputStream; private CommandReader reader; - static class A { + static class A + { } - static class B { + static class B + { } - static class C { + static class C + { } - static class D { + static class D + { } @Before @@ -93,7 +100,7 @@ public void deinit() @Test public void readJustOneClass() { - Iterator it = reader.getIterableClasses( nul() ).iterator(); + Iterator it = reader.getIterableClasses( new ForkedChannelEncoder( nul() ) ).iterator(); assertTrue( it.hasNext() ); assertThat( it.next(), is( getClass().getName() ) ); reader.stop(); @@ -112,7 +119,7 @@ public void readJustOneClass() @Test public void manyClasses() { - Iterator it1 = reader.getIterableClasses( nul() ).iterator(); + Iterator it1 = reader.getIterableClasses( new ForkedChannelEncoder( nul() ) ).iterator(); assertThat( it1.next(), is( getClass().getName() ) ); addTestToPipeline( A.class.getName() ); assertThat( it1.next(), is( A.class.getName() ) ); @@ -128,14 +135,14 @@ public void manyClasses() @Test public void twoIterators() throws Exception { - Iterator it1 = reader.getIterableClasses( nul() ).iterator(); + Iterator it1 = reader.getIterableClasses( new ForkedChannelEncoder( nul() ) ).iterator(); assertThat( it1.next(), is( getClass().getName() ) ); addTestToPipeline( A.class.getName() ); assertThat( it1.next(), is( A.class.getName() ) ); addTestToPipeline( B.class.getName() ); - TimeUnit.MILLISECONDS.sleep( 200 ); // give the test chance to fail + TimeUnit.MILLISECONDS.sleep( DELAY ); // give the test chance to fail Iterator it2 = reader.iterated(); @@ -154,15 +161,14 @@ public void twoIterators() throws Exception } @Test( expected = NoSuchElementException.class ) - public void stopBeforeReadInThread() - throws Throwable + public void stopBeforeReadInThread() throws Throwable { Runnable runnable = new Runnable() { @Override public void run() { - Iterator it = reader.getIterableClasses( nul() ).iterator(); + Iterator it = reader.getIterableClasses( new ForkedChannelEncoder( nul() ) ).iterator(); assertThat( it.next(), is( CommandReaderTest.class.getName() ) ); } }; @@ -181,8 +187,7 @@ public void run() } @Test - public void readTwoClassesInThread() - throws Throwable + public void readTwoClassesInThread() throws Throwable { final CountDownLatch counter = new CountDownLatch( 1 ); Runnable runnable = new Runnable() @@ -190,17 +195,17 @@ public void readTwoClassesInThread() @Override public void run() { - Iterator it = reader.getIterableClasses( nul() ).iterator(); + Iterator it = reader.getIterableClasses( new ForkedChannelEncoder( nul() ) ).iterator(); assertThat( it.next(), is( CommandReaderTest.class.getName() ) ); counter.countDown(); - assertThat( it.next(), is( PropertiesWrapperTest.class.getName() ) ); + assertThat( it.next(), is( Foo.class.getName() ) ); } }; FutureTask futureTask = new FutureTask<>( runnable, null ); Thread t = new Thread( futureTask ); t.start(); counter.await(); - addTestToPipeline( PropertiesWrapperTest.class.getName() ); + addTestToPipeline( Foo.class.getName() ); try { futureTask.get(); @@ -211,21 +216,18 @@ public void run() } } - @Test( timeout = 15000 ) - public void shouldAwaitReaderUp() - throws TestSetFailedException + @Test( timeout = TEST_TIMEOUT ) + public void shouldAwaitReaderUp() throws TestSetFailedException { assertTrue( reader.awaitStarted() ); reader.stop(); assertFalse( reader.awaitStarted() ); } - private class SystemInputStream - extends InputStream + private class SystemInputStream extends InputStream { @Override - public int read() - throws IOException + public int read() throws IOException { try { @@ -241,10 +243,8 @@ public int read() private void addTestToPipeline( String cls ) { byte[] clazz = cls.getBytes( ISO_8859_1 ); - ByteBuffer buffer = ByteBuffer.allocate( 8 + clazz.length ) - .putInt( MasterProcessCommand.RUN_CLASS.getId() ) - .putInt( clazz.length ) - .put( clazz ); + ByteBuffer buffer = ByteBuffer.allocate( 8 + clazz.length ).putInt( + MasterProcessCommand.RUN_CLASS.getId() ).putInt( clazz.length ).put( clazz ); buffer.rewind(); for ( ; buffer.hasRemaining(); ) { @@ -254,9 +254,8 @@ private void addTestToPipeline( String cls ) private void addEndOfPipeline() { - ByteBuffer buffer = ByteBuffer.allocate( 8 ) - .putInt( MasterProcessCommand.TEST_SET_FINISHED.getId() ) - .putInt( 0 ); + ByteBuffer buffer = ByteBuffer.allocate( 8 ).putInt( MasterProcessCommand.TEST_SET_FINISHED.getId() ).putInt( + 0 ); buffer.rewind(); for ( ; buffer.hasRemaining(); ) { diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/Foo.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/Foo.java similarity index 100% rename from surefire-booter/src/test/java/org/apache/maven/surefire/booter/Foo.java rename to surefire-api/src/test/java/org/apache/maven/surefire/booter/Foo.java diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/booter/ForkedChannelEncoderTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/ForkedChannelEncoderTest.java new file mode 100644 index 0000000000..efa89e0a77 --- /dev/null +++ b/surefire-api/src/test/java/org/apache/maven/surefire/booter/ForkedChannelEncoderTest.java @@ -0,0 +1,1094 @@ +package org.apache.maven.surefire.booter; + +/* + * 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.report.ReportEntry; +import org.apache.maven.surefire.report.SafeThrowable; +import org.apache.maven.surefire.report.StackTraceWriter; +import org.apache.maven.surefire.util.internal.ObjectUtils; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.PrintStream; +import java.io.StringReader; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.Map; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Arrays.copyOfRange; +import static org.apache.commons.codec.binary.Base64.encodeBase64String; +import static org.apache.maven.surefire.booter.ForkedChannelEncoder.encode; +import static org.apache.maven.surefire.booter.ForkedChannelEncoder.encodeHeader; +import static org.apache.maven.surefire.booter.ForkedChannelEncoder.encodeMessage; +import static org.apache.maven.surefire.booter.ForkedChannelEncoder.encodeOpcode; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.BOOTERCODE_SYSPROPS; +import static org.apache.maven.surefire.booter.ForkedProcessEvent.MAGIC_NUMBER; +import static org.apache.maven.surefire.report.RunMode.NORMAL_RUN; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Test for {@link ForkedChannelEncoder}. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class ForkedChannelEncoderTest +{ + private static final int ELAPSED_TIME = 102; + + @Test + public void shouldBeFailSafe() + { + assertThat( ForkedChannelEncoder.toBase64( null ) ).isEqualTo( "-" ); + assertThat( ForkedChannelEncoder.toBase64( "" ) ).isEqualTo( "" ); + } + + @Test + public void shouldHaveSystemProperty() + { + StringBuilder actualEncoded = encode( BOOTERCODE_SYSPROPS, NORMAL_RUN, "arg1", "arg2" ); + String expected = MAGIC_NUMBER + BOOTERCODE_SYSPROPS.getOpcode() + ":normal-run" + ":UTF-8:YXJnMQ==:YXJnMg=="; + + assertThat( actualEncoded.toString() ) + .isEqualTo( expected ); + } + + @Test + public void safeThrowableShouldBeEncoded() + { + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1\ntrace line 2"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + StringBuilder encoded = new StringBuilder(); + encode( encoded, stackTraceWriter, false ); + assertThat( encoded.toString() ) + .isEqualTo( ":" + encodedExceptionMsg + ":" + encodedSmartStackTrace + ":" + encodedStackTrace ); + + encoded = new StringBuilder(); + encode( encoded, stackTraceWriter, true ); + assertThat( encoded.toString() ) + .isEqualTo( ":" + encodedExceptionMsg + ":" + encodedSmartStackTrace + ":" + encodedTrimmedStackTrace ); + } + + @Test + public void emptySafeThrowable() + { + SafeThrowable safeThrowable = new SafeThrowable( new Exception( "" ) ); + + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( "" ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( "" ); + + StringBuilder encoded = new StringBuilder(); + encode( encoded, stackTraceWriter, false ); + + assertThat( encoded.toString() ) + .isEqualTo( ":::" ); + } + + @Test + public void nullSafeThrowable() + { + SafeThrowable safeThrowable = new SafeThrowable( new Exception() ); + + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + + StringBuilder encoded = new StringBuilder(); + encode( encoded, stackTraceWriter, false ); + + assertThat( encoded.toString() ) + .isEqualTo( ":-:-:-" ); + } + + @Test + public void reportEntry() throws IOException + { + final String exceptionMessage = "msg"; + final String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + final String smartStackTrace = "MyTest:86 >> Error"; + final String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + final String stackTrace = "trace line 1\ntrace line 2"; + final String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + final String trimmedStackTrace = "trace line 1\ntrace line 2"; + final String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + StringBuilder encode = encode( "X", "normal-run", reportEntry, false ); + assertThat( encode.toString() ) + .isEqualTo( ":maven:surefire:std:out:X:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace + ); + + encode = encode( "X", "normal-run", reportEntry, true ); + assertThat( encode.toString() ) + .isEqualTo( ":maven:surefire:std:out:X:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace + ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testSetStarting( reportEntry, true ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:testset-starting:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + + out = Stream.newStream(); + forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testSetStarting( reportEntry, false ); + printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:testset-starting:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testSetCompleted() throws IOException + { + String exceptionMessage = "msg"; + String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + String smartStackTrace = "MyTest:86 >> Error"; + String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + String stackTrace = "trace line 1\ntrace line 2"; + String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + String trimmedStackTrace = "trace line 1\ntrace line 2"; + String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testSetCompleted( reportEntry, false ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:testset-completed:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testStarting() throws IOException + { + String exceptionMessage = "msg"; + String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + String smartStackTrace = "MyTest:86 >> Error"; + String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + String stackTrace = "trace line 1\ntrace line 2"; + String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + String trimmedStackTrace = "trace line 1\ntrace line 2"; + String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testStarting( reportEntry, true ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:test-starting:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testSuccess() throws IOException + { + String exceptionMessage = "msg"; + String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + String smartStackTrace = "MyTest:86 >> Error"; + String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + String stackTrace = "trace line 1\ntrace line 2"; + String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + String trimmedStackTrace = "trace line 1\ntrace line 2"; + String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testSucceeded( reportEntry, true ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:test-succeeded:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedTrimmedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testFailed() throws IOException + { + String exceptionMessage = "msg"; + String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + String smartStackTrace = "MyTest:86 >> Error"; + String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + String stackTrace = "trace line 1\ntrace line 2"; + String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + String trimmedStackTrace = "trace line 1\ntrace line 2"; + String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testFailed( reportEntry, false ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:test-failed:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testSkipped() throws IOException + { + String encodedExceptionMsg = "-"; + + String smartStackTrace = "MyTest:86 >> Error"; + String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + String stackTrace = "trace line 1\ntrace line 2"; + String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + String trimmedStackTrace = "trace line 1\ntrace line 2"; + String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception() ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testSkipped( reportEntry, false ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:test-skipped:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testError() throws IOException + { + String encodedExceptionMsg = "-"; + + String encodedSmartStackTrace = "-"; + + String stackTrace = "trace line 1\ntrace line 2"; + String encodedStackTrace = encodeBase64String( toArray( UTF_8.encode( stackTrace ) ) ); + + String trimmedStackTrace = "trace line 1\ntrace line 2"; + String encodedTrimmedStackTrace = encodeBase64String( toArray( UTF_8.encode( trimmedStackTrace ) ) ); + + SafeThrowable safeThrowable = new SafeThrowable( new Exception() ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( null ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( trimmedStackTrace ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( stackTrace ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( ELAPSED_TIME ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testError( reportEntry, false ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:test-error:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + ELAPSED_TIME + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testAssumptionFailure() throws IOException + { + String exceptionMessage = "msg"; + String encodedExceptionMsg = encodeBase64String( toArray( UTF_8.encode( exceptionMessage ) ) ); + + String smartStackTrace = "MyTest:86 >> Error"; + String encodedSmartStackTrace = encodeBase64String( toArray( UTF_8.encode( smartStackTrace ) ) ); + + String encodedStackTrace = "-"; + + SafeThrowable safeThrowable = new SafeThrowable( new Exception( exceptionMessage ) ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( safeThrowable ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( smartStackTrace ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( null ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( null ); + + ReportEntry reportEntry = mock( ReportEntry.class ); + when( reportEntry.getElapsed() ).thenReturn( null ); + when( reportEntry.getGroup() ).thenReturn( "this group" ); + when( reportEntry.getMessage() ).thenReturn( "skipped test" ); + when( reportEntry.getName() ).thenReturn( "my test" ); + when( reportEntry.getNameWithGroup() ).thenReturn( "name with group" ); + when( reportEntry.getSourceName() ).thenReturn( "pkg.MyTest" ); + when( reportEntry.getStackTraceWriter() ).thenReturn( stackTraceWriter ); + + String encodedSourceName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getSourceName() ) ) ); + String encodedName = encodeBase64String( toArray( UTF_8.encode( reportEntry.getName() ) ) ); + String encodedGroup = encodeBase64String( toArray( UTF_8.encode( reportEntry.getGroup() ) ) ); + String encodedMessage = encodeBase64String( toArray( UTF_8.encode( reportEntry.getMessage() ) ) ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.testAssumptionFailure( reportEntry, false ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:test-assumption-failure:normal-run:UTF-8:" + + encodedSourceName + + ":" + + "-" + + ":" + + encodedName + + ":" + + "-" + + ":" + + encodedGroup + + ":" + + encodedMessage + + ":" + + "-" + + ":" + + + encodedExceptionMsg + + ":" + + encodedSmartStackTrace + + ":" + + encodedStackTrace + ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testBye() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.bye(); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:bye" ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testStopOnNextTest() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.stopOnNextTest(); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:stop-on-next-test" ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testAcquireNextTest() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.acquireNextTest(); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( ":maven:surefire:std:out:next-test" ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testSendOpcode() + { + StringBuilder encoded = encodeOpcode( "some-opcode", "normal-run" ); + assertThat( encoded.toString() ) + .isEqualTo( ":maven:surefire:std:out:some-opcode:normal-run" ); + + encoded = encodeHeader( "some-opcode", "normal-run" ); + assertThat( encoded.toString() ) + .isEqualTo( ":maven:surefire:std:out:some-opcode:normal-run:UTF-8" ); + + encoded = encodeMessage( "some-opcode", "normal-run", "msg" ); + assertThat( encoded.toString() ) + .isEqualTo( ":maven:surefire:std:out:some-opcode:normal-run:UTF-8:msg" ); + + Stream out = Stream.newStream(); + ForkedChannelEncoder encoder = new ForkedChannelEncoder( out ); + encoded = encoder.print( "some-opcode", "msg" ); + assertThat( encoded.toString() ) + .isEqualTo( ":maven:surefire:std:out:some-opcode:UTF-8:bXNn" ); + + encoded = encoder.print( "some-opcode", new String[] { null } ); + assertThat( encoded.toString() ) + .isEqualTo( ":maven:surefire:std:out:some-opcode:UTF-8:-" ); + } + + @Test + public void testConsoleInfo() + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.consoleInfoLog( "msg" ); + + String encoded = new String( out.toByteArray(), UTF_8 ); + + String expected = ":maven:surefire:std:out:console-info-log:UTF-8:" + + encodeBase64String( toArray( UTF_8.encode( "msg" ) ) ) + + "\n"; + + assertThat( encoded ) + .isEqualTo( expected ); + } + + @Test + public void testConsoleError() + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.consoleErrorLog( "msg" ); + + String encoded = new String( out.toByteArray(), UTF_8 ); + + String expected = ":maven:surefire:std:out:console-error-log:UTF-8:" + + encodeBase64String( toArray( UTF_8.encode( "msg" ) ) ) + + "\n"; + + assertThat( encoded ) + .isEqualTo( expected ); + } + + @Test + public void testConsoleErrorLog1() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.consoleErrorLog( new Exception( "msg" ) ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .startsWith( ":maven:surefire:std:out:console-error-log:UTF-8:bXNn:-:" ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testConsoleErrorLog2() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.consoleErrorLog( "msg2", new Exception( "msg" ) ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .startsWith( ":maven:surefire:std:out:console-error-log:UTF-8:bXNnMg==:-:" ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testConsoleErrorLog3() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( new SafeThrowable( "1" ) ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( "2" ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( "3" ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( "4" ); + + forkedChannelEncoder.consoleErrorLog( stackTraceWriter, true ); + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .startsWith( ":maven:surefire:std:out:console-error-log:UTF-8:MQ==:Mg==:NA==" ); + assertThat( printedLines.readLine() ).isNull(); + } + + @Test + public void testConsoleDebug() + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.consoleDebugLog( "msg" ); + + String encoded = new String( out.toByteArray(), UTF_8 ); + + String expected = ":maven:surefire:std:out:console-debug-log:UTF-8:" + + encodeBase64String( toArray( UTF_8.encode( "msg" ) ) ) + + "\n"; + + assertThat( encoded ) + .isEqualTo( expected ); + } + + @Test + public void testConsoleWarning() + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.consoleWarningLog( "msg" ); + + String encoded = new String( out.toByteArray(), UTF_8 ); + + String expected = ":maven:surefire:std:out:console-warning-log:UTF-8:" + + encodeBase64String( toArray( UTF_8.encode( "msg" ) ) ) + + "\n"; + + assertThat( encoded ) + .isEqualTo( expected ); + } + + @Test + public void testStdOutStream() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.stdOut( "msg", false ); + + String expected = ":maven:surefire:std:out:std-out-stream:normal-run:UTF-8:bXNn"; + + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( expected ); + assertThat( printedLines.readLine() ) + .isNull(); + } + + @Test + public void testStdOutStreamLn() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.stdOut( "msg", true ); + + String expected = ":maven:surefire:std:out:std-out-stream-new-line:normal-run:UTF-8:bXNn"; + + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( expected ); + assertThat( printedLines.readLine() ) + .isNull(); + } + + @Test + public void testStdErrStream() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.stdErr( "msg", false ); + + String expected = ":maven:surefire:std:out:std-err-stream:normal-run:UTF-8:bXNn"; + + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( expected ); + assertThat( printedLines.readLine() ) + .isNull(); + } + + @Test + public void testStdErrStreamLn() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + forkedChannelEncoder.stdErr( "msg", true ); + + String expected = ":maven:surefire:std:out:std-err-stream-new-line:normal-run:UTF-8:bXNn"; + + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .isEqualTo( expected ); + assertThat( printedLines.readLine() ) + .isNull(); + } + + @Test + @SuppressWarnings( "checkstyle:innerassignment" ) + public void shouldCountSameNumberOfSystemProperties() throws IOException + { + Stream out = Stream.newStream(); + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + + Map sysProps = ObjectUtils.systemProps(); + int expectedSize = sysProps.size(); + forkedChannelEncoder.sendSystemProperties( sysProps ); + + LineNumberReader printedLines = out.newReader( UTF_8 ); + + int size = 0; + for ( String line; ( line = printedLines.readLine() ) != null; size++ ) + { + assertThat( line ) + .startsWith( ":maven:surefire:std:out:sys-prop:normal-run:UTF-8:" ); + } + + assertThat( size ) + .isEqualTo( expectedSize ); + } + + @Test + public void shouldHandleExit() throws IOException + { + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( new SafeThrowable( "1" ) ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( "2" ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( "3" ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( "4" ); + forkedChannelEncoder.sendExitEvent( stackTraceWriter, false ); + + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .startsWith( ":maven:surefire:std:out:jvm-exit-error:UTF-8:MQ==:Mg==:Mw==" ); + } + + @Test + public void shouldHandleExitWithTrimmedTrace() throws IOException + { + Stream out = Stream.newStream(); + + ForkedChannelEncoder forkedChannelEncoder = new ForkedChannelEncoder( out ); + StackTraceWriter stackTraceWriter = mock( StackTraceWriter.class ); + when( stackTraceWriter.getThrowable() ).thenReturn( new SafeThrowable( "1" ) ); + when( stackTraceWriter.smartTrimmedStackTrace() ).thenReturn( "2" ); + when( stackTraceWriter.writeTraceToString() ).thenReturn( "3" ); + when( stackTraceWriter.writeTrimmedTraceToString() ).thenReturn( "4" ); + forkedChannelEncoder.sendExitEvent( stackTraceWriter, true ); + + LineNumberReader printedLines = out.newReader( UTF_8 ); + assertThat( printedLines.readLine() ) + .startsWith( ":maven:surefire:std:out:jvm-exit-error:UTF-8:MQ==:Mg==:NA==" ); + } + + private static class Stream extends PrintStream + { + private final ByteArrayOutputStream out; + + Stream( ByteArrayOutputStream out ) + { + super( out, true ); + this.out = out; + } + + byte[] toByteArray() + { + return out.toByteArray(); + } + + LineNumberReader newReader( Charset streamCharset ) + { + return new LineNumberReader( new StringReader( new String( toByteArray(), streamCharset ) ) ); + } + + static Stream newStream() + { + return new Stream( new ByteArrayOutputStream() ); + } + } + + private static byte[] toArray( ByteBuffer buffer ) + { + return copyOfRange( buffer.array(), buffer.arrayOffset(), buffer.arrayOffset() + buffer.remaining() ); + } + +} diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/booter/ForkingRunListenerTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/ForkingRunListenerTest.java index b71eda274e..549f3aabdc 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/booter/ForkingRunListenerTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/booter/ForkingRunListenerTest.java @@ -1,22 +1,23 @@ package org.apache.maven.surefire.booter; + /* -* 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. -*/ + * 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.ByteArrayOutputStream; import java.io.PrintStream; @@ -30,13 +31,11 @@ public class ForkingRunListenerTest extends TestCase { public void testInfo() - throws Exception { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); PrintStream target = new PrintStream( byteArrayOutputStream ); - ForkingRunListener forkingRunListener = new ForkingRunListener( target, 1, true ); - forkingRunListener.info( new String( new byte[]{ 65 } ) ); + ForkingRunListener forkingRunListener = new ForkingRunListener( new ForkedChannelEncoder( target ), true ); + forkingRunListener.info( new String( new byte[]{ (byte) 'A' } ) ); forkingRunListener.info( new String( new byte[]{ } ) ); - } } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java index 19740fdbf5..cfd4d5f5c3 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/booter/MasterProcessCommandTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.booter; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -26,9 +27,14 @@ import java.io.DataInputStream; import java.io.IOException; -import static org.apache.maven.surefire.booter.MasterProcessCommand.*; +import static org.apache.maven.surefire.booter.MasterProcessCommand.decode; +import static org.apache.maven.surefire.booter.MasterProcessCommand.resolve; +import static org.apache.maven.surefire.booter.MasterProcessCommand.setCommandAndDataLength; +import static org.apache.maven.surefire.booter.MasterProcessCommand.BYE_ACK; +import static org.apache.maven.surefire.booter.MasterProcessCommand.NOOP; +import static org.apache.maven.surefire.booter.MasterProcessCommand.RUN_CLASS; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * @author Tibor Digana (tibor17) @@ -90,13 +96,9 @@ public void testDataToByteArrayAndBack() assertThat( decoded, is( dummyData ) ); break; case TEST_SET_FINISHED: - assertEquals( Void.class, command.getDataType() ); - encoded = command.fromDataType( dummyData ); - assertThat( encoded.length, is( 0 ) ); - decoded = command.toDataTypeAsString( encoded ); - assertNull( decoded ); - break; case SKIP_SINCE_NEXT_TEST: + case NOOP: + case BYE_ACK: assertEquals( Void.class, command.getDataType() ); encoded = command.fromDataType( dummyData ); assertThat( encoded.length, is( 0 ) ); @@ -110,20 +112,6 @@ public void testDataToByteArrayAndBack() decoded = command.toDataTypeAsString( encoded ); assertThat( decoded, is( Shutdown.EXIT.name() ) ); break; - case NOOP: - assertEquals( Void.class, command.getDataType() ); - encoded = command.fromDataType( dummyData ); - assertThat( encoded.length, is( 0 ) ); - decoded = command.toDataTypeAsString( encoded ); - assertNull( decoded ); - break; - case BYE_ACK: - assertEquals( Void.class, command.getDataType() ); - encoded = command.fromDataType( dummyData ); - assertThat( encoded.length, is( 0 ) ); - decoded = command.toDataTypeAsString( encoded ); - assertNull( decoded ); - break; default: fail(); } diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/NewClassLoaderRunner.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/NewClassLoaderRunner.java similarity index 96% rename from surefire-booter/src/test/java/org/apache/maven/surefire/booter/NewClassLoaderRunner.java rename to surefire-api/src/test/java/org/apache/maven/surefire/booter/NewClassLoaderRunner.java index 3511951003..780f2f0e10 100644 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/NewClassLoaderRunner.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/booter/NewClassLoaderRunner.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.shared.utils.io.FileUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -45,7 +46,6 @@ import java.util.List; import static java.io.File.pathSeparator; -import static org.apache.commons.io.FileUtils.readFileToString; /** * JUnit runner testing methods in a separate class loader. @@ -189,10 +189,10 @@ private static Class getFromTestClassLoader( String clazz, TestClassLoader lo } } - public static class TestClassLoader + private static class TestClassLoader extends URLClassLoader { - public TestClassLoader() + TestClassLoader() { super( toClassPath(), null ); } @@ -235,7 +235,8 @@ private static Collection toPathList() Collection classPath = new HashSet<>(); try { - String[] files = readFileToString( new File( "target/test-classpath/cp.txt" ) ).split( pathSeparator ); + String[] files = FileUtils.fileRead( new File( "target/test-classpath/cp.txt" ), "UTF-8" ) + .split( pathSeparator ); for ( String file : files ) { File f = new File( file ); diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java index 8394e00a1a..0a006bfd24 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java @@ -1,41 +1,89 @@ package org.apache.maven.surefire.booter; + /* -* 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. -*/ + * 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 junit.framework.TestCase; +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.surefire.report.ReporterConfiguration; import org.apache.maven.surefire.report.ReporterFactory; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.suite.RunResult; +import org.apache.maven.surefire.testset.DirectoryScannerParameters; +import org.apache.maven.surefire.testset.RunOrderParameters; +import org.apache.maven.surefire.testset.TestArtifactInfo; +import org.apache.maven.surefire.testset.TestListResolver; +import org.apache.maven.surefire.testset.TestRequest; +import org.apache.maven.surefire.util.RunOrder; +import org.mockito.ArgumentCaptor; + +import java.io.File; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +/** + * + */ public class SurefireReflectorTest extends TestCase { + public void testCreateConsoleLogger() + { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + ConsoleLogger consoleLogger = mock( ConsoleLogger.class ); + ConsoleLogger decorator = (ConsoleLogger) SurefireReflector.createConsoleLogger( consoleLogger, cl ); + assertThat( decorator ) + .isNotSameAs( consoleLogger ); + + assertThat( decorator.isDebugEnabled() ).isFalse(); + when( consoleLogger.isDebugEnabled() ).thenReturn( true ); + assertThat( decorator.isDebugEnabled() ).isTrue(); + verify( consoleLogger, times( 2 ) ).isDebugEnabled(); + + decorator.info( "msg" ); + ArgumentCaptor argumentMsg = ArgumentCaptor.forClass( String.class ); + verify( consoleLogger, times( 1 ) ).info( argumentMsg.capture() ); + assertThat( argumentMsg.getAllValues() ).hasSize( 1 ); + assertThat( argumentMsg.getAllValues().get( 0 ) ).isEqualTo( "msg" ); + } + public void testShouldCreateFactoryWithoutException() { - ReporterFactory factory = new ReporterFactory() { + ReporterFactory factory = new ReporterFactory() + { @Override - public RunListener createReporter() { + public RunListener createReporter() + { return null; } @Override - public RunResult close() { + public RunResult close() + { return null; } }; @@ -46,4 +94,105 @@ public RunResult close() { assertNotNull( baseProviderFactory.getReporterFactory() ); assertSame( factory, baseProviderFactory.getReporterFactory() ); } + + public void testSetDirectoryScannerParameters() + { + SurefireReflector surefireReflector = getReflector(); + Object foo = getFoo(); + + DirectoryScannerParameters directoryScannerParameters = + new DirectoryScannerParameters( new File( "ABC" ), new ArrayList(), new ArrayList(), + new ArrayList(), false, "hourly" ); + surefireReflector.setDirectoryScannerParameters( foo, directoryScannerParameters ); + assertTrue( isCalled( foo ) ); + } + + public void testRunOrderParameters() + { + SurefireReflector surefireReflector = getReflector(); + Object foo = getFoo(); + + RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, new File( "." ) ); + surefireReflector.setRunOrderParameters( foo, runOrderParameters ); + assertTrue( isCalled( foo ) ); + } + + public void testTestSuiteDefinition() + { + SurefireReflector surefireReflector = getReflector(); + Object foo = getFoo(); + + TestRequest testSuiteDefinition = + new TestRequest( Arrays.asList( new File( "file1" ), new File( "file2" ) ), + new File( "TestSOurce" ), new TestListResolver( "aUserRequestedTest#aMethodRequested" ) ); + surefireReflector.setTestSuiteDefinition( foo, testSuiteDefinition ); + assertTrue( isCalled( foo ) ); + } + + public void testProviderProperties() + { + SurefireReflector surefireReflector = getReflector(); + Object foo = getFoo(); + + surefireReflector.setProviderProperties( foo, new HashMap() ); + assertTrue( isCalled( foo ) ); + } + + public void testReporterConfiguration() + { + SurefireReflector surefireReflector = getReflector(); + Object foo = getFoo(); + + ReporterConfiguration reporterConfiguration = getReporterConfiguration(); + surefireReflector.setReporterConfigurationAware( foo, reporterConfiguration ); + assertTrue( isCalled( foo ) ); + } + + private ReporterConfiguration getReporterConfiguration() + { + return new ReporterConfiguration( new File( "CDE" ), true ); + } + + public void testTestClassLoaderAware() + { + SurefireReflector surefireReflector = getReflector(); + Object foo = getFoo(); + + surefireReflector.setTestClassLoader( foo, getClass().getClassLoader() ); + assertTrue( isCalled( foo ) ); + } + + public void testArtifactInfoAware() + { + SurefireReflector surefireReflector = getReflector(); + Object foo = getFoo(); + + TestArtifactInfo testArtifactInfo = new TestArtifactInfo( "12.3", "test" ); + surefireReflector.setTestArtifactInfo( foo, testArtifactInfo ); + assertTrue( isCalled( foo ) ); + } + + private SurefireReflector getReflector() + { + return new SurefireReflector( this.getClass().getClassLoader() ); + } + + private Object getFoo() + { // Todo: Setup a different classloader so we can really test crossing + return new Foo(); + } + + private Boolean isCalled( Object foo ) + { + final Method isCalled; + try + { + isCalled = foo.getClass().getMethod( "isCalled" ); + return (Boolean) isCalled.invoke( foo ); + } + catch ( ReflectiveOperationException e ) + { + throw new RuntimeException( e ); + } + } } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/report/LegacyPojoStackTraceWriterTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/report/LegacyPojoStackTraceWriterTest.java index d81e8165b9..60bbc0989d 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/report/LegacyPojoStackTraceWriterTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/report/LegacyPojoStackTraceWriterTest.java @@ -26,112 +26,106 @@ /** * @author Kristian Rosenvold */ -public class LegacyPojoStackTraceWriterTest - extends TestCase +public class LegacyPojoStackTraceWriterTest extends TestCase { + @SuppressWarnings( "checkstyle:linelength" ) public void testWriteTrimmedTraceToString() { - String stackTrace = "junit.framework.AssertionFailedError: blah\n" + - " at junit.framework.Assert.fail(Assert.java:47)\n" + - " at TestSurefire3.testQuote(TestSurefire3.java:23)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + - " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + - " at java.lang.reflect.Method.invoke(Method.java:585)\n" + - " at junit.framework.TestCase.runTest(TestCase.java:154)\n" + - " at junit.framework.TestCase.runBare(TestCase.java:127)\n" + - " at junit.framework.TestResult$1.protect(TestResult.java:106)\n" + - " at junit.framework.TestResult.runProtected(TestResult.java:124)\n" + - " at junit.framework.TestResult.run(TestResult.java:109)\n" + - " at junit.framework.TestCase.run(TestCase.java:118)\n" + - " at junit.framework.TestSuite.runTest(TestSuite.java:208)\n" + - " at junit.framework.TestSuite.run(TestSuite.java:203)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + - " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + - " at java.lang.reflect.Method.invoke(Method.java:585)\n" + - " at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:213)\n" + - " at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)\n" - + - " at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)\n" - + - " at org.apache.maven.surefire.Surefire.run(Surefire.java:132)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + - " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + - " at java.lang.reflect.Method.invoke(Method.java:585)\n" + - " at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:318)\n" + - " at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:956)\n"; + String stackTrace = "junit.framework.AssertionFailedError: blah\n" + + " at junit.framework.Assert.fail(Assert.java:47)\n" + + " at TestSurefire3.testQuote(TestSurefire3.java:23)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + + " at java.lang.reflect.Method.invoke(Method.java:585)\n" + + " at junit.framework.TestCase.runTest(TestCase.java:154)\n" + + " at junit.framework.TestCase.runBare(TestCase.java:127)\n" + + " at junit.framework.TestResult$1.protect(TestResult.java:106)\n" + + " at junit.framework.TestResult.runProtected(TestResult.java:124)\n" + + " at junit.framework.TestResult.run(TestResult.java:109)\n" + + " at junit.framework.TestCase.run(TestCase.java:118)\n" + + " at junit.framework.TestSuite.runTest(TestSuite.java:208)\n" + + " at junit.framework.TestSuite.run(TestSuite.java:203)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + + " at java.lang.reflect.Method.invoke(Method.java:585)\n" + + " at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:213)\n" + + " at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)\n" + + " at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)\n" + + " at org.apache.maven.surefire.Surefire.run(Surefire.java:132)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + + " at java.lang.reflect.Method.invoke(Method.java:585)\n" + + " at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:318)\n" + + " at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:956)\n"; MockThrowable t = new MockThrowable( stackTrace ); LegacyPojoStackTraceWriter w = new LegacyPojoStackTraceWriter( "TestSurefire3", "testQuote", t ); String out = w.writeTrimmedTraceToString(); - String expected = "junit.framework.AssertionFailedError: blah\n" + - " at junit.framework.Assert.fail(Assert.java:47)\n" + - " at TestSurefire3.testQuote(TestSurefire3.java:23)\n"; + String expected = "junit.framework.AssertionFailedError: blah\n" + " at junit.framework.Assert.fail(Assert.java:47)\n" + " at TestSurefire3.testQuote(TestSurefire3.java:23)\n"; assertEquals( expected, out ); } + @SuppressWarnings( "checkstyle:linelength" ) public void testCausedBy() { - String stackTrace = "java.lang.RuntimeException: blah\n" + - " at TestSurefire3.testBlah(TestSurefire3.java:45)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + - " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + - " at java.lang.reflect.Method.invoke(Method.java:585)\n" + - " at junit.framework.TestCase.runTest(TestCase.java:154)\n" + - " at junit.framework.TestCase.runBare(TestCase.java:127)\n" + - " at junit.framework.TestResult$1.protect(TestResult.java:106)\n" + - " at junit.framework.TestResult.runProtected(TestResult.java:124)\n" + - " at junit.framework.TestResult.run(TestResult.java:109)\n" + - " at junit.framework.TestCase.run(TestCase.java:118)\n" + - " at junit.framework.TestSuite.runTest(TestSuite.java:208)\n" + - " at junit.framework.TestSuite.run(TestSuite.java:203)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + - " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + - " at java.lang.reflect.Method.invoke(Method.java:585)\n" + - " at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:213)\n" + - " at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)\n" - + - " at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)\n" - + - " at org.apache.maven.surefire.Surefire.run(Surefire.java:132)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + - " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + - " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + - " at java.lang.reflect.Method.invoke(Method.java:585)\n" + - " at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:318)\n" + - " at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:956)\n" + - "Caused by: junit.framework.AssertionFailedError: \"\n" + - " at junit.framework.Assert.fail(Assert.java:47)\n" + - " at TestSurefire3.testQuote(TestSurefire3.java:23)\n" + - " at TestSurefire3.testBlah(TestSurefire3.java:43)\n" + - " at TestSurefire3.testBlah(TestSurefire3.java:43)\n" + - " ... 26 more\n"; + String stackTrace = "java.lang.RuntimeException: blah\n" + + " at TestSurefire3.testBlah(TestSurefire3.java:45)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + + " at java.lang.reflect.Method.invoke(Method.java:585)\n" + + " at junit.framework.TestCase.runTest(TestCase.java:154)\n" + + " at junit.framework.TestCase.runBare(TestCase.java:127)\n" + + " at junit.framework.TestResult$1.protect(TestResult.java:106)\n" + + " at junit.framework.TestResult.runProtected(TestResult.java:124)\n" + + " at junit.framework.TestResult.run(TestResult.java:109)\n" + + " at junit.framework.TestCase.run(TestCase.java:118)\n" + + " at junit.framework.TestSuite.runTest(TestSuite.java:208)\n" + + " at junit.framework.TestSuite.run(TestSuite.java:203)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + + " at java.lang.reflect.Method.invoke(Method.java:585)\n" + + " at org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:213)\n" + + " at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)\n" + + " at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)\n" + + " at org.apache.maven.surefire.Surefire.run(Surefire.java:132)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + " at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n" + + " at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n" + + " at java.lang.reflect.Method.invoke(Method.java:585)\n" + + " at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:318)\n" + + " at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:956)\n" + + "Caused by: junit.framework.AssertionFailedError: \"\n" + + " at junit.framework.Assert.fail(Assert.java:47)\n" + + " at TestSurefire3.testQuote(TestSurefire3.java:23)\n" + + " at TestSurefire3.testBlah(TestSurefire3.java:43)\n" + + " at TestSurefire3.testBlah(TestSurefire3.java:43)\n" + + " ... 26 more\n"; MockThrowable t = new MockThrowable( stackTrace ); LegacyPojoStackTraceWriter w = new LegacyPojoStackTraceWriter( "TestSurefire3", "testBlah", t ); String out = w.writeTrimmedTraceToString(); - String expected = "java.lang.RuntimeException: blah\n" + - " at TestSurefire3.testBlah(TestSurefire3.java:45)\n" + - "Caused by: junit.framework.AssertionFailedError: \"\n" + - " at junit.framework.Assert.fail(Assert.java:47)\n" + - " at TestSurefire3.testQuote(TestSurefire3.java:23)\n" + - " at TestSurefire3.testBlah(TestSurefire3.java:43)\n" + - " at TestSurefire3.testBlah(TestSurefire3.java:43)\n" + - " ... 26 more\n"; + String expected = "java.lang.RuntimeException: blah\n" + + " at TestSurefire3.testBlah(TestSurefire3.java:45)\n" + + "Caused by: junit.framework.AssertionFailedError: \"\n" + + " at junit.framework.Assert.fail(Assert.java:47)\n" + + " at TestSurefire3.testQuote(TestSurefire3.java:23)\n" + + " at TestSurefire3.testBlah(TestSurefire3.java:43)\n" + + " at TestSurefire3.testBlah(TestSurefire3.java:43)\n" + + " ... 26 more\n"; assertEquals( expected, out ); } - class MockThrowable - extends Throwable + static class MockThrowable extends Throwable { private static final long serialVersionUID = 1L; private final String stackTrace; - public MockThrowable( String stackTrace ) + MockThrowable( String stackTrace ) { this.stackTrace = stackTrace; } @@ -145,8 +139,7 @@ public void printStackTrace( PrintWriter s ) public void testMultiLineMessage() { - String msg = - "assert \"foo\" == \"bar\"\n" + String msg = "assert \"foo\" == \"bar\"\n" + " |\n" + " false"; try @@ -160,5 +153,4 @@ public void testMultiLineMessage() assertTrue( stackTrace.startsWith( "java.lang.RuntimeException: \n" + msg ) ); } } - } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java index e888ca259d..67fc171c36 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/suite/RunResultTest.java @@ -34,6 +34,7 @@ public void testEmptySummaryShouldBeErrorFree() assertTrue( summary.isErrorFree() ); } + @SuppressWarnings( "checkstyle:magicnumber" ) public void testFailuresInFirstRun() { RunResult resultOne = new RunResult( 10, 1, 3, 2 ); diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/testset/FundamentalFilterTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/testset/FundamentalFilterTest.java index b99d4f98c8..63fb571137 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/testset/FundamentalFilterTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/testset/FundamentalFilterTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.testset; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -21,7 +22,7 @@ import org.junit.Test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; @SuppressWarnings( { "javadoc", "checkstyle:javadoctype" } ) /** diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/testset/ResolvedTestTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/testset/ResolvedTestTest.java index f636c72f16..2a0d0d0ea4 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/testset/ResolvedTestTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/testset/ResolvedTestTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.testset; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -24,6 +25,9 @@ import static org.apache.maven.surefire.testset.ResolvedTest.Type.METHOD; import static org.apache.maven.surefire.testset.ResolvedTest.fromFullyQualifiedClass; +/** + * + */ public class ResolvedTestTest extends TestCase { @@ -53,19 +57,19 @@ public void testEmptyMethodRegex() public void testFromFullyQualifiedClass() { - String classFileName = fromFullyQualifiedClass("my.package.MyTest"); + String classFileName = fromFullyQualifiedClass( "my.package.MyTest" ); assertEquals( "my/package/MyTest", classFileName ); - classFileName = fromFullyQualifiedClass("my.package.MyTest.class"); + classFileName = fromFullyQualifiedClass( "my.package.MyTest.class" ); assertEquals( "my/package/MyTest.class", classFileName ); - classFileName = fromFullyQualifiedClass("my/package/MyTest.class"); + classFileName = fromFullyQualifiedClass( "my/package/MyTest.class" ); assertEquals( "my/package/MyTest.class", classFileName ); - classFileName = fromFullyQualifiedClass("my/package/MyTest.*"); + classFileName = fromFullyQualifiedClass( "my/package/MyTest.*" ); assertEquals( "my/package/MyTest.*", classFileName ); - classFileName = fromFullyQualifiedClass("my.package.MyTest.*"); + classFileName = fromFullyQualifiedClass( "my.package.MyTest.*" ); assertEquals( "my/package/MyTest.*", classFileName ); } } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java index d7a53b6581..00ce3d196e 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.testset; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -35,8 +36,11 @@ import static java.util.Collections.emptySet; import static java.util.Collections.singleton; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +/** + * + */ public class TestListResolverTest extends TestCase { @@ -235,7 +239,8 @@ public void testResolveTestRequest() public void testShouldRunTestWithoutMethod() { - new TestListResolver("**/*Test.class, !%regex[.*.MyTest.class#myTest]").shouldRun( "pkg/MyTest.class", null ); + new TestListResolver( "**/*Test.class, !%regex[.*.MyTest.class#myTest]" ) + .shouldRun( "pkg/MyTest.class", null ); } public void testShouldNotRunExcludedMethods() @@ -328,7 +333,7 @@ public void testTestListResolverWithoutMethods() ResolvedTest inc2 = new ResolvedTest( "**/?Test", null, false ); ResolvedTest exc1 = new ResolvedTest( "AATest", null, false ); ResolvedTest exc2 = new ResolvedTest( "**/BTest.java", null, false ); - TestListResolver resolver = newTestListResolver( $( inc1, inc2 ), $( exc1, exc2 ) ); + TestListResolver resolver = newTestListResolver( toSet( inc1, inc2 ), toSet( exc1, exc2 ) ); assertThat( resolver.getPluginParameterTest(), is( "A?Test.java, **/?Test, !AATest, !**/BTest.java" ) ); assertFalse( resolver.isEmpty() ); assertFalse( resolver.hasIncludedMethodPatterns() ); @@ -348,7 +353,7 @@ public void testTestListResolverWithMethods() ResolvedTest inc2 = new ResolvedTest( "*?Test", null, false ); ResolvedTest exc1 = new ResolvedTest( "AATest", null, false ); ResolvedTest exc2 = new ResolvedTest( "*BTest.java", "failedTest", false ); - TestListResolver resolver = newTestListResolver( $( inc1, inc2 ), $( exc1, exc2 ) ); + TestListResolver resolver = newTestListResolver( toSet( inc1, inc2 ), toSet( exc1, exc2 ) ); assertThat( resolver.getPluginParameterTest(), is( "A?Test.java, *?Test, !AATest, !*BTest.java#failedTest" ) ); assertFalse( resolver.isEmpty() ); assertFalse( resolver.hasIncludedMethodPatterns() ); @@ -363,7 +368,7 @@ public void testTestListResolverWithMethods() assertFalse( TestListResolver.optionallyWildcardFilter( resolver ).isEmpty() ); } - private static Set $( ResolvedTest... patterns ) + private static Set toSet( ResolvedTest... patterns ) { Set set = new LinkedHashSet<>(); addAll( set, patterns ); diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/ReflectionUtilsTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/ReflectionUtilsTest.java index 5440d6eab0..9941626d59 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/ReflectionUtilsTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/ReflectionUtilsTest.java @@ -31,7 +31,15 @@ */ public class ReflectionUtilsTest { - @Test(expected = RuntimeException.class) + @Test + public void shouldReloadClass() throws Exception + { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + assertThat( ReflectionUtils.reloadClass( cl, new B() ) ) + .isEqualTo( B.class ); + } + + @Test( expected = RuntimeException.class ) public void shouldNotInvokeStaticMethod() { ReflectionUtils.invokeStaticMethod( ReflectionUtilsTest.class, "notCallable", @@ -88,7 +96,7 @@ public static long callable() return 3L; } - public static class A + static class A { public static A current() { @@ -106,7 +114,7 @@ public B createB() } } - public static class B + static class B { public long pid() { diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderCalculatorTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderCalculatorTest.java index 30a7560e53..2308d0cf55 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderCalculatorTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderCalculatorTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.util; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -33,33 +34,29 @@ public class RunOrderCalculatorTest { public void testOrderTestClasses() - throws Exception { getClassesToRun(); TestsToRun testsToRun = new TestsToRun( getClassesToRun() ); RunOrderCalculator runOrderCalculator = new DefaultRunOrderCalculator( RunOrderParameters.alphabetical(), 1 ); final TestsToRun testsToRun1 = runOrderCalculator.orderTestClasses( testsToRun ); assertEquals( A.class, testsToRun1.iterator().next() ); - } private Set> getClassesToRun() { - Set> classesToRun = new LinkedHashSet>(); + Set> classesToRun = new LinkedHashSet<>(); classesToRun.add( B.class ); classesToRun.add( A.class ); return classesToRun; } - class A + static class A { } - class B + static class B { } - - } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderTest.java index 13e5a43824..cf60eba500 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/RunOrderTest.java @@ -21,6 +21,9 @@ import junit.framework.TestCase; +/** + * + */ public class RunOrderTest extends TestCase { diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/TestsToRunTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/TestsToRunTest.java index 0041056ff5..1acd420303 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/TestsToRunTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/TestsToRunTest.java @@ -25,17 +25,15 @@ import junit.framework.TestCase; -/* +/** * @author Kristian Rosenvold */ - public class TestsToRunTest extends TestCase { public void testGetTestSets() - throws Exception { - Set> classes = new LinkedHashSet>(); + Set> classes = new LinkedHashSet<>(); classes.add( T1.class ); classes.add( T2.class ); TestsToRun testsToRun = new TestsToRun( classes ); @@ -49,7 +47,7 @@ public void testGetTestSets() public void testContainsAtLeast() { - Set> classes = new LinkedHashSet>(); + Set> classes = new LinkedHashSet<>(); classes.add( T1.class ); classes.add( T2.class ); TestsToRun testsToRun = new TestsToRun( classes ); @@ -59,7 +57,7 @@ public void testContainsAtLeast() public void testContainsExactly() { - Set> classes = new LinkedHashSet>(); + Set> classes = new LinkedHashSet<>(); classes.add( T1.class ); classes.add( T2.class ); TestsToRun testsToRun = new TestsToRun( classes ); @@ -70,7 +68,7 @@ public void testContainsExactly() public void testToRunArray() { - Set> classes = new LinkedHashSet>(); + Set> classes = new LinkedHashSet<>(); classes.add( T1.class ); classes.add( T2.class ); TestsToRun testsToRun = new TestsToRun( classes ); @@ -80,18 +78,18 @@ public void testToRunArray() public void testGetClassByName() { - Set> classes = new LinkedHashSet>(); + Set> classes = new LinkedHashSet<>(); classes.add( T1.class ); classes.add( T2.class ); TestsToRun testsToRun = new TestsToRun( classes ); assertEquals( T1.class, testsToRun.getClassByName( "org.apache.maven.surefire.util.TestsToRunTest$T1" ) ); assertEquals( T2.class, testsToRun.getClassByName( "org.apache.maven.surefire.util.TestsToRunTest$T2" ) ); - assertEquals( null, testsToRun.getClassByName( "org.apache.maven.surefire.util.TestsToRunTest$T3" ) ); + assertNull( testsToRun.getClassByName( "org.apache.maven.surefire.util.TestsToRunTest$T3" ) ); } public void testTwoIterators() { - Set> classes = new LinkedHashSet>(); + Set> classes = new LinkedHashSet<>(); classes.add( T1.class ); classes.add( T2.class ); TestsToRun testsToRun = new TestsToRun( classes ); @@ -110,12 +108,12 @@ public void testTwoIterators() assertFalse( it1.hasNext() ); } - class T1 + static class T1 { } - class T2 + static class T2 { } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java index 7e76fbfa35..30c4a04120 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ConcurrencyUtilsTest.java @@ -42,7 +42,7 @@ public class ConcurrencyUtilsTest { @Test - public void countDownShouldBeUnchangedAsZero$NegativeTest() + public void countDownShouldBeUnchangedAsZeroNegativeTest() { AtomicInteger atomicCounter = new AtomicInteger( 0 ); assertFalse( countDownToZero( atomicCounter ) ); @@ -50,7 +50,7 @@ public class ConcurrencyUtilsTest } @Test - public void countDownShouldBeUnchangedAsNegative$NegativeTest() + public void countDownShouldBeUnchangedAsNegativeNegativeTest() { AtomicInteger atomicCounter = new AtomicInteger( -1 ); assertFalse( countDownToZero( atomicCounter ) ); diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ImmutableMapTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ImmutableMapTest.java index 0cfe918fef..1da1e22b4b 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ImmutableMapTest.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/ImmutableMapTest.java @@ -23,7 +23,9 @@ import org.junit.Before; import org.junit.Test; -import java.util.HashMap; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -31,6 +33,8 @@ import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; /** @@ -41,9 +45,9 @@ public class ImmutableMapTest private ImmutableMap map; @Before - public void setUp() throws Exception + public void setUp() { - Map backingMap = new HashMap<>(); + Map backingMap = new LinkedHashMap<>(); backingMap.put( "a", "1" ); backingMap.put( "x", null ); backingMap.put( "b", "2" ); @@ -54,7 +58,7 @@ public void setUp() throws Exception } @Test - public void testEntrySet() throws Exception + public void testEntrySet() { Set> entries = map.entrySet(); assertThat( entries, hasSize( 6 ) ); @@ -83,4 +87,78 @@ public void shouldNotModifyEntries() { map.entrySet().clear(); } -} \ No newline at end of file + + @Test + public void shouldSafelyEnumerateEntries() + { + Iterator> it = map.entrySet().iterator(); + + assertThat( it.hasNext(), is( true ) ); + Entry val = it.next(); + assertThat( val.getKey(), is( "a" ) ); + assertThat( val.getValue(), is( "1" ) ); + + assertThat( it.hasNext(), is( true ) ); + val = it.next(); + assertThat( val.getKey(), is( "x" ) ); + assertThat( val.getValue(), is( nullValue() ) ); + + assertThat( it.hasNext(), is( true ) ); + val = it.next(); + assertThat( val.getKey(), is( "b" ) ); + assertThat( val.getValue(), is( "2" ) ); + + assertThat( it.hasNext(), is( true ) ); + val = it.next(); + assertThat( val.getKey(), is( "c" ) ); + assertThat( val.getValue(), is( "3" ) ); + + assertThat( it.hasNext(), is( true ) ); + val = it.next(); + assertThat( val.getKey(), is( "" ) ); + assertThat( val.getValue(), is( "" ) ); + + assertThat( it.hasNext(), is( true ) ); + val = it.next(); + assertThat( val.getKey(), is( nullValue() ) ); + assertThat( val.getValue(), is( "1" ) ); + + assertThat( it.hasNext(), is( false ) ); + } + + @Test( expected = UnsupportedOperationException.class ) + public void shouldNotSetEntries() + { + map.entrySet().iterator().next().setValue( "" ); + } + + @Test( expected = UnsupportedOperationException.class ) + public void shouldNotRemove() + { + map.remove( "a" ); + } + + @Test( expected = UnsupportedOperationException.class ) + public void shouldNotRemoveNull() + { + map.remove( null ); + } + + @Test + public void shouldNotHaveEqualEntry() + { + Map map = new ImmutableMap<>( Collections.singletonMap( "k", "v" ) ); + Entry e = map.entrySet().iterator().next(); + assertThat( e, is( not( (Entry) null ) ) ); + assertThat( e, is( not( new Object() ) ) ); + } + + @Test + public void shouldHaveEqualEntry() + { + Map map = new ImmutableMap<>( Collections.singletonMap( "k", "v" ) ); + Entry e = map.entrySet().iterator().next(); + assertThat( e, is( e ) ); + assertThat( e, is( (Entry) new Node<>( "k", "v" ) ) ); + } +} diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/StringUtilsTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/StringUtilsTest.java deleted file mode 100644 index e686086e99..0000000000 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/internal/StringUtilsTest.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.apache.maven.surefire.util.internal; - -/* - * 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.nio.ByteBuffer; -import java.nio.charset.Charset; - -import junit.framework.TestCase; -import org.apache.maven.surefire.util.internal.StringUtils.EncodedArray; - -import static org.junit.Assert.assertArrayEquals; - -/** - * @author Andreas Gudian - */ -public class StringUtilsTest - extends TestCase -{ - - public void testUnescapeString() - { - CharSequence inputString = createInputString(); - - StringBuilder escaped = new StringBuilder( inputString.length() * 5 ); - int initialCapacity = escaped.capacity(); - - StringUtils.escapeToPrintable( escaped, inputString ); - - assertEquals( initialCapacity, escaped.capacity() ); - - StringBuilder unescaped = new StringBuilder( inputString.length() ); - StringUtils.unescapeString( unescaped, escaped ); - - assertEquals( inputString.length(), unescaped.length() ); - - for ( int i = 0; i < inputString.length(); i++ ) - { - if ( inputString.charAt( i ) != unescaped.charAt( i ) ) - { - fail( "Input and Unescaped String are not equal at position " + i ); - } - } - } - - private CharSequence createInputString() - { - StringBuilder sb = new StringBuilder(); - for ( int i = 0; i < Character.MAX_CODE_POINT; i++ ) - { - sb.appendCodePoint( i ); - } - - return sb; - } - - public void testUnescapeBytes() - { - byte[] input = new byte[256]; - - for ( int i = 0; i <= 0xFF; i++ ) - { - byte b = (byte) ( 0xFF & i ); - input[i] = b; - } - - EncodedArray encodedArray = StringUtils.escapeBytesToPrintable( new byte[0], input, 0, input.length ); - - String escapedString = new String( encodedArray.getArray(), 0, encodedArray.getSize() ); - - assertEquals( encodedArray.getSize(), escapedString.length() ); - - ByteBuffer unescaped = StringUtils.unescapeBytes( escapedString, Charset.defaultCharset().name() ); - - assertEquals( input.length + 1, unescaped.remaining() - unescaped.position() ); - - for ( int i = 0; i < input.length; i++ ) - { - assertEquals( "At position " + i, input[i], unescaped.get() ); - } - } - - public void testEscapeWithHeader() - { - byte[] header = { (byte) 'a' }; - byte[] input = { (byte) '1' }; - - EncodedArray encodedArray = StringUtils.escapeBytesToPrintable( header, input, 0, input.length ); - assertEquals( 3, encodedArray.getSize() ); - - byte[] expectedResult = new byte[] { (byte) 'a', (byte) '1', (byte) '\n' }; - byte[] actualResult = new byte[encodedArray.getSize()]; - System.arraycopy( encodedArray.getArray(), 0, actualResult, 0, encodedArray.getSize() ); - - assertArrayEquals( expectedResult, actualResult ); - } - - public void testEmptyByteArray() - { - byte[] header = { (byte) 'a' }; - byte[] input = {}; - EncodedArray encodedArray = StringUtils.escapeBytesToPrintable( header, input, 0, input.length ); - assertEquals( 0, encodedArray.getSize() ); - assertEquals( 0, encodedArray.getArray().length ); - } - - public void testSubstringSmall() - { - byte[] header = { (byte) 'a' }; - byte[] input = "PleaseLookAfterThisBear".getBytes(); - EncodedArray encodedArray = StringUtils.escapeBytesToPrintable( header, input, - "Please".length(), "Look".length() ); - assertEquals( "Look", - new String( encodedArray.getArray(), 1, encodedArray.getArray().length-1).trim() ); - } - - public void testSubstringLarge() - { - byte[] header = { (byte) 'a' }; - byte[] input = "TheQuickBrownFoxJumpsOverTheLazyDog".getBytes(); - EncodedArray encodedArray = StringUtils.escapeBytesToPrintable( header, input, - "The".length(), "QuickBrownFoxJumpsOverTheLazy".length() ); - assertEquals( "QuickBrownFoxJumpsOverTheLazy", - new String( encodedArray.getArray(), 1, encodedArray.getArray().length-1).trim() ); - } -} diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT1A.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT1A.java index 1d69e2d50b..2c3a725609 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT1A.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT1A.java @@ -1,3 +1,5 @@ +package org.apache.maven.surefire.util.testdata; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,9 @@ * under the License. */ -package org.apache.maven.surefire.util.testdata; - +/** + * + */ public class DataZT1A { } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT2A.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT2A.java index 682747e227..e016215779 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT2A.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT2A.java @@ -1,3 +1,5 @@ +package org.apache.maven.surefire.util.testdata; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,9 +19,9 @@ * under the License. */ -package org.apache.maven.surefire.util.testdata; - - +/** + * + */ public class DataZT2A { } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT3A.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT3A.java index 782286f55b..5abbf9fc14 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT3A.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/DataZT3A.java @@ -1,3 +1,5 @@ +package org.apache.maven.surefire.util.testdata; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,9 +19,9 @@ * under the License. */ -package org.apache.maven.surefire.util.testdata; - - +/** + * + */ public class DataZT3A { } diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/java/javascript/DataJavaZT4A.java b/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/java/javascript/DataJavaZT4A.java index 8b869de040..b497ace29e 100644 --- a/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/java/javascript/DataJavaZT4A.java +++ b/surefire-api/src/test/java/org/apache/maven/surefire/util/testdata/java/javascript/DataJavaZT4A.java @@ -1,3 +1,5 @@ +package org.apache.maven.surefire.util.testdata.java.javascript; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,8 +19,6 @@ * under the License. */ -package org.apache.maven.surefire.util.testdata.java.javascript; - /** * Test data class for SUREFIRE-638 * User: sslavic diff --git a/surefire-booter/pom.xml b/surefire-booter/pom.xml index d863e91bbf..387c2c8307 100644 --- a/surefire-booter/pom.xml +++ b/surefire-booter/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 surefire-booter @@ -61,6 +61,11 @@ jsr305 provided + + commons-codec + commons-codec + test + org.mockito mockito-core @@ -81,23 +86,31 @@ powermock-api-mockito2 test + + org.jacoco + org.jacoco.agent + runtime + test + - maven-dependency-plugin + org.jacoco + jacoco-maven-plugin - build-test-classpath - generate-sources + jacoco-instrumentation - build-classpath + instrument + + + + restore-classes + + restore-instrumented-classes - - test - target/test-classpath/cp.txt - @@ -107,13 +120,17 @@ org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 + ${jvm.args.tests} **/JUnit4SuiteTest.java + + ${project.build.directory}/jacoco.exec + 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 c9651ab272..30d9a86d50 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 @@ 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 @@ protected AbstractPathConfiguration( @Nonnull Classpath surefireClasspathUrls, */ public abstract boolean isClassPathConfig(); - protected Classpath getInprocClasspath() - { - return emptyClasspath(); - } + protected abstract Classpath getInprocClasspath(); public T toRealPath( Class type ) { @@ -95,8 +91,7 @@ public T toRealPath( Class type ) public ClassLoader createMergedClassLoader() throws SurefireExecutionException { - return join( getInprocClasspath(), getTestClasspath() ) - .createClassLoader( isChildDelegation(), isEnableAssertions(), "test" ); + return createMergedClassLoader( getInprocTestClasspath() ); } public Classpath getProviderClasspath() @@ -114,4 +109,15 @@ public boolean isChildDelegation() { 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/BooterConstants.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java index 3551910aa6..fc570f0fa0 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterConstants.java @@ -57,4 +57,5 @@ private BooterConstants() public static final String SHUTDOWN = "shutdown"; public static final String SYSTEM_EXIT_TIMEOUT = "systemExitTimeout"; public static final String PLUGIN_PID = "pluginPid"; + public static final String PROCESS_CHECKER = "processChecker"; } diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java index 75aad1f527..b0916795c6 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java @@ -61,9 +61,9 @@ public BooterDeserializer( InputStream inputStream ) /** * @return PID of Maven process where plugin is executed; or null if PID could not be determined. */ - public Long getPluginPid() + public String getPluginPid() { - return properties.getLongProperty( PLUGIN_PID ); + return properties.getProperty( PLUGIN_PID ); } public ProviderConfiguration deserialize() @@ -122,7 +122,7 @@ preferTestsFromInStream, fromStrings( cli ), failFastCount, shutdown, systemExitTimeout ); } - public StartupConfiguration getProviderConfiguration() + public StartupConfiguration getStartupConfiguration() { boolean useSystemClassLoader = properties.getBooleanProperty( USESYSTEMCLASSLOADER ); boolean useManifestOnlyJar = properties.getBooleanProperty( USEMANIFESTONLYJAR ); @@ -133,7 +133,10 @@ public StartupConfiguration getProviderConfiguration() ClasspathConfiguration classpathConfiguration = new ClasspathConfiguration( properties ); + String processChecker = properties.getProperty( PROCESS_CHECKER ); + ProcessCheckerType processCheckerType = ProcessCheckerType.toEnum( processChecker ); + return StartupConfiguration.inForkedVm( providerConfiguration, classpathConfiguration, - classLoaderConfiguration ); + classLoaderConfiguration, processCheckerType ); } } diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java index 580132a1d8..9da6d9b50d 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java @@ -19,11 +19,10 @@ * under the License. */ +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.surefire.providerapi.ProviderParameters; import org.apache.maven.surefire.providerapi.SurefireProvider; import org.apache.maven.surefire.report.LegacyPojoStackTraceWriter; -import org.apache.maven.surefire.report.StackTraceWriter; -import org.apache.maven.surefire.suite.RunResult; import org.apache.maven.surefire.testset.TestSetFailedException; import java.io.File; @@ -31,8 +30,9 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.io.PrintStream; import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; import java.lang.reflect.InvocationTargetException; import java.security.AccessControlException; import java.security.AccessController; @@ -47,13 +47,13 @@ import static java.lang.Thread.currentThread; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_BYE; -import static org.apache.maven.surefire.booter.ForkingRunListener.BOOTERCODE_ERROR; -import static org.apache.maven.surefire.booter.ForkingRunListener.encode; +import static org.apache.maven.surefire.booter.ProcessCheckerType.ALL; +import static org.apache.maven.surefire.booter.ProcessCheckerType.NATIVE; +import static org.apache.maven.surefire.booter.ProcessCheckerType.PING; import static org.apache.maven.surefire.booter.SystemPropertyManager.setSystemProperties; import static org.apache.maven.surefire.util.ReflectionUtils.instantiateOneArg; import static org.apache.maven.surefire.util.internal.DaemonThreadFactory.newDaemonThreadFactory; -import static org.apache.maven.surefire.util.internal.StringUtils.encodeStringForForkCommunication; +import static org.apache.maven.surefire.util.internal.StringUtils.NL; /** * The part of the booter that is unique to a forked vm. @@ -69,18 +69,20 @@ public final class ForkedBooter { private static final long DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS = 30L; private static final long PING_TIMEOUT_IN_SECONDS = 30L; - private static final long ONE_SECOND_IN_MILLIS = 1000L; + private static final long ONE_SECOND_IN_MILLIS = 1_000L; private static final String LAST_DITCH_SHUTDOWN_THREAD = "surefire-forkedjvm-last-ditch-daemon-shutdown-thread-"; private static final String PING_THREAD = "surefire-forkedjvm-ping-"; private final CommandReader commandReader = CommandReader.getReader(); - private final PrintStream originalOut = System.out; + private final ForkedChannelEncoder eventChannel = new ForkedChannelEncoder( System.out ); + private final Semaphore exitBarrier = new Semaphore( 0 ); private volatile long systemExitTimeoutInSeconds = DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS; private volatile PingScheduler pingScheduler; private ScheduledThreadPoolExecutor jvmTerminator; private ProviderConfiguration providerConfiguration; + private ForkingReporterFactory forkingReporterFactory; private StartupConfiguration startupConfiguration; private Object testSet; @@ -90,15 +92,25 @@ private void setupBooter( String tmpDir, String dumpFileName, String surefirePro { BooterDeserializer booterDeserializer = new BooterDeserializer( createSurefirePropertiesIfFileExists( tmpDir, surefirePropsFileName ) ); - // todo: print PID in debug console logger in version 2.21.2 - pingScheduler = isDebugging() ? null : listenToShutdownCommands( booterDeserializer.getPluginPid() ); setSystemProperties( new File( tmpDir, effectiveSystemPropertiesFileName ) ); providerConfiguration = booterDeserializer.deserialize(); DumpErrorSingleton.getSingleton() .init( providerConfiguration.getReporterConfiguration().getReportsDirectory(), dumpFileName ); - startupConfiguration = booterDeserializer.getProviderConfiguration(); + if ( isDebugging() ) + { + DumpErrorSingleton.getSingleton() + .dumpText( "Found Maven process ID " + booterDeserializer.getPluginPid() ); + } + + startupConfiguration = booterDeserializer.getStartupConfiguration(); + + forkingReporterFactory = createForkingReporterFactory(); + + ConsoleLogger logger = (ConsoleLogger) forkingReporterFactory.createReporter(); + pingScheduler = isDebugging() ? null : listenToShutdownCommands( booterDeserializer.getPluginPid(), logger ); + systemExitTimeoutInSeconds = providerConfiguration.systemExitTimeout( DEFAULT_SYSTEM_EXIT_TIMEOUT_IN_SECONDS ); AbstractPathConfiguration classpathConfiguration = startupConfiguration.getClasspathConfiguration(); @@ -125,24 +137,21 @@ private void execute() { runSuitesInProcess(); } - catch ( InvocationTargetException t ) + catch ( InvocationTargetException e ) { + Throwable t = e.getTargetException(); DumpErrorSingleton.getSingleton().dumpException( t ); - StackTraceWriter stackTraceWriter = - new LegacyPojoStackTraceWriter( "test subsystem", "no method", t.getTargetException() ); - StringBuilder stringBuilder = new StringBuilder(); - encode( stringBuilder, stackTraceWriter, false ); - encodeAndWriteToOutput( ( (char) BOOTERCODE_ERROR ) + ",0," + stringBuilder + "\n" ); + eventChannel.consoleErrorLog( new LegacyPojoStackTraceWriter( "test subsystem", "no method", t ), false ); } catch ( Throwable t ) { DumpErrorSingleton.getSingleton().dumpException( t ); - StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter( "test subsystem", "no method", t ); - StringBuilder stringBuilder = new StringBuilder(); - encode( stringBuilder, stackTraceWriter, false ); - encodeAndWriteToOutput( ( (char) BOOTERCODE_ERROR ) + ",0," + stringBuilder + "\n" ); + eventChannel.consoleErrorLog( new LegacyPojoStackTraceWriter( "test subsystem", "no method", t ), false ); + } + finally + { + acknowledgedExit(); } - acknowledgedExit(); } private Object createTestSet( TypeEncodedValue forkedTestSet, boolean readTestsFromCommandReader, ClassLoader cl ) @@ -153,7 +162,7 @@ private Object createTestSet( TypeEncodedValue forkedTestSet, boolean readTestsF } else if ( readTestsFromCommandReader ) { - return new LazyTestsToRun( originalOut ); + return new LazyTestsToRun( eventChannel ); } return null; } @@ -182,21 +191,31 @@ public Object run() } } - private PingScheduler listenToShutdownCommands( Long ppid ) + private PingScheduler listenToShutdownCommands( String ppid, ConsoleLogger logger ) { - commandReader.addShutdownListener( createExitHandler() ); + PpidChecker ppidChecker = ppid == null ? null : new PpidChecker( ppid ); + commandReader.addShutdownListener( createExitHandler( ppidChecker ) ); AtomicBoolean pingDone = new AtomicBoolean( true ); commandReader.addNoopListener( createPingHandler( pingDone ) ); + PingScheduler pingMechanisms = new PingScheduler( createPingScheduler(), ppidChecker ); + if ( ppidChecker != null ) + { + logger.debug( ppidChecker.toString() ); + } + + ProcessCheckerType checkerType = startupConfiguration.getProcessChecker(); - PingScheduler pingMechanisms = new PingScheduler( createPingScheduler(), - ppid == null ? null : new PpidChecker( ppid ) ); - if ( pingMechanisms.pluginProcessChecker != null ) + if ( ( checkerType == ALL || checkerType == NATIVE ) && pingMechanisms.pluginProcessChecker != null ) { Runnable checkerJob = processCheckerJob( pingMechanisms ); pingMechanisms.pingScheduler.scheduleWithFixedDelay( checkerJob, 0L, 1L, SECONDS ); } - Runnable pingJob = createPingJob( pingDone, pingMechanisms.pluginProcessChecker ); - pingMechanisms.pingScheduler.scheduleAtFixedRate( pingJob, 0L, PING_TIMEOUT_IN_SECONDS, SECONDS ); + + if ( checkerType == ALL || checkerType == PING ) + { + Runnable pingJob = createPingJob( pingDone, pingMechanisms.pluginProcessChecker ); + pingMechanisms.pingScheduler.scheduleWithFixedDelay( pingJob, 0L, PING_TIMEOUT_IN_SECONDS, SECONDS ); + } return pingMechanisms; } @@ -215,7 +234,11 @@ public void run() && !pingMechanism.pingScheduler.isShutdown() ) { DumpErrorSingleton.getSingleton() - .dumpText( "Killing self fork JVM. Maven process died." ); + .dumpText( "Killing self fork JVM. Maven process died." + + NL + + "Thread dump before killing the process (" + getProcessName() + "):" + + NL + + generateThreadDump() ); kill(); } @@ -241,7 +264,7 @@ public void update( Command command ) }; } - private CommandListener createExitHandler() + private CommandListener createExitHandler( final PpidChecker ppidChecker ) { return new CommandListener() { @@ -251,18 +274,36 @@ public void update( Command command ) Shutdown shutdown = command.toShutdownData(); if ( shutdown.isKill() ) { + ppidChecker.stop(); DumpErrorSingleton.getSingleton() - .dumpText( "Killing self fork JVM. Received SHUTDOWN command from Maven shutdown hook." ); + .dumpText( "Killing self fork JVM. Received SHUTDOWN command from Maven shutdown hook." + + NL + + "Thread dump before killing the process (" + getProcessName() + "):" + + NL + + generateThreadDump() ); kill(); } else if ( shutdown.isExit() ) { + ppidChecker.stop(); cancelPingScheduler(); DumpErrorSingleton.getSingleton() - .dumpText( "Exiting self fork JVM. Received SHUTDOWN command from Maven shutdown hook." ); - exit( 1 ); + .dumpText( "Exiting self fork JVM. Received SHUTDOWN command from Maven shutdown hook." + + NL + + "Thread dump before exiting the process (" + getProcessName() + "):" + + NL + + generateThreadDump() ); + exitBarrier.release(); + exit1(); + } + else + { + // else refers to shutdown=testset, but not used now, keeping reader open + DumpErrorSingleton.getSingleton() + .dumpText( "Thread dump for process (" + getProcessName() + "):" + + NL + + generateThreadDump() ); } - // else refers to shutdown=testset, but not used now, keeping reader open } }; } @@ -280,7 +321,11 @@ public void run() if ( !hasPing ) { DumpErrorSingleton.getSingleton() - .dumpText( "Killing self fork JVM. PING timeout elapsed." ); + .dumpText( "Killing self fork JVM. PING timeout elapsed." + + NL + + "Thread dump before killing the process (" + getProcessName() + "):" + + NL + + generateThreadDump() ); kill(); } @@ -289,17 +334,6 @@ public void run() }; } - private void encodeAndWriteToOutput( String string ) - { - byte[] encodeBytes = encodeStringForForkCommunication( string ); - //noinspection SynchronizationOnLocalVariableOrMethodParameter - synchronized ( originalOut ) - { - originalOut.write( encodeBytes, 0, encodeBytes.length ); - originalOut.flush(); - } - } - private void kill() { kill( 1 ); @@ -311,44 +345,42 @@ private void kill( int returnCode ) Runtime.getRuntime().halt( returnCode ); } - private void exit( int returnCode ) + private void exit1() { - launchLastDitchDaemonShutdownThread( returnCode ); - System.exit( returnCode ); + launchLastDitchDaemonShutdownThread( 1 ); + System.exit( 1 ); } private void acknowledgedExit() { - final Semaphore barrier = new Semaphore( 0 ); commandReader.addByeAckListener( new CommandListener() { @Override public void update( Command command ) { - barrier.release(); + exitBarrier.release(); } } ); - encodeAndWriteToOutput( ( (char) BOOTERCODE_BYE ) + ",0,BYE!\n" ); + eventChannel.bye(); launchLastDitchDaemonShutdownThread( 0 ); long timeoutMillis = max( systemExitTimeoutInSeconds * ONE_SECOND_IN_MILLIS, ONE_SECOND_IN_MILLIS ); - acquireOnePermit( barrier, timeoutMillis ); + acquireOnePermit( exitBarrier, timeoutMillis ); cancelPingScheduler(); commandReader.stop(); System.exit( 0 ); } - private RunResult runSuitesInProcess() - throws SurefireExecutionException, TestSetFailedException, InvocationTargetException + private void runSuitesInProcess() + throws TestSetFailedException, InvocationTargetException { - ForkingReporterFactory factory = createForkingReporterFactory(); - return invokeProviderInSameClassLoader( factory ); + createProviderInCurrentClassloader( forkingReporterFactory ).invoke( testSet ); } private ForkingReporterFactory createForkingReporterFactory() { final boolean trimStackTrace = providerConfiguration.getReporterConfiguration().isTrimStackTrace(); - return new ForkingReporterFactory( trimStackTrace, originalOut ); + return new ForkingReporterFactory( trimStackTrace, eventChannel ); } private synchronized ScheduledThreadPoolExecutor getJvmTerminator() @@ -366,29 +398,33 @@ private synchronized ScheduledThreadPoolExecutor getJvmTerminator() @SuppressWarnings( "checkstyle:emptyblock" ) private void launchLastDitchDaemonShutdownThread( final int returnCode ) { - getJvmTerminator().schedule( new Runnable() - { - @Override - public void run() - { - kill( returnCode ); - } - }, systemExitTimeoutInSeconds, SECONDS + getJvmTerminator() + .schedule( new Runnable() + { + @Override + public void run() + { + DumpErrorSingleton.getSingleton() + .dumpText( "Thread dump for process (" + + getProcessName() + + ") after " + + systemExitTimeoutInSeconds + + " seconds shutdown timeout:" + + NL + + generateThreadDump() ); + + kill( returnCode ); + } + }, systemExitTimeoutInSeconds, SECONDS ); } - private RunResult invokeProviderInSameClassLoader( ForkingReporterFactory factory ) - throws TestSetFailedException, InvocationTargetException - { - return createProviderInCurrentClassloader( factory ) - .invoke( testSet ); - } - private SurefireProvider createProviderInCurrentClassloader( ForkingReporterFactory reporterManagerFactory ) { BaseProviderFactory bpf = new BaseProviderFactory( reporterManagerFactory, true ); bpf.setTestRequest( providerConfiguration.getTestSuiteDefinition() ); bpf.setReporterConfiguration( providerConfiguration.getReporterConfiguration() ); + bpf.setForkedChannelEncoder( eventChannel ); ClassLoader classLoader = currentThread().getContextClassLoader(); bpf.setClassLoaders( classLoader ); bpf.setTestArtifactInfo( providerConfiguration.getTestArtifact() ); @@ -409,9 +445,20 @@ private SurefireProvider createProviderInCurrentClassloader( ForkingReporterFact * * @param args Commandline arguments */ - public static void main( String... args ) + public static void main( String[] args ) { ForkedBooter booter = new ForkedBooter(); + run( booter, args ); + } + + /** + * created for testing purposes. + * + * @param booter booter in JVM + * @param args arguments passed to JVM + */ + private static void run( ForkedBooter booter, String[] args ) + { try { booter.setupBooter( args[0], args[1], args[2], args.length > 3 ? args[3] : null ); @@ -422,7 +469,7 @@ public static void main( String... args ) DumpErrorSingleton.getSingleton().dumpException( t ); t.printStackTrace(); booter.cancelPingScheduler(); - booter.exit( 1 ); + booter.exit1(); } } @@ -431,15 +478,15 @@ private static boolean canUseNewPingMechanism( PpidChecker pluginProcessChecker return pluginProcessChecker != null && pluginProcessChecker.canUse(); } - private static boolean acquireOnePermit( Semaphore barrier, long timeoutMillis ) + private static void acquireOnePermit( Semaphore barrier, long timeoutMillis ) { try { - return barrier.tryAcquire( timeoutMillis, MILLISECONDS ); + barrier.tryAcquire( timeoutMillis, MILLISECONDS ); } catch ( InterruptedException e ) { - return true; + // cancel schedulers, stop the command reader and exit 0 } } @@ -490,10 +537,35 @@ void shutdown() pluginProcessChecker.destroyActiveCommands(); } } + } - boolean isShutdown() + private static String generateThreadDump() + { + StringBuilder dump = new StringBuilder(); + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] threadInfos = threadMXBean.getThreadInfo( threadMXBean.getAllThreadIds(), 100 ); + for ( ThreadInfo threadInfo : threadInfos ) { - return pingScheduler.isShutdown(); + dump.append( '"' ); + dump.append( threadInfo.getThreadName() ); + dump.append( "\" " ); + Thread.State state = threadInfo.getThreadState(); + dump.append( "\n java.lang.Thread.State: " ); + dump.append( state ); + StackTraceElement[] stackTraceElements = threadInfo.getStackTrace(); + for ( StackTraceElement stackTraceElement : stackTraceElements ) + { + dump.append( "\n at " ); + dump.append( stackTraceElement ); + } + dump.append( "\n\n" ); } + return dump.toString(); + } + + private static String getProcessName() + { + return ManagementFactory.getRuntimeMXBean() + .getName(); } } diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/LazyTestsToRun.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/LazyTestsToRun.java index 3237d077fa..9d0b2e080c 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/LazyTestsToRun.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/LazyTestsToRun.java @@ -19,7 +19,6 @@ * under the License. */ -import java.io.PrintStream; import java.util.Collections; import java.util.Iterator; @@ -44,24 +43,24 @@ final class LazyTestsToRun extends TestsToRun { - private final PrintStream originalOutStream; + private final ForkedChannelEncoder eventChannel; /** * C'tor * - * @param originalOutStream the output stream to use when requesting new new tests + * @param eventChannel the output stream to use when requesting new new tests */ - LazyTestsToRun( PrintStream originalOutStream ) + LazyTestsToRun( ForkedChannelEncoder eventChannel ) { super( Collections.>emptySet() ); - this.originalOutStream = originalOutStream; + this.eventChannel = eventChannel; } private final class BlockingIterator implements Iterator> { - private final Iterator it = getReader().getIterableClasses( originalOutStream ).iterator(); + private final Iterator it = getReader().getIterableClasses( eventChannel ).iterator(); @Override public boolean hasNext() diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspath.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspath.java index 9607b27644..7bf8bd0b0f 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspath.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ModularClasspath.java @@ -35,25 +35,25 @@ */ public final class ModularClasspath { - private final File moduleDescriptor; + private final String moduleNameFromDescriptor; private final List modulePath; private final Collection packages; private final File patchFile; - public ModularClasspath( @Nonnull File moduleDescriptor, @Nonnull List modulePath, + public ModularClasspath( @Nonnull String moduleNameFromDescriptor, @Nonnull List modulePath, @Nonnull Collection packages, @Nonnull File patchFile ) { - this.moduleDescriptor = moduleDescriptor; + this.moduleNameFromDescriptor = moduleNameFromDescriptor; this.modulePath = modulePath; this.packages = packages; this.patchFile = patchFile; } @Nonnull - public File getModuleDescriptor() + public String getModuleNameFromDescriptor() { - return moduleDescriptor; + return moduleNameFromDescriptor; } @Nonnull 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 823b445e32..e19bd4f3a4 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 @@ import javax.annotation.Nonnull; +import java.util.Collection; + +import static org.apache.maven.surefire.booter.Classpath.join; + /** * @author Tibor Digana (tibor17) * @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 ModularClasspath getModularClasspath() { return modularClasspath; } + + public ClassLoader createMergedClassLoader() + throws SurefireExecutionException + { + Collection modulePath = getModularClasspath().getModulePath(); + return createMergedClassLoader( join( getInprocTestClasspath(), new Classpath( modulePath ) ) ); + } + + @Override + protected Classpath getInprocClasspath() + { + return inprocClasspath; + } } diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java index d69c41939b..4360b023a9 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java @@ -19,6 +19,7 @@ * under the License. */ +import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; @@ -39,12 +40,14 @@ import static org.apache.commons.io.IOUtils.closeQuietly; import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.SystemUtils.IS_OS_HP_UX; +import static org.apache.commons.lang3.SystemUtils.IS_OS_LINUX; import static org.apache.commons.lang3.SystemUtils.IS_OS_UNIX; import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS; import static org.apache.maven.surefire.booter.ProcessInfo.unixProcessInfo; import static org.apache.maven.surefire.booter.ProcessInfo.windowsProcessInfo; import static org.apache.maven.surefire.booter.ProcessInfo.ERR_PROCESS_INFO; import static org.apache.maven.surefire.booter.ProcessInfo.INVALID_PROCESS_INFO; +import static org.apache.maven.surefire.util.internal.StringUtils.NL; /** * Recognizes PID of Plugin process and determines lifetime. @@ -65,6 +68,8 @@ final class PpidChecker private static final String RELATIVE_PATH_TO_WMIC = "System32\\Wbem"; private static final String SYSTEM_PATH_TO_WMIC = "%" + WINDOWS_SYSTEM_ROOT_ENV + "%\\" + RELATIVE_PATH_TO_WMIC + "\\"; + private static final String PS_ETIME_HEADER = "ELAPSED"; + private static final String PS_PID_HEADER = "PID"; private final Queue destroyableCommands = new ConcurrentLinkedQueue<>(); @@ -72,21 +77,26 @@ final class PpidChecker * The etime is in the form of [[dd-]hh:]mm:ss on Unix like systems. * See the workaround https://issues.apache.org/jira/browse/SUREFIRE-1451. */ - static final Pattern UNIX_CMD_OUT_PATTERN = compile( "^(((\\d+)-)?(\\d{1,2}):)?(\\d{1,2}):(\\d{1,2})$" ); + static final Pattern UNIX_CMD_OUT_PATTERN = compile( "^(((\\d+)-)?(\\d{1,2}):)?(\\d{1,2}):(\\d{1,2})\\s+(\\d+)$" ); - private final long ppid; + static final Pattern BUSYBOX_CMD_OUT_PATTERN = compile( "^(\\d+)[hH](\\d{1,2})\\s+(\\d+)$" ); + + private final String ppid; private volatile ProcessInfo parentProcessInfo; private volatile boolean stopped; - PpidChecker( long ppid ) + PpidChecker( @Nonnull String ppid ) { this.ppid = ppid; - //todo WARN logger (after new logger is finished) that (IS_OS_UNIX && canExecuteUnixPs()) is false } boolean canUse() { + if ( isStopped() ) + { + return false; + } final ProcessInfo ppi = parentProcessInfo; return ppi == null ? IS_OS_WINDOWS || IS_OS_UNIX && canExecuteUnixPs() : ppi.canUse(); } @@ -99,7 +109,6 @@ boolean canUse() * or this object has been {@link #destroyActiveCommands() destroyed} * @throws NullPointerException if extracted e-time is null */ - @SuppressWarnings( "unchecked" ) boolean isProcessAlive() { if ( !canUse() ) @@ -108,34 +117,26 @@ boolean isProcessAlive() } final ProcessInfo previousInfo = parentProcessInfo; - try + if ( IS_OS_WINDOWS ) { - if ( IS_OS_WINDOWS ) - { - parentProcessInfo = windows(); - checkProcessInfo(); - - // let's compare creation time, should be same unless killed or PID is reused by OS into another process - return previousInfo == null || parentProcessInfo.isTimeEqualTo( previousInfo ); - } - else if ( IS_OS_UNIX ) - { - parentProcessInfo = unix(); - checkProcessInfo(); + parentProcessInfo = windows(); + checkProcessInfo(); - // let's compare elapsed time, should be greater or equal if parent process is the same and still alive - return previousInfo == null || !parentProcessInfo.isTimeBefore( previousInfo ); - } - - throw new IllegalStateException( "unknown platform or you did not call canUse() before isProcessAlive()" ); + // let's compare creation time, should be same unless killed or PID is reused by OS into another process + return !parentProcessInfo.isInvalid() + && ( previousInfo == null || parentProcessInfo.isTimeEqualTo( previousInfo ) ); } - finally + else if ( IS_OS_UNIX ) { - if ( parentProcessInfo == null ) - { - parentProcessInfo = INVALID_PROCESS_INFO; - } + parentProcessInfo = unix(); + checkProcessInfo(); + + // let's compare elapsed time, should be greater or equal if parent process is the same and still alive + return !parentProcessInfo.isInvalid() + && ( previousInfo == null || !parentProcessInfo.isTimeBefore( previousInfo ) ); } + parentProcessInfo = ERR_PROCESS_INFO; + throw new IllegalStateException( "unknown platform or you did not call canUse() before isProcessAlive()" ); } private void checkProcessInfo() @@ -145,11 +146,6 @@ private void checkProcessInfo() throw new IllegalStateException( "error [STOPPED] to read process " + ppid ); } - if ( parentProcessInfo.isError() ) - { - throw new IllegalStateException( "error to read process " + ppid ); - } - if ( !parentProcessInfo.canUse() ) { throw new IllegalStateException( "Cannot use PPID " + ppid + " process information. " @@ -169,34 +165,47 @@ ProcessInfo unix() ProcessInfoConsumer reader = new ProcessInfoConsumer( Charset.defaultCharset().name() ) { @Override + @Nonnull ProcessInfo consumeLine( String line, ProcessInfo previousOutputLine ) { if ( previousOutputLine.isInvalid() ) { - Matcher matcher = UNIX_CMD_OUT_PATTERN.matcher( line ); - if ( matcher.matches() ) + if ( hasHeader ) { - long pidUptime = fromDays( matcher ) - + fromHours( matcher ) - + fromMinutes( matcher ) - + fromSeconds( matcher ); - return unixProcessInfo( ppid, pidUptime ); + Matcher matcher = UNIX_CMD_OUT_PATTERN.matcher( line ); + if ( matcher.matches() && ppid.equals( fromPID( matcher ) ) ) + { + long pidUptime = fromDays( matcher ) + + fromHours( matcher ) + + fromMinutes( matcher ) + + fromSeconds( matcher ); + return unixProcessInfo( ppid, pidUptime ); + } + matcher = BUSYBOX_CMD_OUT_PATTERN.matcher( line ); + if ( matcher.matches() && ppid.equals( fromBusyboxPID( matcher ) ) ) + { + long pidUptime = fromBusyboxHours( matcher ) + fromBusyboxMinutes( matcher ); + return unixProcessInfo( ppid, pidUptime ); + } + } + else + { + hasHeader = line.contains( PS_ETIME_HEADER ) && line.contains( PS_PID_HEADER ); } } return previousOutputLine; } }; - - return reader.execute( "/bin/sh", "-c", unixPathToPS() + " -o etime= -p " + ppid ); + String cmd = unixPathToPS() + " -o etime,pid " + ( IS_OS_LINUX ? "" : "-p " ) + ppid; + return reader.execute( "/bin/sh", "-c", cmd ); } ProcessInfo windows() { ProcessInfoConsumer reader = new ProcessInfoConsumer( "US-ASCII" ) { - private boolean hasHeader; - @Override + @Nonnull ProcessInfo consumeLine( String line, ProcessInfo previousProcessInfo ) throws Exception { if ( previousProcessInfo.isInvalid() && !line.isEmpty() ) @@ -256,12 +265,26 @@ static boolean canExecuteUnixPs() private static boolean canExecuteLocalUnixPs() { - return new File( "/usr/bin/ps" ).canExecute(); + try + { + return new File( "/usr/bin/ps" ).canExecute(); + } + catch ( SecurityException e ) + { + return false; + } } private static boolean canExecuteStandardUnixPs() { - return new File( "/bin/ps" ).canExecute(); + try + { + return new File( "/bin/ps" ).canExecute(); + } + catch ( SecurityException e ) + { + return false; + } } private static boolean hasWmicStandardSystemPath() @@ -294,6 +317,28 @@ static long fromSeconds( Matcher matcher ) return s == null ? 0L : parseLong( s ); } + static String fromPID( Matcher matcher ) + { + return matcher.group( 7 ); + } + + static long fromBusyboxHours( Matcher matcher ) + { + String s = matcher.group( 1 ); + return s == null ? 0L : HOURS.toSeconds( parseLong( s ) ); + } + + static long fromBusyboxMinutes( Matcher matcher ) + { + String s = matcher.group( 2 ); + return s == null ? 0L : MINUTES.toSeconds( parseLong( s ) ); + } + + static String fromBusyboxPID( Matcher matcher ) + { + return matcher.group( 3 ); + } + private static void checkValid( Scanner scanner ) throws IOException { @@ -318,6 +363,11 @@ private static SimpleDateFormat createWindowsCreationDateFormat() return formatter; } + public void stop() + { + stopped = true; + } + /** * Reads standard output from {@link Process}. *
@@ -329,12 +379,14 @@ private abstract class ProcessInfoConsumer { private final String charset; + boolean hasHeader; + ProcessInfoConsumer( String charset ) { this.charset = charset; } - abstract ProcessInfo consumeLine( String line, ProcessInfo previousProcessInfo ) throws Exception; + abstract @Nonnull ProcessInfo consumeLine( String line, ProcessInfo previousProcessInfo ) throws Exception; ProcessInfo execute( String... command ) { @@ -342,6 +394,7 @@ ProcessInfo execute( String... command ) processBuilder.redirectErrorStream( true ); Process process = null; ProcessInfo processInfo = INVALID_PROCESS_INFO; + StringBuilder out = new StringBuilder( 64 ); try { if ( IS_OS_HP_UX ) // force to run shell commands in UNIX Standard mode on HP-UX @@ -353,17 +406,30 @@ ProcessInfo execute( String... command ) Scanner scanner = new Scanner( process.getInputStream(), charset ); while ( scanner.hasNextLine() ) { - String line = scanner.nextLine().trim(); - processInfo = consumeLine( line, processInfo ); + String line = scanner.nextLine(); + out.append( line ).append( NL ); + processInfo = consumeLine( line.trim(), processInfo ); } checkValid( scanner ); int exitCode = process.waitFor(); - return exitCode == 0 ? processInfo : INVALID_PROCESS_INFO; + if ( exitCode != 0 || isStopped() ) + { + out.append( "<> <<" ).append( exitCode ).append( ">>" ).append( NL ); + DumpErrorSingleton.getSingleton() + .dumpText( out.toString() ); + } + return isStopped() ? ERR_PROCESS_INFO : exitCode == 0 ? processInfo : INVALID_PROCESS_INFO; } catch ( Exception e ) { - DumpErrorSingleton.getSingleton() - .dumpException( e ); + if ( !( e instanceof InterruptedException ) && !( e.getCause() instanceof InterruptedException ) ) + { + DumpErrorSingleton.getSingleton() + .dumpText( out.toString() ); + + DumpErrorSingleton.getSingleton() + .dumpException( e ); + } return ERR_PROCESS_INFO; } @@ -381,4 +447,25 @@ ProcessInfo execute( String... command ) } } + @Override + public String toString() + { + String args = "ppid=" + ppid + + ", stopped=" + stopped; + + ProcessInfo processInfo = parentProcessInfo; + if ( processInfo != null ) + { + args += ", invalid=" + processInfo.isInvalid() + + ", error=" + processInfo.isError(); + } + + if ( IS_OS_UNIX ) + { + args += ", canExecuteLocalUnixPs=" + canExecuteLocalUnixPs() + + ", canExecuteStandardUnixPs=" + canExecuteStandardUnixPs(); + } + + return "PpidChecker{" + args + '}'; + } } diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessCheckerType.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessCheckerType.java new file mode 100644 index 0000000000..547e33095c --- /dev/null +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessCheckerType.java @@ -0,0 +1,81 @@ +package org.apache.maven.surefire.booter; + +/* + * 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 static org.apache.maven.surefire.util.internal.StringUtils.isBlank; + +/** + * + */ +public enum ProcessCheckerType +{ + PING( "ping" ), + NATIVE( "native" ), + ALL( "all" ); + + private final String type; + + ProcessCheckerType( String type ) + { + this.type = type; + } + + /** + * Converts string (ping, native, all) to {@link ProcessCheckerType}. + * + * @param type ping, native, all + * @return {@link ProcessCheckerType} + */ + public static ProcessCheckerType toEnum( String type ) + { + if ( isBlank( type ) ) + { + return null; + } + + for ( ProcessCheckerType e : values() ) + { + if ( e.type.equals( type ) ) + { + return e; + } + } + + throw new IllegalArgumentException( "unknown process checker" ); + } + + public String getType() + { + return type; + } + + public static boolean isValid( String type ) + { + try + { + toEnum( type ); + return true; + } + catch ( IllegalArgumentException e ) + { + return false; + } + } +} diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessInfo.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessInfo.java index a73c33f753..c7e22dee22 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessInfo.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessInfo.java @@ -19,6 +19,8 @@ * under the License. */ +import javax.annotation.Nonnull; + /** * Immutable object which encapsulates PID and elapsed time (Unix) or start time (Windows). *
@@ -40,20 +42,20 @@ final class ProcessInfo *
*
/bin/ps -o etime= -p 123
*/ - static ProcessInfo unixProcessInfo( long pid, long etime ) + static @Nonnull ProcessInfo unixProcessInfo( String pid, long etime ) { return new ProcessInfo( pid, etime ); } - static ProcessInfo windowsProcessInfo( long pid, long startTimestamp ) + static @Nonnull ProcessInfo windowsProcessInfo( String pid, long startTimestamp ) { return new ProcessInfo( pid, startTimestamp ); } - private final Long pid; + private final String pid; private final Comparable time; - private ProcessInfo( Long pid, Comparable time ) + private ProcessInfo( String pid, Comparable time ) { this.pid = pid; this.time = time; @@ -61,7 +63,7 @@ private ProcessInfo( Long pid, Comparable time ) boolean canUse() { - return !isInvalid() && !isError(); + return !isError(); } boolean isInvalid() @@ -74,7 +76,7 @@ boolean isError() return this == ERR_PROCESS_INFO; } - long getPID() + String getPID() { checkValid(); return pid; @@ -91,7 +93,7 @@ boolean isTimeEqualTo( ProcessInfo that ) { checkValid(); that.checkValid(); - return this.time.compareTo( that.time ) == 0; + return time.compareTo( that.time ) == 0; } @SuppressWarnings( "unchecked" ) @@ -99,7 +101,7 @@ boolean isTimeBefore( ProcessInfo that ) { checkValid(); that.checkValid(); - return this.time.compareTo( that.time ) < 0; + return time.compareTo( that.time ) < 0; } private void checkValid() diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java index 870f81d37c..0bbe988fae 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/StartupConfiguration.java @@ -35,17 +35,19 @@ public class StartupConfiguration private final ClassLoaderConfiguration classLoaderConfiguration; private final boolean isForkRequested; private final boolean isInForkedVm; + private final ProcessCheckerType processChecker; public StartupConfiguration( @Nonnull String providerClassName, @Nonnull AbstractPathConfiguration classpathConfiguration, @Nonnull ClassLoaderConfiguration classLoaderConfiguration, boolean isForkRequested, - boolean inForkedVm ) + boolean inForkedVm, ProcessCheckerType processChecker ) { this.classpathConfiguration = classpathConfiguration; this.classLoaderConfiguration = classLoaderConfiguration; this.isForkRequested = isForkRequested; this.providerClassName = providerClassName; isInForkedVm = inForkedVm; + this.processChecker = processChecker; } public boolean isProviderMainClass() @@ -55,10 +57,11 @@ public boolean isProviderMainClass() public static StartupConfiguration inForkedVm( String providerClassName, ClasspathConfiguration classpathConfiguration, - ClassLoaderConfiguration classLoaderConfiguration ) + ClassLoaderConfiguration classLoaderConfiguration, + ProcessCheckerType processChecker ) { return new StartupConfiguration( providerClassName, classpathConfiguration, classLoaderConfiguration, true, - true ); + true, processChecker ); } public AbstractPathConfiguration getClasspathConfiguration() @@ -137,4 +140,9 @@ public void writeSurefireTestClasspathProperty() { getClasspathConfiguration().getTestClasspath().writeToSystemProperty( SUREFIRE_TEST_CLASSPATH ); } + + public ProcessCheckerType getProcessChecker() + { + return processChecker; + } } diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/TypeEncodedValue.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/TypeEncodedValue.java index 95365d8c03..06e93bec7c 100644 --- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/TypeEncodedValue.java +++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/TypeEncodedValue.java @@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.util.Objects; import java.util.Properties; import static java.nio.charset.StandardCharsets.ISO_8859_1; @@ -30,7 +31,7 @@ /** * @author Kristian Rosenvold */ -public class TypeEncodedValue +public final class TypeEncodedValue { private final String type; private final String value; @@ -41,7 +42,7 @@ public TypeEncodedValue( String type, String value ) this.value = value; } - public boolean isTypeClass() + private boolean isTypeClass() { return Class.class.getName().equals( type ); } @@ -111,7 +112,6 @@ public boolean equals( Object o ) TypeEncodedValue that = (TypeEncodedValue) o; return equalsType( that ) && equalsValue( that ); - } @Override @@ -122,13 +122,19 @@ public int hashCode() return result; } + @Override + public String toString() + { + return "TypeEncodedValue{" + "type='" + type + '\'' + ", value='" + value + '\'' + '}'; + } + private boolean equalsType( TypeEncodedValue that ) { - return type == null ? that.type == null : type.equals( that.type ); + return Objects.equals( type, that.type ); } private boolean equalsValue( TypeEncodedValue that ) { - return value == null ? that.value == null : value.equals( that.value ); + return Objects.equals( value, that.value ); } } diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/BooterDeserializerTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/BooterDeserializerTest.java new file mode 100644 index 0000000000..302f7add83 --- /dev/null +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/BooterDeserializerTest.java @@ -0,0 +1,57 @@ +package org.apache.maven.surefire.booter; + +/* + * 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.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringBufferInputStream; + +import static org.apache.maven.surefire.booter.BooterConstants.PROCESS_CHECKER; +import static org.apache.maven.surefire.booter.BooterConstants.PROVIDER_CONFIGURATION; +import static org.apache.maven.surefire.booter.BooterConstants.USESYSTEMCLASSLOADER; +import static org.apache.maven.surefire.booter.ProcessCheckerType.ALL; +import static org.fest.assertions.Assertions.assertThat; + +/** + * + */ +public class BooterDeserializerTest +{ + @Test + public void testStartupConfiguration() throws IOException + { + InputStream is = new StringBufferInputStream( PROCESS_CHECKER + "=all\n" + + USESYSTEMCLASSLOADER + "=true\n" + + PROVIDER_CONFIGURATION + "=abc.MyProvider" ); + + BooterDeserializer deserializer = new BooterDeserializer( is ); + + assertThat( deserializer.getStartupConfiguration().getProcessChecker() ) + .isEqualTo( ALL ); + + assertThat( deserializer.getStartupConfiguration().useSystemClassLoader() ) + .isTrue(); + + assertThat( deserializer.getStartupConfiguration().getProviderClassName() ) + .isEqualTo( "abc.MyProvider" ); + } +} diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ClasspathTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ClasspathTest.java index cb0679e4cb..874010fcdf 100644 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ClasspathTest.java +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ClasspathTest.java @@ -47,7 +47,9 @@ public void testShouldWriteEmptyPropertyForEmptyClasspath() public void testShouldWriteSeparatedElementsAsSystemProperty() { - Classpath classpath = Classpath.emptyClasspath().addClassPathElementUrl( DUMMY_URL_1 ).addClassPathElementUrl( DUMMY_URL_2 ); + Classpath classpath = Classpath.emptyClasspath() + .addClassPathElementUrl( DUMMY_URL_1 ) + .addClassPathElementUrl( DUMMY_URL_2 ); classpath.writeToSystemProperty( DUMMY_PROPERTY_NAME ); assertEquals( DUMMY_URL_1 + File.pathSeparatorChar + DUMMY_URL_2 + File.pathSeparatorChar, System.getProperty( DUMMY_PROPERTY_NAME ) ); @@ -55,8 +57,9 @@ public void testShouldWriteSeparatedElementsAsSystemProperty() public void testShouldAddNoDuplicateElements() { - Classpath classpath = - emptyClasspath().addClassPathElementUrl( DUMMY_URL_1 ).addClassPathElementUrl( DUMMY_URL_1 ); + Classpath classpath = emptyClasspath() + .addClassPathElementUrl( DUMMY_URL_1 ) + .addClassPathElementUrl( DUMMY_URL_1 ); assertClasspathConsistsOfElements( classpath, new String[]{ DUMMY_URL_1 } ); } @@ -69,7 +72,8 @@ public void testShouldJoinTwoNullClasspaths() public void testShouldHaveAllElementsAfterJoiningTwoDifferentClasspaths() { Classpath firstClasspath = Classpath.emptyClasspath(); - Classpath secondClasspath = firstClasspath.addClassPathElementUrl( DUMMY_URL_1 ).addClassPathElementUrl( DUMMY_URL_2 ); + Classpath secondClasspath = firstClasspath.addClassPathElementUrl( DUMMY_URL_1 ) + .addClassPathElementUrl( DUMMY_URL_2 ); Classpath joinedClasspath = Classpath.join( firstClasspath, secondClasspath ); assertClasspathConsistsOfElements( joinedClasspath, new String[]{ DUMMY_URL_1, DUMMY_URL_2 } ); } diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterMockTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterMockTest.java new file mode 100644 index 0000000000..e65beb1386 --- /dev/null +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterMockTest.java @@ -0,0 +1,134 @@ +package org.apache.maven.surefire.booter; + +/* + * 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.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.times; +import static org.powermock.api.mockito.PowerMockito.doCallRealMethod; +import static org.powermock.api.mockito.PowerMockito.doThrow; +import static org.powermock.api.mockito.PowerMockito.verifyNoMoreInteractions; +import static org.powermock.api.mockito.PowerMockito.verifyPrivate; +import static org.powermock.api.mockito.PowerMockito.when; +import static org.powermock.reflect.Whitebox.invokeMethod; + +/** + * PowerMock tests for {@link ForkedBooter}. + */ +@RunWith( PowerMockRunner.class ) +@PrepareForTest( { PpidChecker.class, ForkedBooter.class } ) +public class ForkedBooterMockTest +{ + @Mock + private PpidChecker pluginProcessChecker; + + @Mock + private ForkedBooter booter; + + @Test + public void shouldCheckNewPingMechanism() throws Exception + { + boolean canUse = invokeMethod( ForkedBooter.class, "canUseNewPingMechanism", (PpidChecker) null ); + assertThat( canUse ).isFalse(); + + when( pluginProcessChecker.canUse() ).thenReturn( false ); + canUse = invokeMethod( ForkedBooter.class, "canUseNewPingMechanism", pluginProcessChecker ); + assertThat( canUse ).isFalse(); + + when( pluginProcessChecker.canUse() ).thenReturn( true ); + canUse = invokeMethod( ForkedBooter.class, "canUseNewPingMechanism", pluginProcessChecker ); + assertThat( canUse ).isTrue(); + } + + @Test + public void testMain() throws Exception + { + PowerMockito.mockStatic( ForkedBooter.class ); + + ArgumentCaptor capturedArgs = ArgumentCaptor.forClass( String[].class ); + ArgumentCaptor capturedBooter = ArgumentCaptor.forClass( ForkedBooter.class ); + doCallRealMethod() + .when( ForkedBooter.class, "run", capturedBooter.capture(), capturedArgs.capture() ); + + String[] args = new String[]{ "/", "dump", "surefire.properties", "surefire-effective.properties" }; + invokeMethod( ForkedBooter.class, "run", booter, args ); + + assertThat( capturedBooter.getAllValues() ) + .hasSize( 1 ) + .contains( booter ); + + assertThat( capturedArgs.getAllValues() ) + .hasSize( 1 ); + assertThat( capturedArgs.getAllValues().get( 0 )[0] ) + .isEqualTo( "/" ); + assertThat( capturedArgs.getAllValues().get( 0 )[1] ) + .isEqualTo( "dump" ); + assertThat( capturedArgs.getAllValues().get( 0 )[2] ) + .isEqualTo( "surefire.properties" ); + assertThat( capturedArgs.getAllValues().get( 0 )[3] ) + .isEqualTo( "surefire-effective.properties" ); + + verifyPrivate( booter, times( 1 ) ) + .invoke( "setupBooter", same( args[0] ), same( args[1] ), same( args[2] ), same( args[3] ) ); + + verifyPrivate( booter, times( 1 ) ) + .invoke( "execute" ); + + verifyNoMoreInteractions( booter ); + } + + @Test + public void testMainWithError() throws Exception + { + PowerMockito.mockStatic( ForkedBooter.class ); + + doCallRealMethod() + .when( ForkedBooter.class, "run", any( ForkedBooter.class ), any( String[].class ) ); + + doThrow( new RuntimeException( "dummy exception" ) ) + .when( booter, "execute" ); + + String[] args = new String[]{ "/", "dump", "surefire.properties", "surefire-effective.properties" }; + invokeMethod( ForkedBooter.class, "run", booter, args ); + + verifyPrivate( booter, times( 1 ) ) + .invoke( "setupBooter", same( args[0] ), same( args[1] ), same( args[2] ), same( args[3] ) ); + + verifyPrivate( booter, times( 1 ) ) + .invoke( "execute" ); + + verifyPrivate( booter, times( 1 ) ) + .invoke( "cancelPingScheduler" ); + + verifyPrivate( booter, times( 1 ) ) + .invoke( "exit1" ); + + verifyNoMoreInteractions( booter ); + } +} diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterTest.java new file mode 100644 index 0000000000..434ca80c61 --- /dev/null +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/ForkedBooterTest.java @@ -0,0 +1,214 @@ +package org.apache.maven.surefire.booter; + +/* + * 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.commons.io.FileUtils; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.fest.assertions.Assertions.assertThat; +import static org.powermock.reflect.Whitebox.invokeMethod; + +/** + * Tests for {@link ForkedBooter}. + */ +@SuppressWarnings( "checkstyle:magicnumber" ) +public class ForkedBooterTest +{ + @Test + public void shouldGenerateThreadDump() throws Exception + { + Collection threadNames = new ArrayList<>(); + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + for ( ThreadInfo threadInfo : threadMXBean.getThreadInfo( threadMXBean.getAllThreadIds(), 100 ) ) + { + threadNames.add( threadInfo.getThreadName() ); + } + + String dump = invokeMethod( ForkedBooter.class, "generateThreadDump" ); + + for ( String threadName : threadNames ) + { + assertThat( dump ) + .contains( "\"" + threadName + "\"" ); + } + + assertThat( dump ) + .contains( " java.lang.Thread.State: " ) + .contains( " at " ); + } + + @Test + public void shouldFindCurrentProcessName() throws Exception + { + String process = ManagementFactory.getRuntimeMXBean().getName(); + String expected = invokeMethod( ForkedBooter.class, "getProcessName" ); + assertThat( process ).isEqualTo( expected ); + } + + @Test + public void shouldNotBeDebugMode() throws Exception + { + boolean expected = invokeMethod( ForkedBooter.class, "isDebugging" ); + assertThat( expected ).isFalse(); + } + + @Test + public void shouldReadSurefireProperties() throws Exception + { + File target = new File( System.getProperty( "user.dir", "target" ) ); + File tmpDir = new File( target, "ForkedBooterTest.1" ); + assertThat( tmpDir.mkdirs() ) + .isTrue(); + + try + { + try ( InputStream is = invokeMethod( ForkedBooter.class, "createSurefirePropertiesIfFileExists", + tmpDir.getCanonicalPath(), "surefire.properties" ) ) + { + assertThat( is ) + .isNull(); + } + + File props = new File( tmpDir, "surefire.properties" ); + + assertThat( props.createNewFile() ) + .isTrue(); + + FileUtils.write( props, "key=value", UTF_8 ); + + try ( InputStream is2 = invokeMethod( ForkedBooter.class, "createSurefirePropertiesIfFileExists", + tmpDir.getCanonicalPath(), "surefire.properties" ) ) + { + assertThat( is2 ) + .isNotNull() + .isInstanceOf( FileInputStream.class ); + + byte[] propsContent = new byte[20]; + int length = is2.read( propsContent ); + + assertThat( new String( propsContent, 0, length ) ) + .isEqualTo( "key=value" ); + } + } + finally + { + FileUtils.deleteDirectory( tmpDir ); + } + } + + @Test + public void shouldCreateScheduler() throws Exception + { + ScheduledExecutorService scheduler = null; + try + { + scheduler = invokeMethod( ForkedBooter.class, "createPingScheduler" ); + assertThat( scheduler ) + .isNotNull(); + } + finally + { + if ( scheduler != null ) + { + scheduler.shutdownNow(); + } + } + } + + @Test( timeout = 10_000 ) + public void testBarrier() throws Exception + { + Semaphore semaphore = new Semaphore( 2 ); + invokeMethod( ForkedBooter.class, "acquireOnePermit", semaphore, 30_000L ); + + assertThat( semaphore.availablePermits() ).isEqualTo( 1 ); + } + + @Test + public void testScheduler() throws Exception + { + ScheduledThreadPoolExecutor executor = invokeMethod( ForkedBooter.class, "createPingScheduler" ); + executor.shutdown(); + assertThat( executor.getCorePoolSize() ).isEqualTo( 1 ); + assertThat( executor.getKeepAliveTime( TimeUnit.SECONDS ) ).isEqualTo( 3L ); + assertThat( executor.getMaximumPoolSize() ).isEqualTo( 2 ); + } + + @Test + public void testIsDebug() throws Exception + { + boolean isDebug = invokeMethod( ForkedBooter.class, "isDebugging" ); + assertThat( isDebug ).isFalse(); + } + + @Test + public void testPropsNotExist() throws Exception + { + String target = System.getProperty( "user.dir" ); + String file = "not exists"; + InputStream is = invokeMethod( ForkedBooter.class, "createSurefirePropertiesIfFileExists", target, file ); + assertThat( is ).isNull(); + } + + @Test + public void testPropsExist() throws Exception + { + File props = File.createTempFile( "surefire", ".properties" ); + String target = props.getParent(); + String file = props.getName(); + FileUtils.write( props, "Hi", StandardCharsets.US_ASCII ); + try ( InputStream is = + invokeMethod( ForkedBooter.class, "createSurefirePropertiesIfFileExists", target, file ) ) + { + assertThat( is ).isNotNull(); + byte[] data = new byte[5]; + int bytes = is.read( data ); + assertThat( bytes ).isEqualTo( 2 ); + assertThat( data[0] ).isEqualTo( (byte) 'H' ); + assertThat( data[1] ).isEqualTo( (byte) 'i' ); + } + } + + @Test + public void testThreadDump() throws Exception + { + String threads = invokeMethod( ForkedBooter.class, "generateThreadDump" ); + assertThat( threads ) + .isNotNull(); + assertThat( threads ) + .contains( "\"main\"" ) + .contains( "java.lang.Thread.State: RUNNABLE" ); + } +} \ No newline at end of file diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/JUnit4SuiteTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/JUnit4SuiteTest.java index f073a8b003..75b2ef0e65 100644 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/JUnit4SuiteTest.java +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/JUnit4SuiteTest.java @@ -21,8 +21,8 @@ import junit.framework.JUnit4TestAdapter; import junit.framework.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; +import junit.framework.TestCase; +import junit.framework.TestSuite; /** * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite. @@ -30,19 +30,18 @@ * @author Tibor Digana (tibor17) * @since 2.19 */ -@Suite.SuiteClasses( { - ClasspathTest.class, - CommandReaderTest.class, - PropertiesWrapperTest.class, - SurefireReflectorTest.class, - PpidCheckerTest.class, - SystemUtilsTest.class -} ) -@RunWith( Suite.class ) -public class JUnit4SuiteTest +public class JUnit4SuiteTest extends TestCase { public static Test suite() { - return new JUnit4TestAdapter( JUnit4SuiteTest.class ); + TestSuite suite = new TestSuite(); + suite.addTest( new JUnit4TestAdapter( PpidCheckerTest.class ) ); + suite.addTest( new JUnit4TestAdapter( SystemUtilsTest.class ) ); + suite.addTest( new JUnit4TestAdapter( ForkedBooterTest.class ) ); + suite.addTest( new JUnit4TestAdapter( ForkedBooterMockTest.class ) ); + suite.addTest( new JUnit4TestAdapter( BooterDeserializerTest.class ) ); + suite.addTestSuite( ClasspathTest.class ); + suite.addTestSuite( PropertiesWrapperTest.class ); + return suite; } } diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java index fac18e21fb..424eb5f815 100644 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java @@ -27,8 +27,11 @@ import java.lang.management.ManagementFactory; import java.util.regex.Matcher; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.commons.lang3.SystemUtils.IS_OS_UNIX; import static org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS; +import static org.apache.maven.surefire.booter.ProcessInfo.unixProcessInfo; +import static org.apache.maven.surefire.booter.ProcessInfo.windowsProcessInfo; import static org.fest.assertions.Assertions.assertThat; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; @@ -37,6 +40,7 @@ import static org.junit.Assume.assumeThat; import static org.junit.Assume.assumeTrue; import static org.powermock.reflect.Whitebox.invokeMethod; +import static org.powermock.reflect.Whitebox.setInternalState; /** * Testing {@link PpidChecker} on a platform. @@ -44,20 +48,28 @@ * @author Tibor Digana (tibor17) * @since 2.20.1 */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class PpidCheckerTest { @Rule public final ExpectedException exceptions = ExpectedException.none(); @Test - public void shouldHavePpidAsWindows() + public void canExecuteUnixPs() { - assumeTrue( IS_OS_WINDOWS ); + assumeTrue( IS_OS_UNIX ); + assertThat( PpidChecker.canExecuteUnixPs() ) + .as( "Surefire should be tested on real box OS, e.g. Ubuntu or FreeBSD." ) + .isTrue(); + } - long expectedPid = Long.parseLong( ManagementFactory.getRuntimeMXBean().getName().split( "@" )[0].trim() ); + @Test + public void shouldHavePidAtBegin() + { + String expectedPid = ManagementFactory.getRuntimeMXBean().getName().split( "@" )[0].trim(); PpidChecker checker = new PpidChecker( expectedPid ); - ProcessInfo processInfo = checker.windows(); + ProcessInfo processInfo = IS_OS_UNIX ? checker.unix() : checker.windows(); assertThat( processInfo ) .isNotNull(); @@ -76,18 +88,21 @@ public void shouldHavePpidAsWindows() } @Test - public void shouldHavePpidAsUnix() + public void shouldHavePid() throws Exception { - assumeTrue( IS_OS_UNIX ); + String expectedPid = ManagementFactory.getRuntimeMXBean().getName().split( "@" )[0].trim(); + System.out.println( "java version " + System.getProperty( "java.version" ) + " expectedPid=" + expectedPid ); - assertThat( PpidChecker.canExecuteUnixPs() ) - .as( "Surefire should be tested on real box OS, e.g. Ubuntu or FreeBSD." ) - .isTrue(); + PpidChecker checker = new PpidChecker( expectedPid ); + setInternalState( checker, "parentProcessInfo", + IS_OS_UNIX + ? unixProcessInfo( expectedPid, 0L ) + : windowsProcessInfo( expectedPid, windowsProcessStartTime( checker ) ) ); - long expectedPid = Long.parseLong( ManagementFactory.getRuntimeMXBean().getName().split( "@" )[0].trim() ); + // the etime in Unix is measured in seconds. So let's wait 1s at least. + SECONDS.sleep( 1L ); - PpidChecker checker = new PpidChecker( expectedPid ); - ProcessInfo processInfo = checker.unix(); + ProcessInfo processInfo = IS_OS_UNIX ? checker.unix() : checker.windows(); assertThat( processInfo ) .isNotNull(); @@ -103,72 +118,132 @@ public void shouldHavePpidAsUnix() assertThat( processInfo.getTime() ) .isNotNull(); + + assertThat( checker.toString() ) + .contains( "ppid=" + expectedPid ) + .contains( "stopped=false" ) + .contains( "invalid=false" ) + .contains( "error=false" ); + + checker.destroyActiveCommands(); + assertThat( checker.canUse() ) + .isFalse(); + assertThat( (boolean) invokeMethod( checker, "isStopped" ) ) + .isTrue(); } @Test - public void shouldNotFindSuchPID() + public void shouldBeStopped() { - long ppid = 1000000L; + PpidChecker checker = new PpidChecker( "0" ); + checker.stop(); + + assertThat( checker.canUse() ) + .isFalse(); + + exceptions.expect( IllegalStateException.class ); + exceptions.expectMessage( "irrelevant to call isProcessAlive()" ); + + checker.isProcessAlive(); + + fail( "this test should throw exception" ); + } - PpidChecker checker = new PpidChecker( ppid ); + @Test + public void shouldNotFindSuchPID() + { + PpidChecker checker = new PpidChecker( "1000000" ); + setInternalState( checker, "parentProcessInfo", ProcessInfo.ERR_PROCESS_INFO ); assertThat( checker.canUse() ) - .isTrue(); + .isFalse(); exceptions.expect( IllegalStateException.class ); - exceptions.expectMessage( "Cannot use PPID " + ppid + " process information. Going to use NOOP events." ); + exceptions.expectMessage( "irrelevant to call isProcessAlive()" ); checker.isProcessAlive(); fail( "this test should throw exception" ); } + @Test + public void shouldNotBeAlive() + { + PpidChecker checker = new PpidChecker( "1000000" ); + + assertThat( checker.canUse() ) + .isTrue(); + + assertThat( checker.isProcessAlive() ) + .isFalse(); + } + @Test public void shouldParseEtime() { - Matcher m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "38" ); + Matcher m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "38 1234567890" ); assertThat( m.matches() ) .isFalse(); - m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "05:38" ); + m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "05:38 1234567890" ); assertThat( m.matches() ) .isTrue(); assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 0L ); assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 0L ); assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L ); assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 38L ); + assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" ); - m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "00:05:38" ); + m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "00:05:38 1234567890" ); assertThat( m.matches() ) .isTrue(); assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 0L ); assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 0L ); assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L ); assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 38L ); + assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" ); - m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "01:05:38" ); + m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "01:05:38 1234567890" ); assertThat( m.matches() ) .isTrue(); assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 0L ); assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 3600L ); assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L ); assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 38L ); + assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" ); - m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "02-01:05:38" ); + m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "02-01:05:38 1234567890" ); assertThat( m.matches() ) .isTrue(); assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 2 * 24 * 3600L ); assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 3600L ); assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L ); assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 38L ); + assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" ); - m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "02-1:5:3" ); + m = PpidChecker.UNIX_CMD_OUT_PATTERN.matcher( "02-1:5:3 1234567890" ); assertThat( m.matches() ) .isTrue(); assertThat( PpidChecker.fromDays( m ) ).isEqualTo( 2 * 24 * 3600L ); assertThat( PpidChecker.fromHours( m ) ).isEqualTo( 3600L ); assertThat( PpidChecker.fromMinutes( m ) ).isEqualTo( 300L ); assertThat( PpidChecker.fromSeconds( m ) ).isEqualTo( 3L ); + assertThat( PpidChecker.fromPID( m ) ).isEqualTo( "1234567890" ); + } + + @Test + public void shouldParseBusyboxHoursEtime() + { + Matcher m = PpidChecker.BUSYBOX_CMD_OUT_PATTERN.matcher( "38 1234567890" ); + assertThat( m.matches() ) + .isFalse(); + + m = PpidChecker.BUSYBOX_CMD_OUT_PATTERN.matcher( "05h38 1234567890" ); + assertThat( m.matches() ) + .isTrue(); + assertThat( PpidChecker.fromBusyboxHours( m ) ).isEqualTo( 3600 * 5L ); + assertThat( PpidChecker.fromBusyboxMinutes( m ) ).isEqualTo( 60 * 38L ); + assertThat( PpidChecker.fromBusyboxPID( m ) ).isEqualTo( "1234567890" ); } @Test @@ -182,4 +257,78 @@ public void shouldHaveSystemPathToWmicOnWindows() throws Exception assertThat( (Boolean) invokeMethod( PpidChecker.class, "hasWmicStandardSystemPath" ) ).isTrue(); assertThat( new File( System.getenv( "SystemRoot" ), "System32\\Wbem\\wmic.exe" ) ).isFile(); } + + @Test + public void shouldBeTypeNull() + { + assertThat( ProcessCheckerType.toEnum( null ) ) + .isNull(); + + assertThat( ProcessCheckerType.toEnum( " " ) ) + .isNull(); + + assertThat( ProcessCheckerType.isValid( null ) ) + .isTrue(); + } + + @Test + public void shouldBeException() + { + exceptions.expect( IllegalArgumentException.class ); + exceptions.expectMessage( "unknown process checker" ); + + assertThat( ProcessCheckerType.toEnum( "anything else" ) ) + .isNull(); + } + + @Test + public void shouldNotBeValid() + { + assertThat( ProcessCheckerType.isValid( "anything" ) ) + .isFalse(); + } + + @Test + public void shouldBeTypePing() + { + assertThat( ProcessCheckerType.toEnum( "ping" ) ) + .isEqualTo( ProcessCheckerType.PING ); + + assertThat( ProcessCheckerType.isValid( "ping" ) ) + .isTrue(); + + assertThat( ProcessCheckerType.PING.getType() ) + .isEqualTo( "ping" ); + } + + @Test + public void shouldBeTypeNative() + { + assertThat( ProcessCheckerType.toEnum( "native" ) ) + .isEqualTo( ProcessCheckerType.NATIVE ); + + assertThat( ProcessCheckerType.isValid( "native" ) ) + .isTrue(); + + assertThat( ProcessCheckerType.NATIVE.getType() ) + .isEqualTo( "native" ); + } + + @Test + public void shouldBeTypeAll() + { + assertThat( ProcessCheckerType.toEnum( "all" ) ) + .isEqualTo( ProcessCheckerType.ALL ); + + assertThat( ProcessCheckerType.isValid( "all" ) ) + .isTrue(); + + assertThat( ProcessCheckerType.ALL.getType() ) + .isEqualTo( "all" ); + } + + private static long windowsProcessStartTime( PpidChecker checker ) + { + return (long) checker.windows().getTime(); + } } diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PropertiesWrapperTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PropertiesWrapperTest.java index 9cbad17ac1..06b08aa11b 100644 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PropertiesWrapperTest.java +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PropertiesWrapperTest.java @@ -19,7 +19,10 @@ * under the License. */ -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import junit.framework.TestCase; @@ -30,7 +33,6 @@ public class PropertiesWrapperTest extends TestCase { public void testAddList() - throws Exception { PropertiesWrapper propertiesWrapper = new PropertiesWrapper( new HashMap() ); List items = new ArrayList<>(); @@ -45,7 +47,6 @@ public void testAddList() assertEquals( "String5", test.get( 4 ) ); assertEquals( "String3", test.get( 2 ) ); assertEquals( "String2", test.get( 1 ) ); - } private static final String DUMMY_PREFIX = "dummyPrefix"; @@ -61,7 +62,6 @@ public void testAddList() private final Classpath classpathWithTwoElements = createClasspathWithTwoElements(); public void testReadFromProperties() - throws Exception { properties.put( DUMMY_PREFIX + "0", FIRST_ELEMENT ); properties.put( DUMMY_PREFIX + "1", SECOND_ELEMENT ); @@ -70,14 +70,12 @@ public void testReadFromProperties() } public void testReadFromPropertiesWithEmptyProperties() - throws Exception { Classpath recreatedClasspath = readClasspathFromProperties(); assertTrue( recreatedClasspath.getClassPath().isEmpty() ); } public void testWriteToProperties() - throws Exception { mapper.setClasspath( DUMMY_PREFIX, classpathWithTwoElements ); assertEquals( FIRST_ELEMENT, mapper.getProperty( DUMMY_PREFIX + "0" ) ); @@ -85,7 +83,6 @@ public void testWriteToProperties() } public void testRoundtrip() - throws Exception { mapper.setClasspath( DUMMY_PREFIX, classpathWithTwoElements ); Classpath recreatedClasspath = readClasspathFromProperties(); diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java deleted file mode 100644 index 0f5188c720..0000000000 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.apache.maven.surefire.booter; - -/* - * 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.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import org.apache.maven.surefire.report.ReporterConfiguration; -import org.apache.maven.surefire.testset.DirectoryScannerParameters; -import org.apache.maven.surefire.testset.RunOrderParameters; -import org.apache.maven.surefire.testset.TestArtifactInfo; -import org.apache.maven.surefire.testset.TestListResolver; -import org.apache.maven.surefire.testset.TestRequest; -import org.apache.maven.surefire.util.RunOrder; - -import junit.framework.TestCase; - -/** - * @author Kristian Rosenvold - */ -public class SurefireReflectorTest - extends TestCase -{ - public void testSetDirectoryScannerParameters() - throws Exception - { - SurefireReflector surefireReflector = getReflector(); - Object foo = getFoo(); - - DirectoryScannerParameters directoryScannerParameters = - new DirectoryScannerParameters( new File( "ABC" ), new ArrayList(), new ArrayList(), - new ArrayList(), false, "hourly" ); - surefireReflector.setDirectoryScannerParameters( foo, directoryScannerParameters ); - assertTrue( isCalled( foo ) ); - - } - - public void testRunOrderParameters() - throws Exception - { - SurefireReflector surefireReflector = getReflector(); - Object foo = getFoo(); - - RunOrderParameters runOrderParameters = new RunOrderParameters( RunOrder.DEFAULT, new File( "." ) ); - surefireReflector.setRunOrderParameters( foo, runOrderParameters ); - assertTrue( isCalled( foo ) ); - - } - - public void testTestSuiteDefinition() - throws Exception - { - SurefireReflector surefireReflector = getReflector(); - Object foo = getFoo(); - - TestRequest testSuiteDefinition = - new TestRequest( Arrays.asList( new File( "file1" ), new File( "file2" ) ), - new File( "TestSOurce" ), new TestListResolver( "aUserRequestedTest#aMethodRequested" ) ); - surefireReflector.setTestSuiteDefinition( foo, testSuiteDefinition ); - assertTrue( isCalled( foo ) ); - } - - public void testProviderProperties() - throws Exception - { - SurefireReflector surefireReflector = getReflector(); - Object foo = getFoo(); - - surefireReflector.setProviderProperties( foo, new HashMap() ); - assertTrue( isCalled( foo ) ); - } - - public void testReporterConfiguration() - throws Exception - { - SurefireReflector surefireReflector = getReflector(); - Object foo = getFoo(); - - ReporterConfiguration reporterConfiguration = getReporterConfiguration(); - surefireReflector.setReporterConfigurationAware( foo, reporterConfiguration ); - assertTrue( isCalled( foo ) ); - } - - private ReporterConfiguration getReporterConfiguration() - { - return new ReporterConfiguration( new File( "CDE" ), true ); - } - - public void testTestClassLoaderAware() - throws Exception - { - SurefireReflector surefireReflector = getReflector(); - Object foo = getFoo(); - - surefireReflector.setTestClassLoader( foo, getClass().getClassLoader() ); - assertTrue( isCalled( foo ) ); - } - - public void testArtifactInfoAware() - throws Exception - { - SurefireReflector surefireReflector = getReflector(); - Object foo = getFoo(); - - TestArtifactInfo testArtifactInfo = new TestArtifactInfo( "12.3", "test" ); - surefireReflector.setTestArtifactInfo( foo, testArtifactInfo ); - assertTrue( isCalled( foo ) ); - } - - private SurefireReflector getReflector() - { - return new SurefireReflector( this.getClass().getClassLoader() ); - } - - public Object getFoo() - { // Todo: Setup a different classloader so we can really test crossing - return new Foo(); - } - - - private Boolean isCalled( Object foo ) - { - final Method isCalled; - try - { - isCalled = foo.getClass().getMethod( "isCalled" ); - return (Boolean) isCalled.invoke( foo ); - } - catch ( ReflectiveOperationException e ) - { - throw new RuntimeException( e ); - } - } -} diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java index a957d06c27..34faff048a 100644 --- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java +++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SystemUtilsTest.java @@ -22,6 +22,7 @@ import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -53,9 +54,13 @@ * @author Tibor Digana (tibor17) * @since 2.20.1 */ +@SuppressWarnings( "checkstyle:magicnumber" ) @RunWith( Enclosed.class ) public class SystemUtilsTest { + /** + * + */ public static class PlainUnitTests { @@ -63,7 +68,8 @@ public static class PlainUnitTests public void shouldMatchJavaSpecVersion() throws Exception { BigDecimal actual = invokeMethod( SystemUtils.class, "getJavaSpecificationVersion" ); - BigDecimal expected = new BigDecimal( System.getProperty( "java.specification.version" ) ).stripTrailingZeros(); + BigDecimal expected = + new BigDecimal( System.getProperty( "java.specification.version" ) ).stripTrailingZeros(); assertThat( actual ).isEqualTo( expected ); assertThat( SystemUtils.JAVA_SPECIFICATION_VERSION ).isEqualTo( expected ); } @@ -293,8 +299,12 @@ public static ClassLoader getPlatformClassLoader() } + /** + * + */ @RunWith( PowerMockRunner.class ) @PrepareForTest( SystemUtils.class ) + @PowerMockIgnore( { "org.jacoco.agent.rt.*", "com.vladium.emma.rt.*" } ) public static class MockTest { diff --git a/surefire-extensions-api/pom.xml b/surefire-extensions-api/pom.xml new file mode 100644 index 0000000000..6dcf461b19 --- /dev/null +++ b/surefire-extensions-api/pom.xml @@ -0,0 +1,95 @@ + + + + + 4.0.0 + + + org.apache.maven.surefire + surefire + 3.0.0-M4 + + + surefire-extensions-api + Surefire Extensions API + + + + org.apache.maven.surefire + surefire-api + ${project.version} + provided + + + org.codehaus.plexus + plexus-component-annotations + provided + + + org.jacoco + org.jacoco.agent + runtime + test + + + + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-instrumentation + + + instrument + + + + restore-classes + + restore-instrumented-classes + + + + + + maven-surefire-plugin + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + + + ${jvm.args.tests} + + ${project.build.directory}/jacoco.exec + + + + + + + \ No newline at end of file diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ConsoleOutputReportEventListener.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ConsoleOutputReportEventListener.java new file mode 100644 index 0000000000..2b1e0909ec --- /dev/null +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ConsoleOutputReportEventListener.java @@ -0,0 +1,37 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.report.TestSetReportEntry; + +/** + * Extension listener for logger. + * The signature can be changed between major, minor versions or milestones. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public interface ConsoleOutputReportEventListener +{ + void testSetStarting( TestSetReportEntry report ); + void testSetCompleted( TestSetReportEntry report ); + void close(); + void writeTestOutput( String output, boolean newLine, boolean stdout ); +} diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ConsoleOutputReporter.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ConsoleOutputReporter.java new file mode 100644 index 0000000000..382eaf367d --- /dev/null +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/ConsoleOutputReporter.java @@ -0,0 +1,72 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.io.PrintStream; + +import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; + +/** + * Extension for logger. + * The signature can be changed between major, minor versions or milestones. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public abstract class ConsoleOutputReporter +{ + /** + * {@code false} by default + */ + private boolean disable; + + /** + * The content is encoded UTF-8 by default. + */ + private String encoding; + + public abstract ConsoleOutputReportEventListener createListener( File reportsDirectory, String reportNameSuffix, + Integer forkNumber ); + + public abstract ConsoleOutputReportEventListener createListener( PrintStream out, PrintStream err ); + + public abstract Object clone( ClassLoader target ); + + public boolean isDisable() + { + return disable; + } + + public void setDisable( boolean disable ) + { + this.disable = disable; + } + + public String getEncoding() + { + return isBlank( encoding ) ? "UTF-8" : encoding; + } + + public void setEncoding( String encoding ) + { + this.encoding = encoding; + } +} diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportEventListener.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportEventListener.java new file mode 100644 index 0000000000..31878023af --- /dev/null +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportEventListener.java @@ -0,0 +1,43 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.report.TestSetReportEntry; + +/** + * Creates a report upon handled event "testSetCompleted". + *
+ * Defaults to org.apache.maven.plugin.surefire.report.StatelessXmlReporter. + * + * author Tibor Digana (tibor17) + * @since 3.0.0-M4 + * @param report entry type, see WrappedReportEntry from module the maven-surefire-common + * @param test-set statistics, see TestSetStats from module the maven-surefire-common + */ +public interface StatelessReportEventListener +{ + /** + * The callback is called after the test class has been completed and the state of report is final. + * + * @param report WrappedReportEntry + * @param testSetStats TestSetStats + */ + void testSetCompleted( R report, S testSetStats ); +} diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportMojoConfiguration.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportMojoConfiguration.java new file mode 100644 index 0000000000..f176fce23b --- /dev/null +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReportMojoConfiguration.java @@ -0,0 +1,75 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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; + +/** + * Configuration passed to the constructor of default reporter + * org.apache.maven.plugin.surefire.report.StatelessXmlReporter. + * Signatures can be changed between major, minor versions or milestones. + */ +public class StatelessReportMojoConfiguration +{ + private final File reportsDirectory; + + private final String reportNameSuffix; + + private final boolean trimStackTrace; + + private final int rerunFailingTestsCount; + + private final String xsdSchemaLocation; + + public StatelessReportMojoConfiguration( File reportsDirectory, String reportNameSuffix, boolean trimStackTrace, + int rerunFailingTestsCount, String xsdSchemaLocation ) + { + this.reportsDirectory = reportsDirectory; + this.reportNameSuffix = reportNameSuffix; + this.trimStackTrace = trimStackTrace; + this.rerunFailingTestsCount = rerunFailingTestsCount; + this.xsdSchemaLocation = xsdSchemaLocation; + } + + public File getReportsDirectory() + { + return reportsDirectory; + } + + public String getReportNameSuffix() + { + return reportNameSuffix; + } + + public boolean isTrimStackTrace() + { + return trimStackTrace; + } + + public int getRerunFailingTestsCount() + { + return rerunFailingTestsCount; + } + + public String getXsdSchemaLocation() + { + return xsdSchemaLocation; + } +} diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReporter.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReporter.java new file mode 100644 index 0000000000..60cee595be --- /dev/null +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessReporter.java @@ -0,0 +1,87 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.report.TestSetReportEntry; + +import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; + +/** + * Extension for stateless reporter. + * Signatures can be changed between major, minor versions or milestones. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + * @param report entry type, see WrappedReportEntry from module the maven-surefire-common + * @param test-set statistics, see TestSetStats from module the maven-surefire-common + * @param mojo config, see DefaultStatelessReportMojoConfiguration from maven-surefire-common + */ +public abstract class StatelessReporter +{ + /** + * {@code false} by default + */ + //todo remove isDisableXmlReport() in AbstractSurefireMojo and use this param instead + private boolean disable; + + /** + * Version of reporter. It is version 3.0 used by default in XML reporter. + */ + private String version; + + /** + * Creates reporter. + * + * @return reporter object + */ + public abstract StatelessReportEventListener createListener( C configuration ); + + public abstract Object clone( ClassLoader target ); + + public boolean isDisable() + { + return disable; + } + + public void setDisable( boolean disable ) + { + this.disable = disable; + } + + public String getVersion() + { + return isBlank( version ) ? "3.0" : version; + } + + public void setVersion( String version ) + { + this.version = version; + } + + @Override + public String toString() + { + return getClass().getSimpleName() + + "{" + + "version=" + getVersion() + + ", disable=" + isDisable() + + '}'; + } +} diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoConsoleReportEventListener.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoConsoleReportEventListener.java new file mode 100644 index 0000000000..f01acff960 --- /dev/null +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoConsoleReportEventListener.java @@ -0,0 +1,53 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.surefire.report.TestSetReportEntry; + +import java.util.List; + +/** + * Extension listener for stateless console reporter of test-set. + * Signatures can be changed between major, minor versions or milestones. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + * @param report entry type, see WrappedReportEntry from module the maven-surefire-common + * @param test-set statistics, see TestSetStats from module the maven-surefire-common + */ +public abstract class StatelessTestsetInfoConsoleReportEventListener +{ + private final ConsoleLogger logger; + + public StatelessTestsetInfoConsoleReportEventListener( ConsoleLogger logger ) + { + this.logger = logger; + } + + public abstract void testSetStarting( TestSetReportEntry report ); + public abstract void testSetCompleted( R report, S testSetStats, List testResults ); + public abstract void reset(); + + public ConsoleLogger getConsoleLogger() + { + return logger; + } +} diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoFileReportEventListener.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoFileReportEventListener.java new file mode 100644 index 0000000000..91e460a843 --- /dev/null +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoFileReportEventListener.java @@ -0,0 +1,67 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.report.TestSetReportEntry; + +import java.io.File; +import java.nio.charset.Charset; +import java.util.List; + +/** + * Extension listener for stateless file reporter of test-set. + * Signatures can be changed between major, minor versions or milestones. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + * @param report entry type, see WrappedReportEntry from module the maven-surefire-common + * @param test-set statistics, see TestSetStats from module the maven-surefire-common + */ +public abstract class StatelessTestsetInfoFileReportEventListener +{ + private final File reportsDirectory; + private final String reportNameSuffix; + private final Charset encoding; + + public StatelessTestsetInfoFileReportEventListener( File reportsDirectory, String reportNameSuffix, + Charset encoding ) + { + this.reportsDirectory = reportsDirectory; + this.reportNameSuffix = reportNameSuffix; + this.encoding = encoding; + } + + public abstract void testSetCompleted( R report, S testSetStats, List testResults ); + + protected File getReportsDirectory() + { + return reportsDirectory; + } + + protected String getReportNameSuffix() + { + return reportNameSuffix; + } + + protected Charset getEncoding() + { + return encoding; + } +} diff --git a/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoReporter.java b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoReporter.java new file mode 100644 index 0000000000..ca10944182 --- /dev/null +++ b/surefire-extensions-api/src/main/java/org/apache/maven/surefire/extensions/StatelessTestsetInfoReporter.java @@ -0,0 +1,58 @@ +package org.apache.maven.surefire.extensions; + +/* + * 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.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.surefire.report.TestSetReportEntry; + +import java.io.File; +import java.nio.charset.Charset; + +/** + * Extension listener for stateless file and console reporter of test-set. + * Signatures can be changed between major, minor versions or milestones. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + * @param report entry type, see WrappedReportEntry from module the maven-surefire-common + * @param test-set statistics, see TestSetStats from module the maven-surefire-common + */ +public abstract class StatelessTestsetInfoReporter +{ + private boolean disable; + + public abstract StatelessTestsetInfoConsoleReportEventListener createListener( ConsoleLogger logger ); + + public abstract StatelessTestsetInfoFileReportEventListener createListener( File reportsDirectory, + String reportNameSuffix, + Charset encoding ); + + public abstract Object clone( ClassLoader target ); + + public boolean isDisable() + { + return disable; + } + + public void setDisable( boolean disable ) + { + this.disable = disable; + } +} diff --git a/surefire-grouper/pom.xml b/surefire-grouper/pom.xml index 8c12db863a..5e2368002c 100644 --- a/surefire-grouper/pom.xml +++ b/surefire-grouper/pom.xml @@ -24,7 +24,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 surefire-grouper @@ -32,10 +32,6 @@ Maven Surefire Test-Grouping Support Maven Surefire Test-Grouping Support - - 3.0 - - @@ -51,13 +47,31 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 diff --git a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/AndGroupMatcherTest.java b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/AndGroupMatcherTest.java index f81cfd38fa..d9c8baf8bd 100644 --- a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/AndGroupMatcherTest.java +++ b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/AndGroupMatcherTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.group.match; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,6 +21,9 @@ import junit.framework.TestCase; +/** + * + */ public class AndGroupMatcherTest extends TestCase { diff --git a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/InverseGroupMatcherTest.java b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/InverseGroupMatcherTest.java index 6be29c27dd..23ecc3591e 100644 --- a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/InverseGroupMatcherTest.java +++ b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/InverseGroupMatcherTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.group.match; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,6 +21,9 @@ import junit.framework.TestCase; +/** + * + */ public class InverseGroupMatcherTest extends TestCase { diff --git a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/OrGroupMatcherTest.java b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/OrGroupMatcherTest.java index 3c4160950d..48feb36292 100644 --- a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/OrGroupMatcherTest.java +++ b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/OrGroupMatcherTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.group.match; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,6 +21,9 @@ import junit.framework.TestCase; +/** + * + */ public class OrGroupMatcherTest extends TestCase { diff --git a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/SingleGroupMatcherTest.java b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/SingleGroupMatcherTest.java index 31d959f75b..b75011f920 100644 --- a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/SingleGroupMatcherTest.java +++ b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/match/SingleGroupMatcherTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.group.match; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,6 +21,9 @@ import junit.framework.TestCase; +/** + * + */ public class SingleGroupMatcherTest extends TestCase { diff --git a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/parse/GroupMatcherParserTest.java b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/parse/GroupMatcherParserTest.java index e92595a09d..070caa73c3 100644 --- a/surefire-grouper/src/test/java/org/apache/maven/surefire/group/parse/GroupMatcherParserTest.java +++ b/surefire-grouper/src/test/java/org/apache/maven/surefire/group/parse/GroupMatcherParserTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.group.parse; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -26,6 +27,9 @@ import junit.framework.TestCase; +/** + * + */ public class GroupMatcherParserTest extends TestCase { diff --git a/surefire-its/pom.xml b/surefire-its/pom.xml index 267ab27cff..8ef73b25fa 100644 --- a/surefire-its/pom.xml +++ b/surefire-its/pom.xml @@ -24,7 +24,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 surefire-its @@ -78,6 +78,11 @@ commons-lang3 test + + com.googlecode.junit-toolbox + junit-toolbox + test + @@ -146,7 +151,7 @@ org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 @@ -160,8 +165,9 @@
maven-failsafe-plugin - 3.0.0-M2 + 3.0.0-M3 + false ${jdk.home}/bin/java alphabetical 1 @@ -182,14 +188,17 @@ forked ${jdk.home} ${jacoco-it.agent} + + + 3 - false + true org.apache.maven.surefire surefire-junit47 - 3.0.0-M2 + 3.0.0-M3 @@ -201,13 +210,6 @@ - - maven-jar-plugin - - - true - - org.jacoco jacoco-maven-plugin diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractFailFastIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractFailFastIT.java index 3531c7cb98..507a08af7b 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractFailFastIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractFailFastIT.java @@ -19,12 +19,12 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.surefire.its.fixture.MavenLauncher; import org.apache.maven.surefire.its.fixture.OutputValidator; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import java.util.HashMap; import java.util.Map; @@ -37,29 +37,36 @@ * @author Tibor Digana (tibor17) * @since 2.19 */ -@RunWith( Parameterized.class ) +@RunWith( ParallelParameterized.class ) public abstract class AbstractFailFastIT extends SurefireJUnit4IntegrationTestCase { @Parameter( 0 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String description; @Parameter( 1 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String profile; @Parameter( 2 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public Map properties; @Parameter( 3 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public int total; @Parameter( 4 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public int failures; @Parameter( 5 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public int errors; @Parameter( 6 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public int skipped; protected abstract String withProvider(); diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractJigsawIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractJigsawIT.java index 67e835f4a2..c8fb2d56e8 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractJigsawIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractJigsawIT.java @@ -47,7 +47,7 @@ public abstract class AbstractJigsawIT protected abstract String getProjectDirectoryName(); - protected SurefireLauncher assumeJigsaw() throws IOException + protected SurefireLauncher assumeJava9() throws IOException { assumeTrue( "There's no JDK 9 provided.", isJavaVersion9AtLeast() || EXT_JDK_HOME != null && isExtJavaVerion9AtLeast() ); diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java index 01932facfd..6c458f501b 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java @@ -24,8 +24,13 @@ import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; -import static org.apache.maven.surefire.its.fixture.TestFramework.*; -import static org.apache.maven.surefire.its.fixture.Configuration.*; +import static org.apache.maven.surefire.its.fixture.TestFramework.JUNIT47; +import static org.apache.maven.surefire.its.fixture.TestFramework.TestNG; +import static org.apache.maven.surefire.its.fixture.Configuration.INCLUDES; +import static org.apache.maven.surefire.its.fixture.Configuration.INCLUDES_EXCLUDES; +import static org.apache.maven.surefire.its.fixture.Configuration.INCLUDES_EXCLUDES_FILE; +import static org.apache.maven.surefire.its.fixture.Configuration.INCLUDES_FILE; +import static org.apache.maven.surefire.its.fixture.Configuration.TEST; import static org.hamcrest.core.AnyOf.anyOf; import static org.hamcrest.core.Is.is; import static org.junit.Assume.assumeThat; @@ -48,7 +53,8 @@ protected SurefireLauncher prepare( String tests ) { SurefireLauncher launcher = unpack().addGoal( "-P " + getSettings().profile() ); String[] includedExcluded = splitIncludesExcludes( tests ); - switch ( getSettings().getConfiguration() ) { + switch ( getSettings().getConfiguration() ) + { case TEST: launcher.setTestToRun( tests ); break; @@ -361,11 +367,11 @@ public void shouldMatchMultiplePatterns() throws Exception { assumeThat( getSettings().getConfiguration(), is( TEST ) ); - String test = "jiras/surefire745/BasicTest#testSuccessOne+testSuccessTwo"//2 - + ',' + "jiras/**/TestTwo"//2 - + ',' + "jiras/surefire745/TestThree#testSuccess*"//2 - + ',' + "TestFour#testSuccess???"//2 - + ',' + "jiras/surefire745/*Five#test*One";//1 + String test = "jiras/surefire745/BasicTest#testSuccessOne+testSuccessTwo" //2 + + ',' + "jiras/**/TestTwo" //2 + + ',' + "jiras/surefire745/TestThree#testSuccess*" //2 + + ',' + "TestFour#testSuccess???" //2 + + ',' + "jiras/surefire745/*Five#test*One"; //1 prepare( test ) .executeTest() @@ -379,11 +385,11 @@ public void shouldMatchMultiplePatternsAsParallel() { assumeThat( getSettings().getFramework(), anyOf( is( JUNIT47 ), is( TestNG ) ) ); assumeThat( getSettings().getConfiguration(), is( TEST ) ); - String test = "jiras/surefire745/BasicTest#testSuccessOne+testSuccessTwo"//2 - + ',' + "jiras/**/TestTwo"//2 - + ',' + "jiras/surefire745/TestThree#testSuccess*"//2 - + ',' + "TestFour#testSuccess???"//2 - + ',' + "jiras/surefire745/*Five#test*One";//1 + String test = "jiras/surefire745/BasicTest#testSuccessOne+testSuccessTwo" //2 + + ',' + "jiras/**/TestTwo" //2 + + ',' + "jiras/surefire745/TestThree#testSuccess*" //2 + + ',' + "TestFour#testSuccess???" //2 + + ',' + "jiras/surefire745/*Five#test*One"; //1 prepare( test ) .parallel( "classes" ) @@ -398,11 +404,11 @@ public void shouldMatchMultiplePatternsComplex() throws Exception { assumeThat( getSettings().getConfiguration(), is( TEST ) ); - String test = "**/BasicTest#testSuccessOne+testSuccessTwo"//2 - + ',' + "jiras/**/TestTwo"//2 - + ',' + "?????/surefire745/TestThree#testSuccess*"//2 - + ',' + "jiras/surefire745/TestFour.java#testSuccess???"//2 - + ',' + "jiras/surefire745/*Five#test*One";//1 + String test = "**/BasicTest#testSuccessOne+testSuccessTwo" //2 + + ',' + "jiras/**/TestTwo" //2 + + ',' + "?????/surefire745/TestThree#testSuccess*" //2 + + ',' + "jiras/surefire745/TestFour.java#testSuccess???" //2 + + ',' + "jiras/surefire745/*Five#test*One"; //1 prepare( test ) .executeTest() @@ -416,11 +422,11 @@ public void shouldMatchMultiplePatternsComplexAsParallel() { assumeThat( getSettings().getFramework(), anyOf( is( JUNIT47 ), is( TestNG ) ) ); assumeThat( getSettings().getConfiguration(), is( TEST ) ); - String test = "**/BasicTest#testSuccessOne+testSuccessTwo"//2 - + ',' + "jiras/**/TestTwo"//2 - + ',' + "?????/surefire745/TestThree#testSuccess*"//2 - + ',' + "jiras/surefire745/TestFour.java#testSuccess???"//2 - + ',' + "jiras/surefire745/*Five#test*One";//1 + String test = "**/BasicTest#testSuccessOne+testSuccessTwo" //2 + + ',' + "jiras/**/TestTwo" //2 + + ',' + "?????/surefire745/TestThree#testSuccess*" //2 + + ',' + "jiras/surefire745/TestFour.java#testSuccess???" //2 + + ',' + "jiras/surefire745/*Five#test*One"; //1 prepare( test ) .parallel( "classes" ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/AssumptionFailureReportIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/AssumptionFailureReportIT.java index 856cd8c8c3..f9da42c663 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/AssumptionFailureReportIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/AssumptionFailureReportIT.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.its; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,11 +18,15 @@ * specific language governing permissions and limitations * under the License. */ + import org.apache.maven.surefire.its.fixture.OutputValidator; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; +/** + * + */ public class AssumptionFailureReportIT extends SurefireJUnit4IntegrationTestCase { @Test diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java index 85d0f951f0..95bbc3517e 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckSingleTestIT.java @@ -19,7 +19,10 @@ * under the License. */ -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; import static org.junit.Assert.assertFalse; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestFailIfNoTestsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestFailIfNoTestsIT.java index 787037c217..02fad0c153 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestFailIfNoTestsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestFailIfNoTestsIT.java @@ -19,7 +19,10 @@ * under the License. */ -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; import static org.junit.Assert.assertFalse; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgBeforeMethodFailureIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgBeforeMethodFailureIT.java index 440955cc74..22d72a09be 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgBeforeMethodFailureIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgBeforeMethodFailureIT.java @@ -33,8 +33,7 @@ public class CheckTestNgBeforeMethodFailureIT { @Test - public void TestNgBeforeMethodFailure() - throws Exception + public void testNgBeforeMethodFailure() { unpack( "/testng-beforeMethodFailure" ) .maven() diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgBeforeMethodIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgBeforeMethodIT.java index d96fefc6fd..02fab32348 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgBeforeMethodIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgBeforeMethodIT.java @@ -32,8 +32,7 @@ public class CheckTestNgBeforeMethodIT extends SurefireJUnit4IntegrationTestCase { @Test - public void TestNgBeforeMethod() - throws Exception + public void testNgBeforeMethod() { unpack( "/testng-beforeMethod" ) .sysProp( "testNgVersion", "5.7" ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgCustomObjectFactoryIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgCustomObjectFactoryIT.java index 2e2b6466cd..1cb7f75964 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgCustomObjectFactoryIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgCustomObjectFactoryIT.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.its; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgCustomTestRunnerFactoryIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgCustomTestRunnerFactoryIT.java index 4cf5afaf96..f21014e39c 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgCustomTestRunnerFactoryIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgCustomTestRunnerFactoryIT.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.its; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgExecuteErrorIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgExecuteErrorIT.java index ff0d9da9a4..8582753381 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgExecuteErrorIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgExecuteErrorIT.java @@ -30,7 +30,8 @@ /** - * Test for checking that the output from a forked suite is properly captured even if the suite encounters a severe error. + * Test for checking that the output from a forked suite is properly captured even if the suite encounters + * a severe error. * * @author Dan Fabulich * @author Kristian Rosenvold @@ -58,7 +59,7 @@ public boolean accept( File dir, String name ) { return name.endsWith( "-jvmRun1.dump" ); } - }); + } ); assertThat( dumpFiles ) .isNotNull() .isNotEmpty(); diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgGroupThreadParallelIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgGroupThreadParallelIT.java index f56e2e4d46..5b200a689b 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgGroupThreadParallelIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgGroupThreadParallelIT.java @@ -32,7 +32,7 @@ public class CheckTestNgGroupThreadParallelIT extends SurefireJUnit4IntegrationTestCase { @Test - public void TestNgGroupThreadParallel() + public void testNgGroupThreadParallel() { unpack( "testng-group-thread-parallel" ) .sysProp( "testNgVersion", "5.7" ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgJdk14IT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgJdk14IT.java index 9cabd7e731..fe060eca65 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgJdk14IT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgJdk14IT.java @@ -32,7 +32,7 @@ public class CheckTestNgJdk14IT { @Test - public void TestNgJdk14() + public void testNgJdk14() throws Exception { unpack( "/testng-jdk14" ).executeTest().verifyErrorFree( 1 ); diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgListenerReporterIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgListenerReporterIT.java index 2c618d0836..af945b0062 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgListenerReporterIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgListenerReporterIT.java @@ -19,11 +19,11 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import java.util.Arrays; import java.util.Collection; @@ -38,14 +38,16 @@ * @author Dan Fabulich * @author Kristian Rosenvold */ -@RunWith( Parameterized.class ) +@RunWith( ParallelParameterized.class ) +@SuppressWarnings( { "checkstyle:magicnumber", "checkstyle:linelength" } ) public class CheckTestNgListenerReporterIT extends SurefireJUnit4IntegrationTestCase { @Parameters( name = "{index}: TestNG {0}" ) public static Collection data() { - return Arrays.asList(new Object[][] { + return Arrays.asList( new Object[][] + { { "5.6", "jdk15", 1.5d }, // First TestNG version with reporter support { "5.7", "jdk15", 1.5d }, // default version from pom of the test case { "5.10", "jdk15", 1.5d }, @@ -71,17 +73,21 @@ public static Collection data() { "5.14.6", null, 1.5d }, // Usage of org.testng:guice removed { "5.14.9", null, 1.5d }, // Latest 5.14.x TestNG version { "6.0", null, 1.5d }, - { "6.9.9", null, 1.7d } // Currently latest TestNG version - }); + { "6.14.3", null, 1.7d }, + { "7.0.0", null, 1.8d } // Currently latest TestNG version + } ); } @Parameter + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String version; - @Parameter(1) + @Parameter( 1 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String classifier; - @Parameter(2) + @Parameter( 2 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public double javaVersion; @Test diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgListenersIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgListenersIT.java index cc1bb74f9d..beb3eb6a4c 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgListenersIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgListenersIT.java @@ -29,7 +29,7 @@ public class CheckTestNgListenersIT extends SurefireJUnit4IntegrationTestCase { @Test - public void TestNgListenerReporter() + public void testNgListenerReporter() { unpack( "testng-listeners" ).mavenTestFailureIgnore( true ).executeTest().assertTestSuiteResults( 1, 0, 1, 0 ); } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgPathWithSpacesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgPathWithSpacesIT.java index aa77d1b21e..654cfc294d 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgPathWithSpacesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgPathWithSpacesIT.java @@ -31,7 +31,7 @@ public class CheckTestNgPathWithSpacesIT extends SurefireJUnit4IntegrationTestCase { @Test - public void TestWithSpaces() + public void testWithSpaces() { unpack( "testng-path with spaces" ) .sysProp( "testNgVersion", "5.7" ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgSuiteXmlSingleIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgSuiteXmlSingleIT.java index e2b63b63b3..bec8422483 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgSuiteXmlSingleIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgSuiteXmlSingleIT.java @@ -31,7 +31,7 @@ public class CheckTestNgSuiteXmlSingleIT extends SurefireJUnit4IntegrationTestCase { @Test - public void TestNgSuite() + public void testNgSuite() { unpack( "/testng-twoTestCaseSuite" ) .sysProp( "testNgVersion", "5.7" ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgVersionsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgVersionsIT.java index 6d2bbfa214..64235ee8b3 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgVersionsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/CheckTestNgVersionsIT.java @@ -50,13 +50,17 @@ public class CheckTestNgVersionsIT runTestNgTest( "4.7", "jdk15" ); } - @Test @Ignore( "5.0 and 5.0.1 jars on central are malformed SUREFIRE-375 + MAVENUPLOAD-1024" ) public void XXXtest50() + @Test + @Ignore( "5.0 and 5.0.1 jars on central are malformed SUREFIRE-375 + MAVENUPLOAD-1024" ) + public void xXXtest50() throws Exception { runTestNgTest( "5.0", "jdk15" ); } - @Test @Ignore( "5.0 and 5.0.1 jars on central are malformed SUREFIRE-375 + MAVENUPLOAD-1024" ) public void XXXtest501() + @Test + @Ignore( "5.0 and 5.0.1 jars on central are malformed SUREFIRE-375 + MAVENUPLOAD-1024" ) + public void xXXtest501() throws Exception { runTestNgTest( "5.0.1", "jdk15" ); @@ -210,9 +214,14 @@ private void runTestNgTest( String version, String classifier, boolean validateR assertEquals( 3, report.size() ); - assertTrue( "TestNGSuiteTestC was executed first", getTestClass( report, 0 ).endsWith( "TestNGSuiteTestC" ) ); - assertTrue( "TestNGSuiteTestB was executed second", getTestClass( report, 1 ).endsWith( "TestNGSuiteTestB" ) ); - assertTrue( "TestNGSuiteTestA was executed last", getTestClass( report, 2 ).endsWith( "TestNGSuiteTestA" ) ); + assertTrue( "TestNGSuiteTestC was executed first", + getTestClass( report, 0 ).endsWith( "TestNGSuiteTestC" ) ); + + assertTrue( "TestNGSuiteTestB was executed second", + getTestClass( report, 1 ).endsWith( "TestNGSuiteTestB" ) ); + + assertTrue( "TestNGSuiteTestA was executed last", + getTestClass( report, 2 ).endsWith( "TestNGSuiteTestA" ) ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/ConsoleOutputIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/ConsoleOutputIT.java index 734d773d25..6f0802c027 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/ConsoleOutputIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/ConsoleOutputIT.java @@ -19,13 +19,13 @@ * under the License. */ -import java.nio.charset.Charset; - import org.apache.maven.surefire.its.fixture.OutputValidator; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * Basic suite test using all known versions of JUnit 4.x * @@ -65,13 +65,13 @@ private void validate( final OutputValidator outputValidator, boolean includeShu { TestFile xmlReportFile = outputValidator.getSurefireReportsXmlFile( "TEST-consoleOutput.Test1.xml" ); xmlReportFile.assertContainsText( "SoutLine" ); - xmlReportFile.assertContainsText( normalizeToDefaultCharset( "äöüß" ) ); - xmlReportFile.assertContainsText( normalizeToDefaultCharset( "failing with ü" ) ); + xmlReportFile.assertContainsText( "äöüß" ); + xmlReportFile.assertContainsText( "failing with ü" ); - TestFile outputFile = outputValidator.getSurefireReportsFile( "consoleOutput.Test1-output.txt" ); + TestFile outputFile = outputValidator.getSurefireReportsFile( "consoleOutput.Test1-output.txt", UTF_8 ); outputFile.assertContainsText( "SoutAgain" ); outputFile.assertContainsText( "SoutLine" ); - outputFile.assertContainsText( normalizeToDefaultCharset( "äöüß" ) ); + outputFile.assertContainsText( "äöüß" ); if ( includeShutdownHook ) { @@ -79,22 +79,6 @@ private void validate( final OutputValidator outputValidator, boolean includeShu } } - /** - * @param string the string to normalize - * @return the string with all characters not available in the current charset being replaced, e.g. for US-ASCII, - * German umlauts would be replaced to ? - */ - private String normalizeToDefaultCharset( String string ) - { - Charset cs = Charset.defaultCharset(); - if ( cs.canEncode() ) - { - string = cs.decode( cs.encode( string ) ).toString(); - } - - return string; - } - @Test public void largerSoutThanMemory() { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/EnvironmentVariablesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/EnvironmentVariablesIT.java index 651200f6d8..97342dc611 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/EnvironmentVariablesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/EnvironmentVariablesIT.java @@ -35,13 +35,30 @@ public class EnvironmentVariablesIT @Test public void testWhenUseSystemClassLoader() { - unpack( "/environment-variables" ).addGoal( "-DuseSystemClassLoader=true" ).executeTest(); + unpack( "/environment-variables" ) + .debugLogging() + .addGoal( "-DuseSystemClassLoader=true" ) + .executeTest(); } @Test public void testWhenDontUseSystemClassLoader() { - unpack( "/environment-variables" ).addGoal( "-DuseSystemClassLoader=false" ).executeTest(); + unpack( "/environment-variables" ) + .debugLogging() + .addGoal( "-DuseSystemClassLoader=false" ) + .executeTest(); + } + + @Test + public void testExcludedEnv() + { + unpack( "/environment-variables" ) + .maven() + .debugLogging() + .addEnvVar( "UNDEFINED_VAR", "dwdijoi" ) + .sysProp( "surefire.excludedEnvironmentVariables", "UNDEFINED_VAR" ) + .executeTest(); } } \ No newline at end of file diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/FailFastJUnitIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/FailFastJUnitIT.java index beb1e328c6..9077c02642 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/FailFastJUnitIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/FailFastJUnitIT.java @@ -32,8 +32,8 @@ public class FailFastJUnitIT extends AbstractFailFastIT { - - @Parameters(name = "{0}") + @Parameters( name = "{0}" ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public static Iterable data() { /** @@ -55,13 +55,13 @@ public static Iterable data() args.add( new Object[] { "junit4-oneFork-ff2", "junit4", props( 1, 2, true ), 5, 0, 2, 3 } ); args.add( new Object[] { "junit47-oneFork-ff2", "junit47", props( 1, 2, true ), 5, 0, 2, 3 } ); args.add( new Object[] { "junit4-twoForks-ff1", "junit4", props( 2, 1, true ), 5, 0, 2, 3 } ); - args.add( new Object[] { "junit47-twoForks-ff1", "junit47",props( 2, 1, true ), 5, 0, 2, 3 } ); + args.add( new Object[] { "junit47-twoForks-ff1", "junit47", props( 2, 1, true ), 5, 0, 2, 3 } ); args.add( new Object[] { "junit4-twoForks-ff2", "junit4", props( 2, 2, true ), 5, 0, 2, 2 } ); - args.add( new Object[] { "junit47-twoForks-ff2", "junit47",props( 2, 2, true ), 5, 0, 2, 2 } ); + args.add( new Object[] { "junit47-twoForks-ff2", "junit47", props( 2, 2, true ), 5, 0, 2, 2 } ); args.add( new Object[] { "junit4-oneFork-ff3", "junit4", props( 1, 3, true ), 5, 0, 2, 0 } ); args.add( new Object[] { "junit47-oneFork-ff3", "junit47", props( 1, 3, true ), 5, 0, 2, 0 } ); args.add( new Object[] { "junit4-twoForks-ff3", "junit4", props( 2, 3, true ), 5, 0, 2, 0 } ); - args.add( new Object[] { "junit47-twoForks-ff3", "junit47",props( 2, 3, true ), 5, 0, 2, 0 } ); + args.add( new Object[] { "junit47-twoForks-ff3", "junit47", props( 2, 3, true ), 5, 0, 2, 0 } ); /*args.add( new Object[] { "junit4-twoForks-ff1x","junit4", props( 2, 1, false ), 5, 0, 2, 3 } ); args.add( new Object[] { "junit47-twoForks-ff1x","junit47",props( 2, 1, false ), 5, 0, 2, 3 } ); args.add( new Object[] { "junit4-twoForks-ff2x","junit4", props( 2, 2, false ), 5, 0, 2, 2 } ); diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/FailFastTestNgIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/FailFastTestNgIT.java index f4aa2b7f7d..0ee26068fd 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/FailFastTestNgIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/FailFastTestNgIT.java @@ -33,7 +33,7 @@ public class FailFastTestNgIT extends AbstractFailFastIT { - @Parameters(name = "{0}") + @Parameters( name = "{0}" ) public static Iterable data() { /** diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/ForkModeIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/ForkModeIT.java index 6965b4d8b9..22dc5fdb79 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/ForkModeIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/ForkModeIT.java @@ -143,8 +143,8 @@ public void testForkCountOneReuse() @Test public void testForkCountTwoNoReuse() { - String[] pids = - doTest( unpack( getProject() ).setForkJvm().forkCount( 2 ).reuseForks( false ).addGoal( "-DsleepLength=7200" ) ); + String[] pids = doTest( unpack( getProject() ).setForkJvm().forkCount( 2 ).reuseForks( false ) + .addGoal( "-DsleepLength=7200" ) ); assertDifferentPids( pids ); assertFalse( "pid 1 is not the same as the main process' pid", pids[0].equals( getMainPID() ) ); } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/ForkModeMultiModuleIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/ForkModeMultiModuleIT.java index 6a8d9df2fa..b0ed712692 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/ForkModeMultiModuleIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/ForkModeMultiModuleIT.java @@ -19,7 +19,11 @@ * under the License. */ -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.HelperAssertions; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; import java.io.File; @@ -33,22 +37,21 @@ /** * Test forkMode in a multi module project with parallel maven builds - * + * * @author Andreas Gudian */ -public class ForkModeMultiModuleIT - extends SurefireJUnit4IntegrationTestCase +public class ForkModeMultiModuleIT extends SurefireJUnit4IntegrationTestCase { @Test public void testForkCountOneNoReuse() { List pids = doTest( unpack( getProject() ).forkCount( 1 ).reuseForks( false ) ); assertAllDifferentPids( pids ); - int matchesOne = countSuffixMatches( pids, "_1_1"); + int matchesOne = countSuffixMatches( pids, "_1_1" ); int matchesTwo = countSuffixMatches( pids, "_2_2" ); assertTrue( "At least one fork had forkNumber 1", matchesOne >= 1 ); assertTrue( "At least one fork had forkNumber 2", matchesTwo >= 1 ); - assertEquals( "No other forkNumbers than 1 and 2 have been used", 6, matchesOne + matchesTwo); + assertEquals( "No other forkNumbers than 1 and 2 have been used", 6, matchesOne + matchesTwo ); } @@ -66,33 +69,34 @@ public void testForkCountTwoNoReuse() { List pids = doTest( unpack( getProject() ).forkCount( 2 ).reuseForks( false ) ); assertAllDifferentPids( pids ); - int matchesOne = countSuffixMatches( pids, "_1_1"); + int matchesOne = countSuffixMatches( pids, "_1_1" ); int matchesTwo = countSuffixMatches( pids, "_2_2" ); - int matchesThree = countSuffixMatches( pids, "_3_3"); + int matchesThree = countSuffixMatches( pids, "_3_3" ); int matchesFour = countSuffixMatches( pids, "_4_4" ); assertTrue( "At least one fork had forkNumber 1", matchesOne >= 1 ); assertTrue( "At least one fork had forkNumber 2", matchesTwo >= 1 ); assertTrue( "At least one fork had forkNumber 3", matchesThree >= 1 ); assertTrue( "At least one fork had forkNumber 4", matchesFour >= 1 ); - assertEquals( "No other forkNumbers than 1, 2, 3, or 4 have been used", 6, matchesOne + matchesTwo + matchesThree + matchesFour ); + assertEquals( "No other forkNumbers than 1, 2, 3, or 4 have been used", 6, + matchesOne + matchesTwo + matchesThree + matchesFour ); } @Test public void testForkCountTwoReuse() { - List pids = - doTest( unpack( getProject() ).forkCount( 2 ).reuseForks( true ) ); + List pids = doTest( unpack( getProject() ).forkCount( 2 ).reuseForks( true ) ); assertDifferentPids( pids, 4 ); - - int matchesOne = countSuffixMatches( pids, "_1_1"); + + int matchesOne = countSuffixMatches( pids, "_1_1" ); int matchesTwo = countSuffixMatches( pids, "_2_2" ); - int matchesThree = countSuffixMatches( pids, "_3_3"); + int matchesThree = countSuffixMatches( pids, "_3_3" ); int matchesFour = countSuffixMatches( pids, "_4_4" ); assertTrue( "At least one fork had forkNumber 1", matchesOne >= 1 ); assertTrue( "At least one fork had forkNumber 2", matchesTwo >= 1 ); assertTrue( "At least one fork had forkNumber 3", matchesThree >= 1 ); assertTrue( "At least one fork had forkNumber 4", matchesFour >= 1 ); - assertEquals( "No other forkNumbers than 1, 2, 3, or 4 have been used", 6, matchesOne + matchesTwo + matchesThree + matchesFour ); + assertEquals( "No other forkNumbers than 1, 2, 3, or 4 have been used", 6, + matchesOne + matchesTwo + matchesThree + matchesFour ); } private void assertEndWith( List pids, String suffix, int expectedMatches ) @@ -149,7 +153,7 @@ private List validateModule( OutputValidator outputValidator, String mod String pid = targetFile.slurpFile(); pids.add( pid ); } - + return pids; } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/IncludesExcludesFromFileIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/IncludesExcludesFromFileIT.java index a6c539cbad..89e735f930 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/IncludesExcludesFromFileIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/IncludesExcludesFromFileIT.java @@ -64,7 +64,7 @@ public void testPath() @Test public void testMissingExcludes() { - expectBuildFailure("missing-excludes-file", "Failed to load list from file", "no-such-excludes-file"); + expectBuildFailure( "missing-excludes-file", "Failed to load list from file", "no-such-excludes-file" ); } @Test diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47ConcurrencyIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47ConcurrencyIT.java index 57007a72ad..c7ccdad912 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47ConcurrencyIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47ConcurrencyIT.java @@ -23,9 +23,11 @@ import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Test; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertNotNull; +import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.*; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.CoreMatchers.endsWith; /** * Basic suite test using all known versions of JUnit 4.x @@ -51,7 +53,7 @@ public void test47() break; } } - assertNotNull( result); + assertNotNull( result ); assertThat( result, anyOf( containsString( "Time elapsed: 1." ), containsString( "Time elapsed: 0.9" ) ) ); assertThat( result, endsWith( " s - in concurrentjunit47.src.test.java.junit47.BasicTest" ) ); } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47ParallelIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47ParallelIT.java index fdf75efaef..e6121966e9 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47ParallelIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47ParallelIT.java @@ -29,29 +29,29 @@ * @author Tibor Digana (tibor17) * @since 2.16 */ -public class JUnit47ParallelIT - extends SurefireJUnit4IntegrationTestCase +@SuppressWarnings( "checkstyle:magicnumber" ) +public class JUnit47ParallelIT extends SurefireJUnit4IntegrationTestCase { @Test public void unknownThreadCountSuites() { unpack().parallelSuites().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog( - "Use threadCount or threadCountSuites > 0 or useUnlimitedThreads=true for parallel='suites'" ); + "Use threadCount or threadCountSuites > 0 or useUnlimitedThreads=true for parallel='suites'" ); } @Test public void unknownThreadCountClasses() { unpack().parallelClasses().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog( - "Use threadCount or threadCountClasses > 0 or useUnlimitedThreads=true for parallel='classes'" ); + "Use threadCount or threadCountClasses > 0 or useUnlimitedThreads=true for parallel='classes'" ); } @Test public void unknownThreadCountMethods() { unpack().parallelMethods().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog( - "Use threadCount or threadCountMethods > 0 or useUnlimitedThreads=true for parallel='methods'" ); + "Use threadCount or threadCountMethods > 0 or useUnlimitedThreads=true for parallel='methods'" ); } @@ -59,61 +59,52 @@ public void unknownThreadCountMethods() public void unknownThreadCountBoth() { unpack().parallelBoth().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog( - "Use useUnlimitedThreads=true, " + - "or only threadCount > 0, " + - "or (threadCountClasses > 0 and threadCountMethods > 0), " + - "or (threadCount > 0 and threadCountClasses > 0 and threadCountMethods > 0), " + - "or (threadCount > 0 and threadCountClasses > 0 and threadCount > threadCountClasses) " + - "for parallel='both' or parallel='classesAndMethods'" ); + "Use useUnlimitedThreads=true, " + "or only threadCount > 0, " + "or (threadCountClasses > 0 and " + + "threadCountMethods > 0), " + "or (threadCount > 0 and threadCountClasses > 0 and " + + "threadCountMethods > 0), " + "or (threadCount > 0 and threadCountClasses > 0 and " + + "threadCount > threadCountClasses) " + "for parallel='both' or " + + "parallel='classesAndMethods'" ); } @Test public void unknownThreadCountAll() { unpack().parallelAll().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog( - "Use useUnlimitedThreads=true, " + - "or only threadCount > 0, " + - "or (threadCountSuites > 0 and threadCountClasses > 0 and threadCountMethods > 0), " + - "or every thread-count is specified, " + - "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0 " + - "and threadCount > threadCountSuites + threadCountClasses) " + - "for parallel='all'" ); + "Use useUnlimitedThreads=true, " + "or only threadCount > 0, " + "or (threadCountSuites > 0 and " + + "threadCountClasses > 0 and threadCountMethods > 0), " + "or every thread-count is " + + "specified, " + "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0 " + + "and threadCount > threadCountSuites + threadCountClasses) " + "for parallel='all'" ); } @Test public void unknownThreadCountSuitesAndClasses() { unpack().parallelSuitesAndClasses().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog( - "Use useUnlimitedThreads=true, " + - "or only threadCount > 0, " + - "or (threadCountSuites > 0 and threadCountClasses > 0), " + - "or (threadCount > 0 and threadCountSuites > 0 and threadCountClasses > 0) " + - "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) " + - "for parallel='suitesAndClasses' or 'both'" ); + "Use useUnlimitedThreads=true, " + "or only threadCount > 0, " + "or (threadCountSuites > 0 and " + + "threadCountClasses > 0), " + "or (threadCount > 0 and threadCountSuites > 0 and " + + "threadCountClasses > 0) " + "or (threadCount > 0 and threadCountSuites > 0 and threadCount" + + " > threadCountSuites) " + "for parallel='suitesAndClasses' or 'both'" ); } @Test public void unknownThreadCountSuitesAndMethods() { unpack().parallelSuitesAndMethods().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog( - "Use useUnlimitedThreads=true, " + - "or only threadCount > 0, " + - "or (threadCountSuites > 0 and threadCountMethods > 0), " + - "or (threadCount > 0 and threadCountSuites > 0 and threadCountMethods > 0), " + - "or (threadCount > 0 and threadCountSuites > 0 and threadCount > threadCountSuites) " + - "for parallel='suitesAndMethods'" ); + "Use useUnlimitedThreads=true, " + "or only threadCount > 0, " + "or (threadCountSuites > 0 and " + + "threadCountMethods > 0), " + "or (threadCount > 0 and threadCountSuites > 0 and " + + "threadCountMethods > 0), " + "or (threadCount > 0 and threadCountSuites > 0 and " + + "threadCount > threadCountSuites) " + "for parallel='suitesAndMethods'" ); } @Test public void unknownThreadCountClassesAndMethods() { unpack().parallelClassesAndMethods().setTestToRun( "TestClass" ).failNever().executeTest().verifyTextInLog( - "Use useUnlimitedThreads=true, " + - "or only threadCount > 0, " + - "or (threadCountClasses > 0 and threadCountMethods > 0), " + - "or (threadCount > 0 and threadCountClasses > 0 and threadCountMethods > 0), " + - "or (threadCount > 0 and threadCountClasses > 0 and threadCount > threadCountClasses) " + - "for parallel='both' or parallel='classesAndMethods'" ); + "Use useUnlimitedThreads=true, " + "or only threadCount > 0, " + "or (threadCountClasses > 0 and " + + "threadCountMethods > 0), " + "or (threadCount > 0 and threadCountClasses > 0 and " + + "threadCountMethods > 0), " + "or (threadCount > 0 and threadCountClasses > 0 and " + + "threadCount > threadCountClasses) " + "for parallel='both' or " + + "parallel='classesAndMethods'" ); } @Test @@ -128,7 +119,7 @@ public void unlimitedThreadsSuites1() { // takes 3.6 sec unpack().parallelSuites().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( - 24 ); + 24 ); } @Test @@ -136,7 +127,7 @@ public void unlimitedThreadsSuites2() { // takes 3.6 sec unpack().parallelSuites().useUnlimitedThreads().threadCountSuites( 5 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -144,7 +135,7 @@ public void unlimitedThreadsClasses1() { // takes 1.8 sec unpack().parallelClasses().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( - 24 ); + 24 ); } @Test @@ -152,7 +143,7 @@ public void unlimitedThreadsClasses2() { // takes 1.8 sec unpack().parallelClasses().useUnlimitedThreads().threadCountClasses( 5 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -160,7 +151,7 @@ public void unlimitedThreadsMethods1() { // takes 2.4 sec unpack().parallelMethods().useUnlimitedThreads().setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( - 24 ); + 24 ); } @Test @@ -168,7 +159,7 @@ public void unlimitedThreadsMethods2() { // takes 2.4 sec unpack().parallelMethods().useUnlimitedThreads().threadCountMethods( 5 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -176,7 +167,7 @@ public void unlimitedThreadsSuitesAndClasses1() { // takes 0.9 sec unpack().parallelSuitesAndClasses().useUnlimitedThreads().setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -185,7 +176,7 @@ public void unlimitedThreadsSuitesAndClasses2() // takes 0.9 sec // 1.8 sec with 4 parallel classes unpack().parallelSuitesAndClasses().useUnlimitedThreads().threadCountSuites( 5 ).threadCountClasses( - 15 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 15 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -193,7 +184,7 @@ public void unlimitedThreadsSuitesAndMethods1() { // takes 1.2 sec unpack().parallelSuitesAndMethods().useUnlimitedThreads().setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -201,7 +192,7 @@ public void unlimitedThreadsSuitesAndMethods2() { // takes 1.2 sec unpack().parallelSuitesAndMethods().useUnlimitedThreads().threadCountSuites( 5 ).threadCountMethods( - 15 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 15 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -209,7 +200,7 @@ public void unlimitedThreadsClassesAndMethods1() { // takes 0.6 sec unpack().parallelClassesAndMethods().useUnlimitedThreads().setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -217,7 +208,7 @@ public void unlimitedThreadsClassesAndMethods2() { // takes 0.6 sec unpack().parallelClassesAndMethods().useUnlimitedThreads().threadCountClasses( 5 ).threadCountMethods( - 15 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 15 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -232,7 +223,7 @@ public void unlimitedThreadsAll2() { // takes 0.3 sec unpack().parallelAll().useUnlimitedThreads().threadCountSuites( 5 ).threadCountClasses( 15 ).threadCountMethods( - 30 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 30 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -262,7 +253,7 @@ public void threadCountClassesAndMethodsOneCore() { // takes 4.8 sec unpack().disablePerCoreThreadCount().disableParallelOptimization().parallelClassesAndMethods().threadCount( - 3 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 3 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -270,7 +261,7 @@ public void threadCountClassesAndMethodsOneCoreOptimized() { // the number of reused threads in leafs depends on the number of runners and CPU unpack().disablePerCoreThreadCount().parallelClassesAndMethods().threadCount( 3 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -278,7 +269,7 @@ public void threadCountClassesAndMethods() { // takes 2.4 sec for double core CPU unpack().disableParallelOptimization().parallelClassesAndMethods().threadCount( 3 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -286,7 +277,7 @@ public void threadCountClassesAndMethodsOptimized() { // the number of reused threads in leafs depends on the number of runners and CPU unpack().parallelClassesAndMethods().threadCount( 3 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -295,7 +286,7 @@ public void threadCountSuitesAndMethods() // usually 24 times 0.3 sec = 7.2 sec with one core CPU // takes 1.8 sec for double core CPU unpack().disableParallelOptimization().parallelSuitesAndMethods().threadCount( 3 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -303,14 +294,14 @@ public void threadCountSuitesAndMethodsOptimized() { // the number of reused threads in leafs depends on the number of runners and CPU unpack().parallelSuitesAndMethods().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( - 24 ); + 24 ); } @Test public void threadCountSuitesAndClasses() { unpack().disableParallelOptimization().parallelSuitesAndClasses().threadCount( 3 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -318,14 +309,14 @@ public void threadCountSuitesAndClassesOptimized() { // the number of reused threads in leafs depends on the number of runners and CPU unpack().parallelSuitesAndClasses().threadCount( 3 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( - 24 ); + 24 ); } @Test public void threadCountAll() { unpack().disableParallelOptimization().parallelAll().threadCount( 3 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -340,7 +331,7 @@ public void everyThreadCountSuitesAndClasses() { // takes 1.8 sec for double core CPU unpack().parallelSuitesAndClasses().threadCount( 3 ).threadCountSuites( 34 ).threadCountClasses( - 66 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 66 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -348,7 +339,7 @@ public void everyThreadCountSuitesAndMethods() { // takes 1.8 sec for double core CPU unpack().parallelSuitesAndMethods().threadCount( 3 ).threadCountSuites( 34 ).threadCountMethods( - 66 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 66 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -356,7 +347,7 @@ public void everyThreadCountClassesAndMethods() { // takes 1.8 sec for double core CPU unpack().parallelClassesAndMethods().threadCount( 3 ).threadCountClasses( 34 ).threadCountMethods( - 66 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 66 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -364,7 +355,7 @@ public void everyThreadCountAll() { // takes 2.4 sec for double core CPU unpack().parallelAll().threadCount( 3 ).threadCountSuites( 17 ).threadCountClasses( 34 ).threadCountMethods( - 49 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 49 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -373,7 +364,7 @@ public void reusableThreadCountSuitesAndClasses() // 4 * cpu to 5 * cpu threads to run test classes // takes cca 1.8 sec unpack().disableParallelOptimization().parallelSuitesAndClasses().disablePerCoreThreadCount().threadCount( - 6 ).threadCountSuites( 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 6 ).threadCountSuites( 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -381,7 +372,7 @@ public void reusableThreadCountSuitesAndClassesOptimized() { // the number of reused threads in leafs depends on the number of runners and CPU unpack().parallelSuitesAndClasses().disablePerCoreThreadCount().threadCount( 6 ).threadCountSuites( - 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -390,7 +381,7 @@ public void reusableThreadCountSuitesAndMethods() // 4 * cpu to 5 * cpu threads to run test methods // takes cca 1.8 sec unpack().disableParallelOptimization().parallelSuitesAndMethods().disablePerCoreThreadCount().threadCount( - 6 ).threadCountSuites( 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 6 ).threadCountSuites( 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -398,7 +389,7 @@ public void reusableThreadCountSuitesAndMethodsOptimized() { // the number of reused threads in leafs depends on the number of runners and CPU unpack().parallelSuitesAndMethods().disablePerCoreThreadCount().threadCount( 6 ).threadCountSuites( - 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -407,7 +398,7 @@ public void reusableThreadCountClassesAndMethods() // 4 * cpu to 5 * cpu threads to run test methods // takes cca 1.8 sec unpack().disableParallelOptimization().parallelClassesAndMethods().disablePerCoreThreadCount().threadCount( - 6 ).threadCountClasses( 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 6 ).threadCountClasses( 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -415,7 +406,7 @@ public void reusableThreadCountClassesAndMethodsOptimized() { // the number of reused threads in leafs depends on the number of runners and CPU unpack().parallelClassesAndMethods().disablePerCoreThreadCount().threadCount( 6 ).threadCountClasses( - 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 2 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -424,8 +415,8 @@ public void reusableThreadCountAll() // 8 * cpu to 13 * cpu threads to run test methods // takes 0.9 sec unpack().disableParallelOptimization().parallelAll().disablePerCoreThreadCount().threadCount( - 14 ).threadCountSuites( 2 ).threadCountClasses( 4 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 14 ).threadCountSuites( 2 ).threadCountClasses( 4 ).setTestToRun( + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -433,7 +424,7 @@ public void reusableThreadCountAllOptimized() { // the number of reused threads in leafs depends on the number of runners and CPU unpack().parallelAll().disablePerCoreThreadCount().threadCount( 14 ).threadCountSuites( 2 ).threadCountClasses( - 4 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + 4 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -441,7 +432,7 @@ public void suites() { // takes 3.6 sec unpack().parallelSuites().threadCountSuites( 5 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( - 24 ); + 24 ); } @Test @@ -449,7 +440,7 @@ public void classes() { // takes 1.8 sec on any CPU because the suites are running in a sequence unpack().parallelClasses().threadCountClasses( 5 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( - 24 ); + 24 ); } @Test @@ -458,7 +449,7 @@ public void methods() // takes 2.4 sec on any CPU because every class has only three methods // and the suites and classes are running in a sequence unpack().parallelMethods().threadCountMethods( 5 ).setTestToRun( "Suite*Test" ).executeTest().verifyErrorFree( - 24 ); + 24 ); } @Test @@ -466,7 +457,7 @@ public void suitesAndClasses() { // takes 0.9 sec unpack().parallelSuitesAndClasses().threadCountSuites( 5 ).threadCountClasses( 15 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -474,7 +465,7 @@ public void suitesAndMethods() { // takes 1.2 sec on any CPU unpack().parallelSuitesAndMethods().threadCountSuites( 5 ).threadCountMethods( 15 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -482,7 +473,7 @@ public void classesAndMethods() { // takes 0.6 sec on any CPU unpack().parallelClassesAndMethods().threadCountClasses( 5 ).threadCountMethods( 15 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -490,7 +481,7 @@ public void all() { // takes 0.3 sec on any CPU unpack().parallelAll().threadCountSuites( 5 ).threadCountClasses( 15 ).threadCountMethods( 30 ).setTestToRun( - "Suite*Test" ).executeTest().verifyErrorFree( 24 ); + "Suite*Test" ).executeTest().verifyErrorFree( 24 ); } @Test @@ -498,8 +489,8 @@ public void shutdown() { // executes for 2.5 sec until timeout has elapsed unpack().parallelMethods().threadCountMethods( 2 ).parallelTestsTimeoutInSeconds( 2.5d ).setTestToRun( - "TestClass" ).failNever().executeTest().verifyTextInLog( - "The test run has finished abruptly after timeout of 2.5 seconds." ); + "TestClass" ).failNever().executeTest().verifyTextInLog( + "The test run has finished abruptly after timeout of 2.5 seconds." ); } @Test @@ -507,8 +498,8 @@ public void forcedShutdown() { // executes for 2.5 sec until timeout has elapsed unpack().parallelMethods().threadCountMethods( 2 ).parallelTestsTimeoutForcedInSeconds( 2.5d ).setTestToRun( - "TestClass" ).failNever().executeTest().verifyTextInLog( - "The test run has finished abruptly after timeout of 2.5 seconds." ); + "TestClass" ).failNever().executeTest().verifyTextInLog( + "The test run has finished abruptly after timeout of 2.5 seconds." ); } @Test @@ -516,27 +507,25 @@ public void timeoutAndForcedShutdown() { // executes for one sec until timeout has elapsed unpack().parallelMethods().threadCountMethods( 2 ).parallelTestsTimeoutInSeconds( - 1 ).parallelTestsTimeoutForcedInSeconds( 2.5d ).setTestToRun( - "TestClass" ).failNever().executeTest().verifyTextInLog( - "The test run has finished abruptly after timeout of 1.0 seconds." ); + 1 ).parallelTestsTimeoutForcedInSeconds( 2.5d ).setTestToRun( + "TestClass" ).failNever().executeTest().verifyTextInLog( + "The test run has finished abruptly after timeout of 1.0 seconds." ); } @Test public void forcedShutdownVerifyingLogs() { // attempts to run for 2.4 sec until timeout has elapsed - unpack().parallelMethods().threadCountMethods( 3 ).disablePerCoreThreadCount() - .parallelTestsTimeoutForcedInSeconds( 1.05d ).setTestToRun( "Waiting*Test" ).failNever().executeTest() - .verifyTextInLog( "The test run has finished abruptly after timeout of 1.05 seconds." ) - .verifyTextInLog( "These tests were executed in prior to the shutdown operation:" ) - .verifyTextInLog( "These tests are incomplete:" ); + unpack().parallelMethods().threadCountMethods( + 3 ).disablePerCoreThreadCount().parallelTestsTimeoutForcedInSeconds( 1.05d ).setTestToRun( + "Waiting*Test" ).failNever().executeTest().verifyTextInLog( + "The test run has finished abruptly after timeout of 1.05 seconds." ).verifyTextInLog( + "These tests were executed in prior to the shutdown operation:" ).verifyTextInLog( + "These tests are incomplete:" ); } private SurefireLauncher unpack() { - return unpack( "junit47-parallel" ) - .showErrorStackTraces() - .forkOnce() - .redirectToFile( false ); + return unpack( "junit47-parallel" ).showErrorStackTraces().forkOnce().redirectToFile( false ); } } \ No newline at end of file diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RedirectOutputIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RedirectOutputIT.java index c3144e1ed9..437d24a2f0 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RedirectOutputIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RedirectOutputIT.java @@ -30,6 +30,9 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +/** + * + */ public class JUnit47RedirectOutputIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RerunFailingTestWithCucumberIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RerunFailingTestWithCucumberIT.java index 628d63ee93..470cfe3233 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RerunFailingTestWithCucumberIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47RerunFailingTestWithCucumberIT.java @@ -24,48 +24,41 @@ import org.junit.Test; /** - * Tests using the JUnit 47 provider to rerun failing tests with the cucumber runner. The main - * problem that the junit4 provider has with the cucumber runner is that the junit Description - * instance created by the runner has a null test class attribute. This requires that tests are - * rerun based on their description. + * Tests using the JUnit 47 provider to rerun failing tests with the cucumber runner. The main problem that the junit4 + * provider has with the cucumber runner is that the junit Description instance created by the runner has a null test + * class attribute. This requires that tests are rerun based on their description. * * @author mpkorstanje */ -public class JUnit47RerunFailingTestWithCucumberIT - extends SurefireJUnit4IntegrationTestCase { +public class JUnit47RerunFailingTestWithCucumberIT extends SurefireJUnit4IntegrationTestCase +{ - private SurefireLauncher unpack() { - return unpack("junit47-rerun-failing-tests-with-cucumber") - .setJUnitVersion("4.12"); + private SurefireLauncher unpack() + { + return unpack( "junit47-rerun-failing-tests-with-cucumber" ).setJUnitVersion( "4.12" ); } @Test - public void testRerunFailingErrorTestsFalse() { - unpack() - .maven() - .addGoal("-Dsurefire.rerunFailingTestsCount=" + 0) - .withFailure() - .executeTest() - .assertTestSuiteResults(1, 0, 1, 0, 0); + public void testRerunFailingErrorTestsFalse() + { + unpack().maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=" + 0 ).withFailure().executeTest().assertTestSuiteResults( 1, 0, 1, + 0, 0 ); } @Test - public void testRerunFailingErrorTestsWithOneRetry() { - unpack() - .maven() - .addGoal("-Dsurefire.rerunFailingTestsCount=" + 1) - .withFailure() - .executeTest() - .assertTestSuiteResults(1, 0, 1, 0, 0); + public void testRerunFailingErrorTestsWithOneRetry() + { + unpack().maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=" + 1 ).withFailure().executeTest().assertTestSuiteResults( 1, 0, 1, + 0, 0 ); } @Test - public void testRerunFailingErrorTestsTwoRetry() { - unpack() - .maven() - .addGoal("-Dsurefire.rerunFailingTestsCount=" + 2) - .executeTest() - .assertTestSuiteResults(1, 0, 0, 0, 2); + public void testRerunFailingErrorTestsTwoRetry() + { + unpack().maven().addGoal( "-Dsurefire.rerunFailingTestsCount=" + 2 ).executeTest().assertTestSuiteResults( 1, 0, + 0, 0, 2 ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47StaticInnerClassTestsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47StaticInnerClassTestsIT.java index e50e6d7df8..c3e2e972dc 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47StaticInnerClassTestsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit47StaticInnerClassTestsIT.java @@ -22,6 +22,9 @@ import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Test; +/** + * + */ public class JUnit47StaticInnerClassTestsIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit4RerunFailingTestsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit4RerunFailingTestsIT.java index 7d6f5609d0..b64edff5d0 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit4RerunFailingTestsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit4RerunFailingTestsIT.java @@ -254,9 +254,9 @@ private void verifyFailuresTwoRetry( OutputValidator outputValidator, int run, i private void verifyFailuresNoRetry( OutputValidator outputValidator, int run, int failures, int errors, int flakes ) { outputValidator.verifyTextInLog( "Failures:" ); - outputValidator.verifyTextInLog( "testFailingTestOne(junit4.FlakyFirstTimeTest)" ); + outputValidator.verifyTextInLog( "junit4.FlakyFirstTimeTest.testFailingTestOne" ); outputValidator.verifyTextInLog( "ERROR" ); - outputValidator.verifyTextInLog( "testErrorTestOne(junit4.FlakyFirstTimeTest)" ); + outputValidator.verifyTextInLog( "junit4.FlakyFirstTimeTest.testErrorTestOne" ); verifyStatistics( outputValidator, run, failures, errors, flakes ); } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit4VersionsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit4VersionsIT.java index 24d4d63db8..38ca8a5e6e 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit4VersionsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnit4VersionsIT.java @@ -21,11 +21,11 @@ import java.util.Collection; +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import static java.util.Arrays.asList; @@ -36,7 +36,7 @@ import static org.apache.maven.surefire.its.JUnitVersion.JUNIT_4_8_1; import static org.apache.maven.surefire.its.JUnitVersion.JUNIT_4_8_2; import static org.apache.maven.surefire.its.JUnitVersion.JUNIT_4_9; -import static org.junit.runners.Parameterized.*; +import static org.junit.runners.Parameterized.Parameters; import static org.apache.maven.surefire.its.JUnitVersion.JUNIT_4_0; import static org.apache.maven.surefire.its.JUnitVersion.JUNIT_4_1; @@ -53,7 +53,7 @@ * * @author Dan Fabulich */ -@RunWith( Parameterized.class ) +@RunWith( ParallelParameterized.class ) public class JUnit4VersionsIT extends SurefireJUnit4IntegrationTestCase { @@ -82,6 +82,7 @@ public static Collection junitVersions() } @Parameter + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public JUnitVersion version; @Test diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitDepIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitDepIT.java index 0757a17ec9..045473aac0 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitDepIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitDepIT.java @@ -28,8 +28,7 @@ * * @author Dan Fabulich */ -public class JUnitDepIT - extends SurefireJUnit4IntegrationTestCase +public class JUnitDepIT extends SurefireJUnit4IntegrationTestCase { public SurefireLauncher unpack() { @@ -37,34 +36,30 @@ public SurefireLauncher unpack() } @Test - public void testJUnit44Dep() - throws Exception + public void testJUnit44Dep() throws Exception { - unpack().debugLogging().sysProp( "junit-dep.version", "4.4" ).executeTest().verifyErrorFree( 1 ).verifyTextInLog( - "surefire-junit4" ); // Ahem. Will match on the 4.7 provider too + unpack().debugLogging().sysProp( "junit-dep.version", "4.4" ).executeTest().verifyErrorFree( + 1 ).verifyTextInLog( "surefire-junit4" ); // Ahem. Will match on the 4.7 provider too } @Test - public void testJUnit44DepWithSneaky381() - throws Exception + public void testJUnit44DepWithSneaky381() throws Exception { unpack().debugLogging().sysProp( "junit-dep.version", "4.4" ).activateProfile( - "provided381" ).executeTest().verifyErrorFree( 1 ); + "provided381" ).executeTest().verifyErrorFree( 1 ); } @Test - public void testJUnit47Dep() - throws Exception + public void testJUnit47Dep() throws Exception { - unpack().debugLogging().sysProp( "junit-dep.version", "4.7" ).executeTest().verifyErrorFree( 1 ).verifyTextInLog( - "surefire-junit47" ); + unpack().debugLogging().sysProp( "junit-dep.version", "4.7" ).executeTest().verifyErrorFree( + 1 ).verifyTextInLog( "surefire-junit47" ); } @Test - public void testJUnit48Dep() - throws Exception + public void testJUnit48Dep() throws Exception { - unpack().debugLogging().sysProp( "junit-dep.version", "4.8" ).executeTest().verifyErrorFree( 1 ).verifyTextInLog( - "surefire-junit47" ); + unpack().debugLogging().sysProp( "junit-dep.version", "4.8" ).executeTest().verifyErrorFree( + 1 ).verifyTextInLog( "surefire-junit47" ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java index 332cbb9e6d..f0cf023bd0 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java @@ -19,13 +19,13 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.it.VerificationException; import org.apache.maven.surefire.its.fixture.OutputValidator; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; @@ -36,34 +36,45 @@ import static org.apache.maven.surefire.its.fixture.IsRegex.regex; import static org.fest.assertions.Assertions.assertThat; import static org.fest.util.Collections.set; +import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.startsWith; import static org.junit.Assert.assertThat; -@RunWith( Parameterized.class ) -public class JUnitPlatformEnginesIT - extends SurefireJUnit4IntegrationTestCase +/** + * + */ +@RunWith( ParallelParameterized.class ) +@SuppressWarnings( "checkstyle:magicnumber" ) +public class JUnitPlatformEnginesIT extends SurefireJUnit4IntegrationTestCase { @Parameter + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String platform; @Parameter( 1 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String jupiter; @Parameter( 2 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String opentest; @Parameter( 3 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String apiguardian; - @Parameters(name = "{0}") - public static Iterable regexVersions() + @Parameters( name = "{0}" ) + public static Iterable artifactVersions() { - ArrayList args = new ArrayList(); - args.add( new Object[] { "1.0.0", "5.0.0", "1.0.0", "1.0.0" } ); - args.add( new Object[] { "1.1.1", "5.1.1", "1.0.0", "1.0.0" } ); - args.add( new Object[] { "1.2.0", "5.2.0", "1.1.0", "1.0.0" } ); - args.add( new Object[] { "1.3.1", "5.3.1", "1.1.1", "1.0.0" } ); - args.add( new Object[] { "1.4.0-SNAPSHOT", "5.4.0-SNAPSHOT", "1.1.1", "1.0.0" } ); + ArrayList args = new ArrayList<>(); + args.add( new Object[] {"1.0.3", "5.0.3", "1.0.0", "1.0.0"} ); + args.add( new Object[] {"1.1.1", "5.1.1", "1.0.0", "1.0.0"} ); + args.add( new Object[] {"1.2.0", "5.2.0", "1.1.0", "1.0.0"} ); + args.add( new Object[] {"1.3.2", "5.3.2", "1.1.1", "1.0.0"} ); + args.add( new Object[] {"1.4.2", "5.4.2", "1.1.1", "1.0.0"} ); + args.add( new Object[] {"1.5.2", "5.5.2", "1.2.0", "1.1.0"} ); + args.add( new Object[] {"1.6.0-M1", "5.6.0-M1", "1.2.0", "1.1.0"} ); + //args.add( new Object[] { "1.6.0-SNAPSHOT", "5.6.0-SNAPSHOT", "1.2.0", "1.1.0" } ); return args; } @@ -77,8 +88,7 @@ public void setUp() public void testToRegex() { String regex = toRegex( ".[]()*" ); - assertThat( regex ) - .isEqualTo( "\\.\\[\\]\\(\\).*" ); + assertThat( regex ).isEqualTo( "\\.\\[\\]\\(\\).*" ); } @Test @@ -90,67 +100,64 @@ public void platform() throws VerificationException .executeTest() .verifyErrorFree( 1 ); - String testClasspath = "[DEBUG] test(compact) classpath:" - + " test-classes" - + " classes" - + " junit-jupiter-engine-" + jupiter + ".jar" - + " apiguardian-api-" + apiguardian + ".jar" - + " junit-platform-engine-" + platform + ".jar" - + " junit-platform-commons-" + platform + ".jar" - + " opentest4j-" + opentest + ".jar" - + " junit-jupiter-api-" + jupiter + ".jar"; - List lines = validator.loadLogLines( startsWith( "[DEBUG] test(compact) classpath" ) ); - assertThat( lines ) - .hasSize( 1 ); + assertThat( lines ).hasSize( 1 ); String line = lines.get( 0 ); - assertThat( set( line ), regex( toRegex( testClasspath ) ) ); - - String providerClasspath = "[DEBUG] provider(compact) classpath:" - + " surefire-junit-platform-*.jar" - + " surefire-api-*.jar" - + " surefire-logger-api-*.jar" - + " common-java5-*.jar" - + " junit-platform-launcher-1.3.1.jar"; + assertThat( set( line ), allOf( + regex( toRegex( "*[DEBUG] test(compact) classpath:*" ) ), + regex( toRegex( "* test-classes*" ) ), + regex( toRegex( "* classes*" ) ), + regex( toRegex( "*junit-jupiter-engine-" + jupiter + ".jar*" ) ), + regex( toRegex( "*apiguardian-api-" + apiguardian + ".jar*" ) ), + regex( toRegex( "*junit-platform-engine-" + platform + ".jar*" ) ), + regex( toRegex( "*junit-platform-commons-" + platform + ".jar*" ) ), + regex( toRegex( "*opentest4j-" + opentest + ".jar*" ) ), + regex( toRegex( "*junit-jupiter-api-" + jupiter + ".jar*" ) ) + ) ); lines = validator.loadLogLines( startsWith( "[DEBUG] provider(compact) classpath" ) ); - assertThat( lines ) - .hasSize( 1 ); + assertThat( lines ).hasSize( 1 ); line = lines.get( 0 ); - assertThat( set( line ), regex( toRegex( providerClasspath ) ) ); - - String bootClasspath = "[DEBUG] boot(compact) classpath:" - + " surefire-booter-*.jar" - + " surefire-api-*.jar" - + " surefire-logger-api-*.jar" - + " test-classes" - + " classes" - + " junit-jupiter-engine-" + jupiter + ".jar" - + " apiguardian-api-" + apiguardian + ".jar" - + " junit-platform-engine-" + platform + ".jar" - + " junit-platform-commons-" + platform + ".jar" - + " opentest4j-" + opentest + ".jar" - + " junit-jupiter-api-" + jupiter + ".jar" - + " surefire-junit-platform-*.jar" - + " junit-platform-launcher-1.3.1.jar"; + assertThat( set( line ), allOf( + regex( toRegex( "*[DEBUG] provider(compact) classpath:*" ) ), + regex( toRegex( "*surefire-junit-platform-*.jar*" ) ), + regex( toRegex( "*surefire-api-*.jar*" ) ), + regex( toRegex( "*surefire-logger-api-*.jar*" ) ), + regex( toRegex( "*common-java5-*.jar*" ) ), + regex( toRegex( "*junit-platform-launcher-" + platform + ".jar*" ) ) + ) ); lines = validator.loadLogLines( startsWith( "[DEBUG] boot(compact) classpath" ) ); - assertThat( lines ) - .hasSize( 1 ); + assertThat( lines ).hasSize( 1 ); line = lines.get( 0 ); - assertThat( set( line ), regex( toRegex( bootClasspath ) ) ); + assertThat( set( line ), allOf( + regex( toRegex( "*[DEBUG] boot(compact) classpath:*" ) ), + regex( toRegex( "*surefire-booter-*.jar*" ) ), + regex( toRegex( "*surefire-api-*.jar*" ) ), + regex( toRegex( "*surefire-logger-api-*.jar*" ) ), + regex( toRegex( "* test-classes*" ) ), + regex( toRegex( "* classes*" ) ), + regex( toRegex( "*junit-jupiter-engine-" + jupiter + ".jar*" ) ), + regex( toRegex( "*apiguardian-api-" + apiguardian + ".jar*" ) ), + regex( toRegex( "*junit-platform-engine-" + platform + ".jar*" ) ), + regex( toRegex( "*junit-platform-commons-" + platform + ".jar*" ) ), + regex( toRegex( "*opentest4j-" + opentest + ".jar*" ) ), + regex( toRegex( "*junit-jupiter-api-" + jupiter + ".jar*" ) ), + regex( toRegex( "*surefire-junit-platform-*.jar*" ) ), + regex( toRegex( "*junit-platform-launcher-" + platform + ".jar*" ) ) ) ); } - private static String toRegex(String text) { + private static String toRegex( String text ) + { return text.replaceAll( "\\.", "\\\\." ) .replaceAll( "\\[", "\\\\[" ) .replaceAll( "]", "\\\\]" ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformIT.java index 6c8d29d53c..765d1a71a7 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformIT.java @@ -19,15 +19,57 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; +import org.apache.maven.surefire.its.fixture.OutputValidator; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import java.util.ArrayList; + +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaVersion; +/** + * + */ +@RunWith( ParallelParameterized.class ) +@SuppressWarnings( "checkstyle:magicnumber" ) public class JUnitPlatformIT extends SurefireJUnit4IntegrationTestCase { + private static final String XML_TESTSUITE_FRAGMENT = + " artifactVersions() + { + ArrayList args = new ArrayList<>(); + args.add( new Object[] { "5.2.0", "0.8.0" } ); + args.add( new Object[] { "5.3.0", "0.8.15" } ); + args.add( new Object[] { "5.3.2", "0.9.0" } ); + args.add( new Object[] { "5.4.0", "0.9.3" } ); + args.add( new Object[] { "5.4.2", "1.0.0" } ); + args.add( new Object[] { "5.5.0", "1.1.0" } ); + args.add( new Object[] { "5.5.2", "1.1.0" } ); + args.add( new Object[] { "5.6.0-M1", "1.1.0" } ); + //args.add( new Object[] { "5.6.0-SNAPSHOT", "1.1.6" } ); + return args; + } + @Before public void setUp() { @@ -37,15 +79,68 @@ public void setUp() @Test public void testJupiterEngine() { - unpack( "/junit-platform-engine-jupiter" ) + unpack( "junit-platform-engine-jupiter", "-" + junit5Version + "-" + jqwikVersion ) + .setTestToRun( "Basic*Test" ) + .sysProp( "junit5.version", junit5Version ) + .sysProp( "jqwik.version", jqwikVersion ) .executeTest() .verifyErrorFree( 5 ); } + @Test + public void testJupiterEngineWithDisplayNames() + { + OutputValidator validator = unpack( "junit-platform-engine-jupiter", "-" + junit5Version + "-" + jqwikVersion ) + .sysProp( "junit5.version", junit5Version ) + .sysProp( "jqwik.version", jqwikVersion ) + .executeTest() + .verifyErrorFree( 7 ); + + validator.getSurefireReportsFile( "junitplatformenginejupiter.DisplayNameTest.txt", UTF_8 ) + .assertContainsText( "<< ✨ >>" ); + + validator.getSurefireReportsFile( "junitplatformenginejupiter.DisplayNameTest.txt", UTF_8 ) + .assertContainsText( "Test set: << ✨ >>" ); + + validator.getSurefireReportsFile( "junitplatformenginejupiter.DisplayNameTest.txt", UTF_8 ) + .assertContainsText( " - in << ✨ >>" ); + + + validator.getSurefireReportsFile( "junitplatformenginejupiter.DisplayNameTest-output.txt", UTF_8 ) + .assertContainsText( "<< ✨ >>" ); + + validator.getSurefireReportsFile( "junitplatformenginejupiter.DisplayNameTest-output.txt", UTF_8 ) + .assertContainsText( "73$71 ✔" ); + + validator.getSurefireReportsFile( "junitplatformenginejupiter.DisplayNameTest-output.txt", UTF_8 ) + .assertContainsText( "73$72 ✔" ); + + + validator.getSurefireReportsFile( "TEST-junitplatformenginejupiter.DisplayNameTest.xml", UTF_8 ) + .assertContainsText( "testcase name=\"73$71 ✔\" classname=\"<< ✨ >>\"" ) + .assertContainsText( "testcase name=\"73$72 ✔\" classname=\"<< ✨ >>\"" ) + .assertContainsText( XML_TESTSUITE_FRAGMENT ); + + + validator.getSurefireReportsFile( "TEST-junitplatformenginejupiter.BasicJupiterTest.xml", UTF_8 ) + .assertContainsText( "Qingzhou Luo + * @author Matt Coley + */ +@SuppressWarnings( "checkstyle:magicnumber" ) +public class JUnitPlatformRerunFailingTestsIT extends SurefireJUnit4IntegrationTestCase +{ + private static final String VERSION = "5.5.1"; + + private SurefireLauncher unpack() + { + return unpack( "/junit-platform-rerun-failing-tests" ); + } + + @Before + public void setup() + { + assumeJavaVersion( 1.8 ); + } + + @Test + public void testRerunFailingErrorTestsWithOneRetry() + { + OutputValidator outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ) + .withFailure() + .debugLogging() + .executeTest() + .assertTestSuiteResults( 5, 1, 1, 0, 0 ); + verifyFailuresOneRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().debugLogging().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( + "-DforkCount=2" ).withFailure().executeTest().assertTestSuiteResults( 5, 1, 1, 0, 0 ); + verifyFailuresOneRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().debugLogging().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( "-Dparallel=methods" ).addGoal( + "-DuseUnlimitedThreads=true" ).withFailure().executeTest().assertTestSuiteResults( 5, 1, 1, 0, 0 ); + verifyFailuresOneRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().debugLogging().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( "-Dparallel=classes" ).addGoal( + "-DuseUnlimitedThreads=true" ).withFailure().executeTest().assertTestSuiteResults( 5, 1, 1, 0, 0 ); + verifyFailuresOneRetryAllClasses( outputValidator ); + } + + @Test + public void testRerunFailingErrorTestsTwoRetry() + { + // Four flakes, both tests have been re-run twice + OutputValidator outputValidator = unpack().setJUnitVersion( VERSION ).maven().debugLogging().addGoal( + "-Dsurefire.rerunFailingTestsCount=2" ).executeTest().assertTestSuiteResults( 5, 0, 0, 0, 4 ); + + verifyFailuresTwoRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().debugLogging().addGoal( + "-Dsurefire.rerunFailingTestsCount=2" ).addGoal( "-DforkCount=3" ).executeTest().assertTestSuiteResults( + 5, 0, 0, 0, 4 ); + + verifyFailuresTwoRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().debugLogging().addGoal( + "-Dsurefire.rerunFailingTestsCount=2" ).addGoal( "-Dparallel=methods" ).addGoal( + "-DuseUnlimitedThreads=true" ).executeTest().assertTestSuiteResults( 5, 0, 0, 0, 4 ); + + verifyFailuresTwoRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().debugLogging().addGoal( + "-Dsurefire.rerunFailingTestsCount=2" ).addGoal( "-Dparallel=classes" ).addGoal( + "-DuseUnlimitedThreads=true" ).executeTest().assertTestSuiteResults( 5, 0, 0, 0, 4 ); + + verifyFailuresTwoRetryAllClasses( outputValidator ); + } + + @Test + public void testRerunFailingErrorTestsFalse() + { + OutputValidator outputValidator = unpack().setJUnitVersion( + VERSION ).maven().withFailure().debugLogging().executeTest().assertTestSuiteResults( 5, 1, 1, 0, 0 ); + + verifyFailuresNoRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-DforkCount=3" ).withFailure().debugLogging().executeTest().assertTestSuiteResults( 5, 1, 1, 0, 0 ); + + verifyFailuresNoRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( "-Dparallel=methods" ).addGoal( + "-DuseUnlimitedThreads=true" ).withFailure().debugLogging().executeTest().assertTestSuiteResults( 5, 1, + 1, 0, 0 ); + + verifyFailuresNoRetryAllClasses( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( "-Dparallel=classes" ).addGoal( + "-DuseUnlimitedThreads=true" ).withFailure().debugLogging().executeTest().assertTestSuiteResults( 5, 1, + 1, 0, 0 ); + + verifyFailuresNoRetryAllClasses( outputValidator ); + } + + @Test + public void testRerunOneTestClass() + { + OutputValidator outputValidator = unpack().setJUnitVersion( VERSION ).maven().debugLogging().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( + "-Dtest=FlakyFirstTimeTest" ).withFailure().executeTest().assertTestSuiteResults( 3, 1, 1, 0, 0 ); + + verifyFailuresOneRetryOneClass( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( "-DforkCount=3" ).addGoal( + "-Dtest=FlakyFirstTimeTest" ).withFailure().debugLogging().executeTest().assertTestSuiteResults( 3, 1, + 1, 0, 0 ); + + verifyFailuresOneRetryOneClass( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( "-Dparallel=methods" ).addGoal( + "-DuseUnlimitedThreads=true" ).addGoal( + "-Dtest=FlakyFirstTimeTest" ).withFailure().debugLogging().executeTest().assertTestSuiteResults( 3, 1, + 1, 0, 0 ); + + verifyFailuresOneRetryOneClass( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( "-Dparallel=classes" ).addGoal( + "-DuseUnlimitedThreads=true" ).addGoal( + "-Dtest=FlakyFirstTimeTest" ).withFailure().debugLogging().executeTest().assertTestSuiteResults( 3, 1, + 1, 0, 0 ); + + verifyFailuresOneRetryOneClass( outputValidator ); + } + + @Test + public void testRerunOneTestMethod() + { + OutputValidator outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( + "-Dtest=FlakyFirstTimeTest#testFailing*" ).withFailure().debugLogging().executeTest() + .assertTestSuiteResults( 1, 0, 1, 0, 0 ); + + verifyFailuresOneRetryOneMethod( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( "-DforkCount=3" ).addGoal( + "-Dtest=FlakyFirstTimeTest#testFailing*" ).withFailure().debugLogging().executeTest() + .assertTestSuiteResults( 1, 0, 1, 0, 0 ); + + verifyFailuresOneRetryOneMethod( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( "-Dparallel=methods" ).addGoal( + "-DuseUnlimitedThreads=true" ).addGoal( + "-Dtest=FlakyFirstTimeTest#testFailing*" ) + .withFailure() + .debugLogging() + .executeTest() + .assertTestSuiteResults( 1, 0, 1, 0, 0 ); + + verifyFailuresOneRetryOneMethod( outputValidator ); + + outputValidator = unpack().setJUnitVersion( VERSION ).maven().addGoal( + "-Dsurefire.rerunFailingTestsCount=1" ).addGoal( "-Dparallel=classes" ).addGoal( + "-DuseUnlimitedThreads=true" ).addGoal( + "-Dtest=FlakyFirstTimeTest#testFailing*" ) + .withFailure() + .debugLogging() + .executeTest() + .assertTestSuiteResults( 1, 0, 1, 0, 0 ); + + verifyFailuresOneRetryOneMethod( outputValidator ); + } + + private void verifyFailuresOneRetryAllClasses( OutputValidator outputValidator ) + { + verifyFailuresOneRetry( outputValidator, 5, 1, 1, 0 ); + } + + private void verifyFailuresTwoRetryAllClasses( OutputValidator outputValidator ) + { + verifyFailuresTwoRetry( outputValidator, 5, 0, 0, 2 ); + } + + private void verifyFailuresNoRetryAllClasses( OutputValidator outputValidator ) + { + verifyFailuresNoRetry( outputValidator, 5, 1, 1, 0 ); + } + + private void verifyFailuresOneRetryOneClass( OutputValidator outputValidator ) + { + verifyFailuresOneRetry( outputValidator, 3, 1, 1, 0 ); + } + + private void verifyFailuresOneRetryOneMethod( OutputValidator outputValidator ) + { + verifyOnlyFailuresOneRetry( outputValidator, 1, 1, 0, 0 ); + } + + private void verifyFailuresOneRetry( OutputValidator outputValidator, int run, int failures, int errors, + int flakes ) + { + outputValidator.verifyTextInLog( "Failures:" ); + outputValidator.verifyTextInLog( "Run 1: FlakyFirstTimeTest.testFailingTestOne" ); + outputValidator.verifyTextInLog( "Run 2: FlakyFirstTimeTest.testFailingTestOne" ); + + outputValidator.verifyTextInLog( "Errors:" ); + outputValidator.verifyTextInLog( "Run 1: FlakyFirstTimeTest.testErrorTestOne" ); + outputValidator.verifyTextInLog( "Run 2: FlakyFirstTimeTest.testErrorTestOne" ); + + verifyStatistics( outputValidator, run, failures, errors, flakes ); + } + + private void verifyOnlyFailuresOneRetry( OutputValidator outputValidator, int run, int failures, int errors, + int flakes ) + { + outputValidator.verifyTextInLog( "Failures:" ); + outputValidator.verifyTextInLog( "Run 1: FlakyFirstTimeTest.testFailingTestOne" ); + outputValidator.verifyTextInLog( "Run 2: FlakyFirstTimeTest.testFailingTestOne" ); + + verifyStatistics( outputValidator, run, failures, errors, flakes ); + } + + private void verifyFailuresTwoRetry( OutputValidator outputValidator, int run, int failures, int errors, + int flakes ) + { + outputValidator.verifyTextInLog( "Flakes:" ); + outputValidator.verifyTextInLog( "Run 1: FlakyFirstTimeTest.testFailingTestOne" ); + outputValidator.verifyTextInLog( "Run 2: FlakyFirstTimeTest.testFailingTestOne" ); + outputValidator.verifyTextInLog( "Run 3: PASS" ); + + outputValidator.verifyTextInLog( "Run 1: FlakyFirstTimeTest.testErrorTestOne" ); + outputValidator.verifyTextInLog( "Run 2: FlakyFirstTimeTest.testErrorTestOne" ); + + verifyStatistics( outputValidator, run, failures, errors, flakes ); + } + + private void verifyFailuresNoRetry( OutputValidator outputValidator, int run, int failures, int errors, int flakes ) + { + outputValidator.verifyTextInLog( "Failures:" ); + outputValidator.verifyTextInLog( "junitplatform.FlakyFirstTimeTest.testFailingTestOne" ); + outputValidator.verifyTextInLog( "ERROR" ); + outputValidator.verifyTextInLog( "junitplatform.FlakyFirstTimeTest.testErrorTestOne" ); + + verifyStatistics( outputValidator, run, failures, errors, flakes ); + } + + private void verifyStatistics( OutputValidator outputValidator, int run, int failures, int errors, int flakes ) + { + if ( flakes > 0 ) + { + outputValidator.verifyTextInLog( + "Tests run: " + run + ", Failures: " + failures + ", Errors: " + errors + ", Skipped: 0, Flakes: " + + flakes ); + } + else + { + outputValidator.verifyTextInLog( + "Tests run: " + run + ", Failures: " + failures + ", Errors: " + errors + ", Skipped: 0" ); + } + } +} diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformStreamCorruptionIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformStreamCorruptionIT.java index 00a556c744..baa557d26f 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformStreamCorruptionIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformStreamCorruptionIT.java @@ -31,6 +31,10 @@ import static org.fest.assertions.Assertions.assertThat; import static org.hamcrest.CoreMatchers.startsWith; +/** + * + */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class JUnitPlatformStreamCorruptionIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitVersion.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitVersion.java index 9549016fb6..522e0625d2 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitVersion.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitVersion.java @@ -24,7 +24,8 @@ /** * Enum listing all the JUnit version. */ -public enum JUnitVersion { +public enum JUnitVersion +{ JUNIT_4_0( "4.0" ), JUNIT_4_1( "4.1" ), diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/Java9FullApiIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/Java9FullApiIT.java index 1ceebb0922..37b784b0e8 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/Java9FullApiIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/Java9FullApiIT.java @@ -26,7 +26,6 @@ import static org.apache.maven.surefire.its.fixture.SurefireLauncher.EXT_JDK_HOME; import static org.apache.maven.surefire.its.fixture.SurefireLauncher.EXT_JDK_HOME_KEY; -import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; @@ -43,9 +42,10 @@ public class Java9FullApiIT private static final String JVM_SPEC_VERSION = System.getProperty( "java.specification.version" ); @Test + @SuppressWarnings( "checkstyle:methodname" ) public void shouldLoadMultipleJavaModules_JavaHome() throws Exception { - OutputValidator validator = assumeJigsaw() + OutputValidator validator = assumeJava9() .setForkJvm() .debugLogging() .execute( "verify" ) @@ -61,6 +61,7 @@ public void shouldLoadMultipleJavaModules_JavaHome() throws Exception } @Test + @SuppressWarnings( "checkstyle:methodname" ) public void shouldLoadMultipleJavaModules_JvmParameter() throws Exception { OutputValidator validator = assumeJava9Property() @@ -80,6 +81,7 @@ public void shouldLoadMultipleJavaModules_JvmParameter() throws Exception } @Test + @SuppressWarnings( "checkstyle:methodname" ) public void shouldLoadMultipleJavaModules_ToolchainsXML() throws Exception { OutputValidator validator = assumeJava9Property() diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/ModulePathIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/ModulePathIT.java index dedd0dbb29..5a716cadf1 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/ModulePathIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/ModulePathIT.java @@ -23,6 +23,9 @@ import java.io.IOException; +/** + * + */ public class ModulePathIT extends AbstractJigsawIT { @@ -32,7 +35,7 @@ public class ModulePathIT public void testModulePath() throws IOException { - assumeJigsaw() + assumeJava9() .debugLogging() .executeTest() .verifyErrorFreeLog() @@ -44,7 +47,7 @@ public void testModulePathWithSpaces() throws IOException { suffix = " with spaces"; - assumeJigsaw() + assumeJava9() .debugLogging() .executeTest() .verifyErrorFreeLog() diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/PlexusConflictIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/PlexusConflictIT.java index bec3e9972b..1df2e7eeb3 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/PlexusConflictIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/PlexusConflictIT.java @@ -40,7 +40,7 @@ public void testPlexusConflict() @Test public void testPlexusConflictIsolatedClassLoader() { - unpack().useSystemClassLoader(false).executeTest().verifyErrorFree( 1 ); + unpack().useSystemClassLoader( false ).executeTest().verifyErrorFree( 1 ); } private SurefireLauncher unpack() diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/PojoSimpleIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/PojoSimpleIT.java index 03902ef77d..6905730903 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/PojoSimpleIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/PojoSimpleIT.java @@ -19,9 +19,13 @@ * under the License. */ +import org.apache.maven.it.VerificationException; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Test; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; + /** * Test support for POJO tests. * @@ -31,8 +35,14 @@ public class PojoSimpleIT extends SurefireJUnit4IntegrationTestCase { @Test - public void testit() + public void twoTestsWithFixtures() throws VerificationException { - unpack( "pojo-simple" ).executeTest().assertTestSuiteResults( 2, 0, 1, 0 ); + unpack( "pojo-simple" ) + .executeTest() + .assertTestSuiteResults( 2, 0, 1, 0 ) + .assertThatLogLine( containsString( "setUp called 1" ), is( 1 ) ) + .assertThatLogLine( containsString( "setUp called 2" ), is( 1 ) ) + .assertThatLogLine( containsString( "tearDown called 1" ), is( 1 ) ) + .assertThatLogLine( containsString( "tearDown called 2" ), is( 1 ) ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/ReporterTime.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/ReporterTime.java index 154fb733e5..d6a69d03aa 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/ReporterTime.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/ReporterTime.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.its; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/ResultCountingIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/ResultCountingIT.java index 714d0c4527..034e1148e1 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/ResultCountingIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/ResultCountingIT.java @@ -32,6 +32,7 @@ * * @author Kristian Rosenvold */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class ResultCountingIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java index 099aa0761c..d2031fa7f2 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderIT.java @@ -19,7 +19,6 @@ * under the License. */ -import java.io.IOException; import java.util.Calendar; import org.apache.maven.it.VerificationException; import org.apache.maven.surefire.its.fixture.OutputValidator; @@ -78,8 +77,13 @@ public void testHourly() public void testNonExistingRunOrder() throws Exception { - unpack().forkMode( getForkMode() ).runOrder( "nonExistingRunOrder" ).maven().withFailure().executeTest().verifyTextInLog( - "There's no RunOrder with the name nonExistingRunOrder." ); + unpack() + .forkMode( getForkMode() ) + .runOrder( "nonExistingRunOrder" ) + .maven() + .withFailure() + .executeTest() + .verifyTextInLog( "There's no RunOrder with the name nonExistingRunOrder." ); } private OutputValidator executeWithRunOrder( String runOrder ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java index 72fc4286be..5694ae3b54 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/RunOrderParallelForksIT.java @@ -19,6 +19,9 @@ * under the License. */ +/** + * + */ public class RunOrderParallelForksIT extends RunOrderIT { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/SmartStackTraceIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/SmartStackTraceIT.java index b98155e0fb..2c29bc1ec4 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/SmartStackTraceIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/SmartStackTraceIT.java @@ -37,8 +37,10 @@ public void misg() throws Exception { OutputValidator outputValidator = unpack( "/junit48-smartStackTrace" ).maven().withFailure().executeTest(); - outputValidator.verifyTextInLog( "SmartStackTraceTest.shouldFailInMethodButDoesnt Expected exception: java.lang.RuntimeException" ); - outputValidator.verifyTextInLog( "SmartStackTraceTest.shortName Expected exception: java.io.IOException" ); + outputValidator.verifyTextInLog( + "SmartStackTraceTest.shouldFailInMethodButDoesnt Expected exception: java.lang.RuntimeException" ); + outputValidator.verifyTextInLog( + "SmartStackTraceTest.shortName Expected exception: java.io.IOException" ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/Surefire1602IT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/Surefire1602IT.java index d26bd4ad63..8ce773273d 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/Surefire1602IT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/Surefire1602IT.java @@ -19,7 +19,6 @@ * under the License. */ -import org.apache.maven.surefire.its.fixture.OutputValidator; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java index d490ce56ab..ff2c1471ad 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java @@ -19,17 +19,18 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.surefire.its.fixture.Settings; import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import java.util.Arrays; /** * JUnit test project using multiple method patterns, including wildcards in class and method names. */ -@RunWith( Parameterized.class ) +@RunWith( ParallelParameterized.class ) public class TestMultipleMethodPatternsIT extends AbstractTestMultipleMethodPatterns { @@ -40,7 +41,7 @@ public TestMultipleMethodPatternsIT( Settings settings ) this.settings = settings; } - @Parameterized.Parameters + @Parameters public static Iterable data() { return Arrays.asList( new Object[][]{ diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsTestNGIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsTestNGIT.java index 2de3670927..0ea902ecff 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsTestNGIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsTestNGIT.java @@ -19,17 +19,18 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.surefire.its.fixture.Settings; import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import java.util.Arrays; /** * TestNG test project using multiple method patterns, including wildcards in class and method names. */ -@RunWith( Parameterized.class ) +@RunWith( ParallelParameterized.class ) public class TestMultipleMethodPatternsTestNGIT extends AbstractTestMultipleMethodPatterns { @@ -40,7 +41,7 @@ public TestMultipleMethodPatternsTestNGIT( Settings settings ) this.settings = settings; } - @Parameterized.Parameters + @Parameters public static Iterable data() { return Arrays.asList( new Object[][]{ diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/TestNgSuccessPercentageIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/TestNgSuccessPercentageIT.java index 3b12e03567..1be72f4b07 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/TestNgSuccessPercentageIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/TestNgSuccessPercentageIT.java @@ -30,16 +30,17 @@ * @author Jon Todd * @author Andreas Gudian */ -public class TestNgSuccessPercentageIT extends SurefireJUnit4IntegrationTestCase { +public class TestNgSuccessPercentageIT extends SurefireJUnit4IntegrationTestCase +{ @Test public void testPassesWhenFailuresLessThanSuccessPercentage() { - OutputValidator validator = unpack("/testng-succes-percentage") + OutputValidator validator = unpack( "/testng-succes-percentage" ) .sysProp( "testNgVersion", "5.7" ) .sysProp( "testNgClassifier", "jdk15" ) .mavenTestFailureIgnore( true ) .executeTest(); - validator.assertTestSuiteResults(8, 0, 1, 0); + validator.assertTestSuiteResults( 8, 0, 1, 0 ); } } \ No newline at end of file diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/TestSingleMethodIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/TestSingleMethodIT.java index 24dd8f4d81..3b20ea2639 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/TestSingleMethodIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/TestSingleMethodIT.java @@ -124,8 +124,8 @@ public void fullyQualifiedJunit48Provider4() public void fullyQualifiedJunit48Provider47() throws Exception { - singleMethod("junit48-single-method", Collections.emptyMap(), - "junit4.BasicTest#testSuccessOne", "-P surefire-junit47"); + singleMethod( "junit48-single-method", Collections.emptyMap(), + "junit4.BasicTest#testSuccessOne", "-P surefire-junit47" ); } @Test diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/TwoTestCasesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/TwoTestCasesIT.java index 61b5517198..23e6dd08c3 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/TwoTestCasesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/TwoTestCasesIT.java @@ -23,7 +23,10 @@ import java.util.List; import java.util.Set; import org.apache.maven.plugins.surefire.report.ReportTestSuite; -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.HelperAssertions; +import org.apache.maven.surefire.its.fixture.IntegrationTestSuiteResults; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/UmlautDirIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/UmlautDirIT.java index 7b008bcd94..e0095e0dd4 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/UmlautDirIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/UmlautDirIT.java @@ -19,28 +19,112 @@ * under the License. */ -import org.apache.maven.it.VerificationException; +import org.apache.maven.shared.utils.io.FileUtils; import org.apache.maven.surefire.its.fixture.MavenLauncher; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static java.nio.file.Files.copy; +import static java.nio.file.Files.createDirectories; +import static java.nio.file.Files.exists; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang3.SystemUtils.IS_OS_LINUX; +import static org.junit.Assume.assumeTrue; /** * Test a directory with an umlaut * * @author Dan Fabulich */ -public class UmlautDirIT - extends SurefireJUnit4IntegrationTestCase +public class UmlautDirIT extends SurefireJUnit4IntegrationTestCase { + private String localRepo; + + @Before + public void backupLocalRepo() + { + localRepo = System.getProperty( "maven.repo.local" ); + } + + @After + public void restoreLocalRepo() + { + if ( localRepo == null ) + { + System.clearProperty( "maven.repo.local" ); + } + else + { + System.setProperty( "maven.repo.local", localRepo ); + } + } + + @Test + public void surefire1617WithColonInLocalRepo() + throws Exception + { + assumeTrue( IS_OS_LINUX ); + + unpack( "junit-pathWithUmlaut", "_compiled" ) + .maven() + .execute( "compiler:testCompile" ); + + String cwd = System.getProperty( "user.dir" ); + + Path from = Paths.get( cwd, "target", "UmlautDirIT_surefire1617WithColonInLocalRepo_compiled", "target", + "test-classes", "umlautTest" ); + + Path to = Paths.get( cwd, "target", "UmlautDirIT_surefire1617WithColonInLocalRepo", "target", + "test-classes", "umlautTest" ); + + MavenLauncher mavenLauncher = unpackWithColonInLocalRepo() + .maven(); + + mavenLauncher.setForkJvm( true ); + mavenLauncher.setAutoclean( false ); + + if ( !Files.exists( to ) ) + { + Files.createDirectories( to ); + } + + FileUtils.copyDirectory( from.toFile(), to.toFile() ); + + mavenLauncher.sysProp( "skipCompiler", true ) + .debugLogging() + .executeTest() + .verifyErrorFreeLog() + .assertTestSuiteResults( 1, 0, 0, 0 ); + } + + @Test + public void surefire1617WithColonInProjectDir() + throws Exception + { + assumeTrue( IS_OS_LINUX ); + unpackWithNewProjectDirectory( "this is: a test", "_surefire-1617" ) + .setForkJvm() + .sysProp( "argLine", "-Dpath.separator=;" ) + .executeTest() + .verifyErrorFreeLog() + .assertTestSuiteResults( 1, 0, 0, 0 ); + } + @Test public void testUmlaut() throws Exception { - specialUnpack( "1" ) + unpackWithNewProjectDirectory( "/junit-pathWith\u00DCmlaut_", "1" ) .executeTest() .verifyErrorFreeLog() .assertTestSuiteResults( 1, 0, 0, 0 ); @@ -50,20 +134,59 @@ public void testUmlaut() public void testUmlautIsolatedClassLoader() throws Exception { - specialUnpack( "2" ) + unpackWithNewProjectDirectory( "/junit-pathWith\u00DCmlaut_", "2" ) .useSystemClassLoader( false ) .executeTest() .assertTestSuiteResults( 1, 0, 0, 0 ); } - SurefireLauncher specialUnpack( String postfix ) - throws IOException + private SurefireLauncher unpackWithNewProjectDirectory( String projectDirectory, String postfix ) + throws IOException { SurefireLauncher unpack = unpack( "junit-pathWithUmlaut" ); MavenLauncher maven = unpack.maven(); - File dest = new File( maven.getUnpackedAt().getParentFile().getPath(), "/junit-pathWith\u00DCmlaut_" + postfix ); + File dest = new File( maven.getUnpackedAt().getParentFile().getPath(), projectDirectory + postfix ); maven.moveUnpackTo( dest ); return unpack; } + + private SurefireLauncher unpackWithColonInLocalRepo() + throws IOException + { + String newLocalRepo = + Paths.get( System.getProperty( "user.dir" ), "target", "local repo for: SUREFIRE-1617" ).toString(); + String defaultLocalRepo = new MavenLauncher( getClass(), "junit-pathWithUmlaut", null ).getLocalRepository(); + + copyFolder( Paths.get( defaultLocalRepo, "org", "apache", "maven", "surefire" ), + Paths.get( newLocalRepo, "org", "apache", "maven", "surefire" ) ); + + copyFolder( Paths.get( defaultLocalRepo, "org", "apache", "maven", "plugins", "maven-surefire-plugin" ), + Paths.get( newLocalRepo, "org", "apache", "maven", "plugins", "maven-surefire-plugin" ) ); + + System.setProperty( "maven.repo.local", newLocalRepo ); + return unpack( "junit-pathWithUmlaut" ); + } + + private static void copyFolder( Path src, Path dest ) + throws IOException + { + if ( !exists( dest ) ) + { + createDirectories( dest ); + } + + for ( File from : requireNonNull( src.toFile().listFiles() ) ) + { + Path to = dest.resolve( from.getName() ); + if ( from.isDirectory() ) + { + copyFolder( from.toPath(), to ); + } + else if ( from.isFile() ) + { + copy( from.toPath(), to, REPLACE_EXISTING ); + } + } + } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/UnicodeTestNamesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/UnicodeTestNamesIT.java index 3ce7336c71..57bc602d52 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/UnicodeTestNamesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/UnicodeTestNamesIT.java @@ -16,7 +16,7 @@ * "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 LicenseUni. + * under the License. */ import org.apache.maven.surefire.its.fixture.OutputValidator; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/WorkingDirectoryIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/WorkingDirectoryIT.java index 174ed1a623..f381950a2b 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/WorkingDirectoryIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/WorkingDirectoryIT.java @@ -24,7 +24,10 @@ import java.io.IOException; import java.util.Properties; import org.apache.maven.it.VerificationException; -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/WorkingDirectoryIsInvalidPropertyIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/WorkingDirectoryIsInvalidPropertyIT.java index 1415b6ef9e..8f0e0096f2 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/WorkingDirectoryIsInvalidPropertyIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/WorkingDirectoryIsInvalidPropertyIT.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.its; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/XmlReporterRunTimeIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/XmlReporterRunTimeIT.java index e8ee58b6df..539d6cfa0e 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/XmlReporterRunTimeIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/XmlReporterRunTimeIT.java @@ -35,6 +35,7 @@ * * @author Kristian Rosenvold */ +@SuppressWarnings( { "checkstyle:magicnumber", "checkstyle:linelength" } ) public class XmlReporterRunTimeIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/FailsafeOutputValidator.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/FailsafeOutputValidator.java index b96cf9bd60..19e1089959 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/FailsafeOutputValidator.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/FailsafeOutputValidator.java @@ -21,6 +21,9 @@ import org.apache.maven.it.VerificationException; +/** + * + */ public class FailsafeOutputValidator extends OutputValidator { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java index b8e63f2ca1..e4b8e84f57 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/HelperAssertions.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.its.fixture; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -30,10 +31,13 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; -import static org.apache.commons.io.Charsets.UTF_8; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.Assume.assumeTrue; -@SuppressWarnings( { "JavaDoc" } ) +/** + * + */ +@SuppressWarnings( {"JavaDoc"} ) public class HelperAssertions { /** @@ -45,7 +49,8 @@ public static void assertTestSuiteResults( int total, int errors, int failures, assertTestSuiteResults( total, errors, failures, skipped, suite ); } - public static void assertTestSuiteResults( int total, int errors, int failures, int skipped, int flakes, File testDir ) + public static void assertTestSuiteResults( int total, int errors, int failures, int skipped, int flakes, + File testDir ) { IntegrationTestSuiteResults suite = parseTestResults( testDir ); assertTestSuiteResults( total, errors, failures, skipped, flakes, suite ); @@ -90,7 +95,7 @@ public static void assertTestSuiteResults( int total, IntegrationTestSuiteResult public static void assertTestSuiteResults( int total, int errors, int failures, int skipped, int flakes, IntegrationTestSuiteResults actualSuite ) { - assertTestSuiteResults(total, errors, failures, skipped, actualSuite); + assertTestSuiteResults( total, errors, failures, skipped, actualSuite ); assertEquals( "wrong number of flaky tests", flakes, actualSuite.getFlakes() ); } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/IntegrationTestSuiteResults.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/IntegrationTestSuiteResults.java index f147281cbd..c2d77439f9 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/IntegrationTestSuiteResults.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/IntegrationTestSuiteResults.java @@ -19,7 +19,9 @@ * under the License. */ - +/** + * + */ public class IntegrationTestSuiteResults { private int total, errors, failures, skipped, flakes; @@ -34,7 +36,7 @@ public IntegrationTestSuiteResults( int total, int errors, int failures, int ski public IntegrationTestSuiteResults( int total, int errors, int failures, int skipped, int flakes ) { - this(total, errors, failures, skipped); + this( total, errors, failures, skipped ); this.flakes = flakes; } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/IsRegex.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/IsRegex.java index 09e8d0d235..59d9070607 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/IsRegex.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/IsRegex.java @@ -23,7 +23,6 @@ import org.hamcrest.Description; import org.hamcrest.Matcher; -import java.util.Collections; import java.util.Iterator; import java.util.Set; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java index c36da47691..d444e35c49 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/MavenLauncher.java @@ -77,7 +77,7 @@ public final class MavenLauncher resetCliOptions(); } - MavenLauncher( Class testClass, String resourceName, String suffix ) + public MavenLauncher( Class testClass, String resourceName, String suffix ) { this( testClass, resourceName, suffix, null ); } @@ -96,8 +96,7 @@ private File ensureUnpacked() return unpackedAt; } - public void moveUnpackTo( File dest ) - throws IOException + public void moveUnpackTo( File dest ) throws IOException { FileUtils.deleteDirectory( dest ); //noinspection ResultOfMethodCallIgnored @@ -159,8 +158,7 @@ public MavenLauncher getSubProjectLauncher( String subProject ) return mavenLauncher; } - public OutputValidator getSubProjectValidator( String subProject ) - throws VerificationException + public OutputValidator getSubProjectValidator( String subProject ) throws VerificationException { String subProjectBasedir = getValidator().getSubFile( subProject ).getAbsolutePath(); String settingsXml = settingsXmlPath().getAbsolutePath(); @@ -235,18 +233,17 @@ private void writeGoal( String newGoal ) { if ( newGoal != null && newGoal.startsWith( "-D" ) ) { - final String sysPropKey = - newGoal.contains( "=" ) ? newGoal.substring( 0, newGoal.indexOf( '=' ) ) : newGoal; + String sysPropKey = newGoal.contains( "=" ) ? newGoal.substring( 0, newGoal.indexOf( '=' ) ) : newGoal; - final String sysPropStarter = sysPropKey + "="; + String sysPropStarter = sysPropKey + "="; for ( ListIterator it = goals.listIterator(); it.hasNext(); ) { String goal = it.next(); if ( goal.equals( sysPropKey ) || goal.startsWith( sysPropStarter ) ) { - System.out.printf( "[WARNING] System property already exists '%s'. Overriding to '%s'.\n", - goal, newGoal ); + System.out.printf( "[WARNING] System property already exists '%s'. Overriding to '%s'.\n", goal, + newGoal ); it.set( newGoal ); return; } @@ -255,7 +252,7 @@ private void writeGoal( String newGoal ) goals.add( newGoal ); } - private OutputValidator conditionalExec(String goal) + private OutputValidator conditionalExec( String goal ) { OutputValidator verify; try @@ -372,10 +369,21 @@ public OutputValidator getValidator() return validator; } - public void setForkJvm( boolean forkJvm ) { + public void setForkJvm( boolean forkJvm ) + { getVerifier().setForkJvm( forkJvm ); } + public String getLocalRepository() + { + return getVerifier().getLocalRepository(); + } + + public void setAutoclean( boolean autoclean ) + { + getVerifier().setAutoclean( autoclean ); + } + private Verifier getVerifier() { if ( verifier == null ) @@ -393,7 +401,7 @@ private Verifier getVerifier() } return verifier; } - + private File simpleExtractResources( Class cl, String resourcePath ) { if ( !resourcePath.startsWith( "/" ) ) @@ -405,7 +413,8 @@ private File simpleExtractResources( Class cl, String resourcePath ) try { File parentPom = new File( tempDir.getParentFile(), "pom.xml" ); - if (!parentPom.exists()){ + if ( !parentPom.exists() ) + { URL resource = cl.getResource( "/pom.xml" ); FileUtils.copyURLToFile( resource, parentPom ); } @@ -423,8 +432,7 @@ private File simpleExtractResources( Class cl, String resourcePath ) private File getUnpackDir() { String tempDirPath = System.getProperty( "maven.test.tmpdir", System.getProperty( "java.io.tmpdir" ) ); - return new File( tempDirPath, - testCaseBeingRun.getSimpleName() + "_" + getTestMethodName() + suffix ); + return new File( tempDirPath, testCaseBeingRun.getSimpleName() + "_" + getTestMethodName() + suffix ); } public File getArtifactPath( String gid, String aid, String version, String ext ) @@ -453,12 +461,10 @@ String getTestMethodName() private static Verifier createVerifier( String basedir, String settingsFile, String[] defaultCliOptions ) throws VerificationException { - Verifier verifier = defaultCliOptions == null ? - new Verifier( basedir, settingsFile, false ) - : new Verifier( basedir, settingsFile, false, defaultCliOptions ); + Verifier verifier = defaultCliOptions == null ? new Verifier( basedir, settingsFile, false ) : new Verifier( + basedir, settingsFile, false, defaultCliOptions ); - verifier.getVerifierProperties() - .setProperty( "use.mavenRepoLocal", "true" ); + verifier.getVerifierProperties().setProperty( "use.mavenRepoLocal", "true" ); return verifier; } @@ -467,8 +473,7 @@ private static File settingsXmlPath() { try { - return new File( System.getProperty( "maven.settings.file" ) ) - .getCanonicalFile(); + return new File( System.getProperty( "maven.settings.file" ) ).getCanonicalFile(); } catch ( IOException e ) { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/OutputValidator.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/OutputValidator.java index 5f61fc4b3c..d36c6a6065 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/OutputValidator.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/OutputValidator.java @@ -30,6 +30,7 @@ import org.apache.maven.it.Verifier; import org.hamcrest.Matcher; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.hamcrest.MatcherAssert.assertThat; /** @@ -203,7 +204,7 @@ public TestFile getSurefireReportsFile( String fileName ) public TestFile getSurefireReportsXmlFile( String fileName ) { File targetDir = getSurefireReportsDirectory(); - return new TestFile( new File( targetDir, fileName ), Charset.forName( "UTF-8" ), this ); + return new TestFile( new File( targetDir, fileName ), UTF_8, this ); } public File getSurefireReportsDirectory() diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java index bb19ea9a39..a507604590 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/SurefireLauncher.java @@ -131,7 +131,7 @@ private SurefireLauncher addEnvVar( String key, String value ) return this; } - public SurefireLauncher setMavenOpts(String opts) + public SurefireLauncher setMavenOpts( String opts ) { return addEnvVar( "MAVEN_OPTS", opts ); } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/TestFile.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/TestFile.java index f7f05f7beb..d6aefa3d21 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/TestFile.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/fixture/TestFile.java @@ -50,7 +50,7 @@ public class TestFile public TestFile( File file, OutputValidator surefireVerifier ) { - this( file, defaultCharset(), surefireVerifier); + this( file, defaultCharset(), surefireVerifier ); } public TestFile( File file, Charset charset, OutputValidator surefireVerifier ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1004RunTestFromDependencyJarsTypeAndClassifierIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1004RunTestFromDependencyJarsTypeAndClassifierIT.java new file mode 100644 index 0000000000..ffc05b202d --- /dev/null +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1004RunTestFromDependencyJarsTypeAndClassifierIT.java @@ -0,0 +1,58 @@ +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 static org.junit.Assert.assertFalse; + +import java.util.Collection; + +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.junit.Test; + +/** + * + */ +public class Surefire1004RunTestFromDependencyJarsTypeAndClassifierIT extends SurefireJUnit4IntegrationTestCase +{ + + @Test + public void shouldScanAndRunTestsInDependencyJars() throws Exception + { + SurefireLauncher launcher = unpack( "surefire-1004-RunTestFromDependencyJarsTypeAndClassifier" ); + launcher.addGoal( "test" ).addGoal( "install" ); + OutputValidator wholeExecValidator = launcher.executeCurrentGoals(); + wholeExecValidator.verifyErrorFreeLog(); + + OutputValidator module1 = launcher.getSubProjectValidator( "surefire-1004-module1" ); + module1.assertTestSuiteResults( 3, 0, 0, 0 ); + + // Tests from dependencies + wholeExecValidator.verifyTextInLog( "Running org.acme.tests.TestA" ); + wholeExecValidator.verifyTextInLog( "Running org.acme.classifiedtests.ClassifiedTestA" ); + // Tests from module1 to verify classpath + wholeExecValidator.verifyTextInLog( "Running org.acme.tests.ClasspathTest" ); + // Should not run these tests + Collection logLines = wholeExecValidator.loadLogLines(); + assertFalse( logLines.contains( "org.acme.othertests.OtherTestA" ) ); + assertFalse( logLines.contains( "org.acme.tests.TestB" ) ); + } +} diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1024VerifyFailsafeIfTestedIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1024VerifyFailsafeIfTestedIT.java index 886cd0740f..9db5da8e36 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1024VerifyFailsafeIfTestedIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1024VerifyFailsafeIfTestedIT.java @@ -37,7 +37,8 @@ public class Surefire1024VerifyFailsafeIfTestedIT { @Test - public void shouldScanAndRunTestsInDependencyJars() throws Exception { + public void shouldScanAndRunTestsInDependencyJars() throws Exception + { SurefireLauncher launcher = unpack( "surefire-1024" ); launcher.executeVerify() .verifyTextInLog( "class jiras.surefire1024.A1IT#test() dependency to scan" ); diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1036NonFilterableJUnitRunnerWithCategoriesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1036NonFilterableJUnitRunnerWithCategoriesIT.java index 0d6d8b6f24..d4e7328beb 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1036NonFilterableJUnitRunnerWithCategoriesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1036NonFilterableJUnitRunnerWithCategoriesIT.java @@ -30,7 +30,9 @@ import java.io.FileNotFoundException; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * @author Tibor Digana (tibor17) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1041FailingJUnitRunnerIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1041FailingJUnitRunnerIT.java index bb656821a1..8c23d75a20 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1041FailingJUnitRunnerIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1041FailingJUnitRunnerIT.java @@ -33,6 +33,9 @@ public class Surefire1041FailingJUnitRunnerIT @Test public void reportErrorInJUnitRunnerAsTestError() { - unpack( "surefire-1041-exception-in-junit-runner" ).mavenTestFailureIgnore( true ).executeTest().assertTestSuiteResults( 1, 1, 0, 0 ); + unpack( "surefire-1041-exception-in-junit-runner" ) + .mavenTestFailureIgnore( true ) + .executeTest() + .assertTestSuiteResults( 1, 1, 0, 0 ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1055CorrectConcurrentTestCountIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1055CorrectConcurrentTestCountIT.java index 0293a757fa..9326b367d3 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1055CorrectConcurrentTestCountIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1055CorrectConcurrentTestCountIT.java @@ -28,6 +28,7 @@ * * @author Kristian Rosenvold */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class Surefire1055CorrectConcurrentTestCountIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1082ParallelJUnitParameterizedIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1082ParallelJUnitParameterizedIT.java index 34dd5ae1d3..5bac50666b 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1082ParallelJUnitParameterizedIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1082ParallelJUnitParameterizedIT.java @@ -26,11 +26,11 @@ import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; -import java.nio.charset.Charset; import java.util.Collection; import java.util.Set; import java.util.TreeSet; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.apache.maven.surefire.its.fixture.IsRegex.regex; import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.core.AnyOf.anyOf; @@ -50,7 +50,7 @@ private static Set printOnlyTestLinesFromOutFile( OutputValidator valida { TestFile report = validator.getSurefireReportsFile( "jiras.surefire1082.Jira1082Test-output.txt" ); report.assertFileExists(); - return printOnlyTestLines( validator.loadFile( report.getFile(), Charset.forName( "UTF-8" ) ) ); + return printOnlyTestLines( validator.loadFile( report.getFile(), UTF_8 ) ); } private static Set printOnlyTestLines( Collection logs ) diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1095NpeInRunListener.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1095NpeInRunListener.java index f894265a20..d120d418f0 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1095NpeInRunListener.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1095NpeInRunListener.java @@ -23,7 +23,7 @@ import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; -@SuppressWarnings( { "javadoc", "checkstyle:javadoctype" } ) +@SuppressWarnings( { "javadoc", "checkstyle:javadoctype", "checkstyle:linelength" } ) /** * * In the surefire plugin, it is possible to specify one or more RunListener when running tests with JUnit. diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1098BalancedRunOrderIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1098BalancedRunOrderIT.java index 9a1fd11a6e..f50bb8e915 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1098BalancedRunOrderIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1098BalancedRunOrderIT.java @@ -36,11 +36,8 @@ /** * The purpose of this IT is to assert that the run order of test classes is according to the settings:
- * - * runOrder=balanced
- * parallel=classes
- * threadCount=2
- * perCoreThreadCount=false
+ *

+ * runOrder=balanced
parallel=classes
threadCount=2
perCoreThreadCount=false
*
* The list of tests should be reordered to (DTest, CTest, BTest, ATest) in the second run. * @@ -48,28 +45,23 @@ * @see SUREFIRE-1098 * @since 2.18 */ -public class Surefire1098BalancedRunOrderIT - extends SurefireJUnit4IntegrationTestCase +public class Surefire1098BalancedRunOrderIT extends SurefireJUnit4IntegrationTestCase { @Test - public void reorderedParallelClasses() - throws VerificationException + public void reorderedParallelClasses() throws VerificationException { SurefireLauncher launcher = unpack(); launcher - // .runOrder( "balanced" ) call it in 3.x and remove it in surefire-1098-balanced-runorder/pom.xml - // as soon as there is prefix available "failsafe" and "surefire" in system property for this parameter. - .parallelClasses().threadCount( 2 ).disablePerCoreThreadCount() - .executeTest().verifyErrorFree( 4 ); + // .runOrder( "balanced" ) call it in 3.x and remove it in surefire-1098-balanced-runorder/pom.xml + // as soon as there is prefix available "failsafe" and "surefire" in system property for this parameter. + .parallelClasses().threadCount( 2 ).disablePerCoreThreadCount().executeTest().verifyErrorFree( 4 ); - OutputValidator validator = - launcher + OutputValidator validator = launcher // .runOrder( "balanced" ) call it in 3.x and remove it in surefire-1098-balanced-runorder/pom.xml // as soon as there is prefix available "failsafe" and "surefire" in system property for this parameter. - .parallelClasses().threadCount( 2 ).disablePerCoreThreadCount() - .executeTest().verifyErrorFree( 4 ); + .parallelClasses().threadCount( 2 ).disablePerCoreThreadCount().executeTest().verifyErrorFree( 4 ); List log = printOnlyTestLines( validator ); assertThat( log.size(), is( 4 ) ); @@ -91,28 +83,29 @@ private SurefireLauncher unpack() return unpack( "surefire-1098-balanced-runorder" ); } - private static List printOnlyTestLines( OutputValidator validator ) - throws VerificationException + private static List printOnlyTestLines( OutputValidator validator ) throws VerificationException { List log = new ArrayList<>( validator.loadLogLines() ); - for ( Iterator it = log.iterator(); it.hasNext(); ) { + for ( Iterator it = log.iterator(); it.hasNext(); ) + { String line = it.next(); - if ( !line.startsWith( "class jiras.surefire1098." ) ) { + if ( !line.startsWith( "class jiras.surefire1098." ) ) + { it.remove(); } } return log; } - private static int[] extractThreadPoolIds(String logLine) + private static int[] extractThreadPoolIds( String logLine ) { //Example to parse "class jiras.surefire1098.DTest pool-2-thread-1" into {2, 1}. String t = logLine.split( " " )[2]; String[] ids = t.split( "-" ); - return new int[]{ Integer.parseInt( ids[1] ), Integer.parseInt( ids[3] )}; + return new int[] {Integer.parseInt( ids[1] ), Integer.parseInt( ids[3] )}; } - private String testLine(String test, int pool, int thread) + private String testLine( String test, int pool, int thread ) { return String.format( "class jiras.surefire1098.%sTest pool-%d-thread-%d", test, pool, thread ); } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1135ImproveIgnoreMessageForTestNGIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1135ImproveIgnoreMessageForTestNGIT.java index f7324c9103..fe1ec8f60e 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1135ImproveIgnoreMessageForTestNGIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1135ImproveIgnoreMessageForTestNGIT.java @@ -20,7 +20,11 @@ */ import static org.apache.maven.shared.utils.xml.Xpp3DomBuilder.build; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.arrayWithSize; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyOrNullString; +import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; import java.io.FileNotFoundException; @@ -36,72 +40,72 @@ * * @author Michal Bocek */ -public class Surefire1135ImproveIgnoreMessageForTestNGIT - extends SurefireJUnit4IntegrationTestCase +public class Surefire1135ImproveIgnoreMessageForTestNGIT extends SurefireJUnit4IntegrationTestCase { private enum ResultType { - SKIPPED( "skipped" ), FAILURE( "failure" ); + SKIPPED( "skipped" ), + FAILURE( "failure" ); private final String type; - ResultType(String type) + ResultType( String type ) { this.type = type; } - public String getType() { + public String getType() + { return type; } } @Test - public void testNgReport688() throws Exception { - testNgReport( "6.8.8", null, ResultType.SKIPPED, - "Skip test", - /*"org.testng.SkipException"*/ null, - /*"SkipExceptionReportTest.java:30"*/ null ); + public void testNgReport688() throws Exception + { + testNgReport( "6.8.8", null, ResultType.SKIPPED, "Skip test", + /*"org.testng.SkipException"*/ null, + /*"SkipExceptionReportTest.java:30"*/ null ); } @Test - public void testNgReport57() throws Exception { - testNgReport( "5.7", "jdk15", ResultType.SKIPPED, - "Skip test", - /*"org.testng.SkipException"*/ null, - /*"SkipExceptionReportTest.java:30"*/ null ); + public void testNgReport57() throws Exception + { + testNgReport( "5.7", "jdk15", ResultType.SKIPPED, "Skip test", + /*"org.testng.SkipException"*/ null, + /*"SkipExceptionReportTest.java:30"*/ null ); } private void testNgReport( String version, String classifier, ResultType resultType, String message, String type, - String stackTrace ) - throws Exception + String stackTrace ) throws Exception { - OutputValidator outputValidator = - runTest( version, classifier, resultType, "/surefire-1135-improve-ignore-message-for-testng" ); + OutputValidator outputValidator = runTest( version, classifier, resultType, + "/surefire-1135-improve-ignore-message-for-testng" ); Xpp3Dom[] children = readTests( outputValidator, "testng.SkipExceptionReportTest" ); assertThat( "Report should contains only one test case", children.length, is( 1 ) ); Xpp3Dom test = children[0]; assertThat( "Not expected classname", test.getAttribute( "classname" ), - is( "testng.SkipExceptionReportTest" ) ); + is( "testng.SkipExceptionReportTest" ) ); assertThat( "Not expected test name", test.getAttribute( "name" ), is( "testSkipException" ) ); children = test.getChildren( resultType.getType() ); assertThat( "Test should contains only one " + resultType.getType() + " element", children, - is( arrayWithSize( 1 ) ) ); + is( arrayWithSize( 1 ) ) ); Xpp3Dom result = children[0]; if ( message == null ) { assertThat( "Subelement message attribute must be null", result.getAttribute( "message" ), - is( nullValue() ) ); + is( nullValue() ) ); } else { assertThat( "Subelement should contains message attribute", result.getAttribute( "message" ), - is( message ) ); + is( message ) ); } if ( type == null ) @@ -115,7 +119,7 @@ private void testNgReport( String version, String classifier, ResultType resultT if ( stackTrace == null ) { - assertThat( "Element body must be null", result.getValue() , isEmptyOrNullString() ); + assertThat( "Element body must be null", result.getValue(), isEmptyOrNullString() ); } else { @@ -135,18 +139,13 @@ private OutputValidator runTest( String version, String classifier, ResultType r launcher.sysProp( "testNgClassifier", classifier ); } - return launcher.addSurefireReportGoal() - .executeCurrentGoals() - .assertTestSuiteResults( 1, 0, failure, skipped ); + return launcher.addSurefireReportGoal().executeCurrentGoals().assertTestSuiteResults( 1, 0, failure, skipped ); } - private static Xpp3Dom[] readTests( OutputValidator validator, String className ) - throws FileNotFoundException + private static Xpp3Dom[] readTests( OutputValidator validator, String className ) throws FileNotFoundException { - Xpp3Dom testResult = - build( validator.getSurefireReportsXmlFile( "TEST-" + className + ".xml" ).getFileInputStream(), - "UTF-8" - ); + Xpp3Dom testResult = build( + validator.getSurefireReportsXmlFile( "TEST-" + className + ".xml" ).getFileInputStream(), "UTF-8" ); return testResult.getChildren( "testcase" ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1144XmlRunTimeIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1144XmlRunTimeIT.java index d81d7c2c90..08197ad327 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1144XmlRunTimeIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1144XmlRunTimeIT.java @@ -37,6 +37,7 @@ * * @author Lamyaa Eloussi */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class Surefire1144XmlRunTimeIT extends SurefireJUnit4IntegrationTestCase { @@ -52,7 +53,7 @@ public void testXmlRunTime() ReportTestSuite report = reports.get( 0 ); float xmlTime = report.getTimeElapsed(); - assertThat( xmlTime, is(greaterThanOrEqualTo( 1.6f ) ) ); //include beforeClass and afterClass + assertThat( xmlTime, is( greaterThanOrEqualTo( 1.6f ) ) ); //include beforeClass and afterClass outputValidator.verifyTextInLog( Float.toString( xmlTime ) ); //same time in console } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1146RerunFailedAndParameterized.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1146RerunFailedAndParameterized.java index f78c16ab28..3a5fa8cfa1 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1146RerunFailedAndParameterized.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1146RerunFailedAndParameterized.java @@ -34,9 +34,10 @@ public class Surefire1146RerunFailedAndParameterized public void testsAreRerun() { OutputValidator outputValidator = unpack( "surefire-1146-rerunFailingTests-with-Parameterized" ).executeTest(); - verify(outputValidator, 8, 0, 0, 0, 5); + verify( outputValidator, 8, 0, 0, 0, 5 ); } + @SuppressWarnings( "checkstyle:linelength" ) private void verify( OutputValidator outputValidator, int run, int failures, int errors, int skipped, int flakes ) { outputValidator.verifyTextInLog( "Flakes:" ); diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1152RerunFailingTestsInSuiteIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1152RerunFailingTestsInSuiteIT.java index 58e951a6f2..b32129a29e 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1152RerunFailingTestsInSuiteIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1152RerunFailingTestsInSuiteIT.java @@ -29,15 +29,14 @@ * * @author Sean Flanigan */ -public class Surefire1152RerunFailingTestsInSuiteIT - extends SurefireJUnit4IntegrationTestCase +public class Surefire1152RerunFailingTestsInSuiteIT extends SurefireJUnit4IntegrationTestCase { private static final String RUNNING_WITH_PROVIDER47 = - "Using configured provider org.apache.maven.surefire.junitcore.JUnitCoreProvider"; + "Using configured provider org.apache.maven.surefire.junitcore.JUnitCoreProvider"; - public OutputValidator runMethodPattern( String projectName, String... goals ) + private OutputValidator runMethodPattern( String... goals ) { - SurefireLauncher launcher = unpack( projectName ); + SurefireLauncher launcher = unpack( "surefire-1152-rerunFailingTestsCount-suite" ); for ( String goal : goals ) { launcher.addGoal( goal ); @@ -51,14 +50,12 @@ public OutputValidator runMethodPattern( String projectName, String... goals ) @Test public void testJUnit48Provider4() { - runMethodPattern( "surefire-1152-rerunFailingTestsCount-suite", "-P surefire-junit4" ); + runMethodPattern( "-P surefire-junit4" ); } @Test public void testJUnit48Provider47() { - runMethodPattern( "surefire-1152-rerunFailingTestsCount-suite", "-P surefire-junit47" ) - .verifyTextInLog( RUNNING_WITH_PROVIDER47 ); + runMethodPattern( "-P surefire-junit47" ).verifyTextInLog( RUNNING_WITH_PROVIDER47 ); } - } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1153IncludesAndSpecifiedTestIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1153IncludesAndSpecifiedTestIT.java index 3a2c826481..f60a878501 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1153IncludesAndSpecifiedTestIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1153IncludesAndSpecifiedTestIT.java @@ -1,4 +1,5 @@ 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 @@ -22,6 +23,9 @@ import org.junit.Test; +/** + * + */ public class Surefire1153IncludesAndSpecifiedTestIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java index 706f6b5f40..0b236e12e5 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1158RemoveInfoLinesIT.java @@ -1,4 +1,5 @@ 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 @@ -18,62 +19,67 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.surefire.its.fixture.OutputValidator; import org.apache.maven.surefire.its.fixture.SurefireVerifierException; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import java.util.ArrayList; import static org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase.unpack; -import static org.junit.runners.Parameterized.*; -import static org.junit.Assert.*; +import static org.junit.runners.Parameterized.Parameter; +import static org.junit.runners.Parameterized.Parameters; +import static org.junit.Assert.fail; /** - * * @author Tibor Digana (tibor17) * @see SUREFIRE-1158 * @since 2.19 */ -@RunWith( Parameterized.class ) +@RunWith( ParallelParameterized.class ) public class Surefire1158RemoveInfoLinesIT { - @Parameters(name = "{0}") + @Parameters( name = "{0}" ) public static Iterable data() { - ArrayList args = new ArrayList(); - args.add( new Object[] { "junit-option-ff", "JUnitTest", "-ff", "surefire-junit47", false, true } ); - args.add( new Object[] { "testng-option-ff", "TestNGSuiteTest", "-ff", "surefire-testng", false, false } ); - args.add( new Object[] { "junit-option-X", "JUnitTest", "-X", "surefire-junit47", true, true } ); - args.add( new Object[] { "testng-option-X", "TestNGSuiteTest", "-X", "surefire-testng", true, false } ); - args.add( new Object[] { "junit-option-e", "JUnitTest", "-e", "surefire-junit47", true, true } ); - args.add( new Object[] { "testng-option-e", "TestNGSuiteTest", "-e", "surefire-testng", true, false } ); + ArrayList args = new ArrayList<>(); + args.add( new Object[] {"junit-option-ff", "JUnitTest", "-ff", "surefire-junit47", false, true} ); + args.add( new Object[] {"testng-option-ff", "TestNGSuiteTest", "-ff", "surefire-testng", false, false} ); + args.add( new Object[] {"junit-option-X", "JUnitTest", "-X", "surefire-junit47", true, true} ); + args.add( new Object[] {"testng-option-X", "TestNGSuiteTest", "-X", "surefire-testng", true, false} ); + args.add( new Object[] {"junit-option-e", "JUnitTest", "-e", "surefire-junit47", true, true} ); + args.add( new Object[] {"testng-option-e", "TestNGSuiteTest", "-e", "surefire-testng", true, false} ); return args; } - @Parameter(0) + @Parameter( 0 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String description; - @Parameter(1) + @Parameter( 1 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String testToRun; - @Parameter(2) + @Parameter( 2 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String cliOption; - @Parameter(3) + @Parameter( 3 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public String provider; - @Parameter(4) + @Parameter( 4 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public boolean printsInfoLines; - @Parameter(5) + @Parameter( 5 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) public boolean isJUnit; @Test - public void shouldRunWithCliOption() - throws Exception + public void shouldRunWithCliOption() throws Exception { OutputValidator validator = assertTest(); if ( isJUnit ) @@ -86,14 +92,12 @@ public void shouldRunWithCliOption() } } - private OutputValidator assertTest() - throws Exception + private OutputValidator assertTest() throws Exception { final String[] cli = {"--batch-mode"}; - return unpack( getClass(), "/surefire-1158-remove-info-lines", "_" + description, cli ) - .sysProp( "provider", provider ).addGoal( cliOption ).setTestToRun( testToRun ) - .executeTest() - .verifyErrorFreeLog().assertTestSuiteResults( 1, 0, 0, 0 ); + return unpack( getClass(), "/surefire-1158-remove-info-lines", "_" + description, cli ).sysProp( "provider", + provider ).addGoal( cliOption ).setTestToRun( + testToRun ).executeTest().verifyErrorFreeLog().assertTestSuiteResults( 1, 0, 0, 0 ); } private void assertJUnitTestLogs( OutputValidator validator ) @@ -101,10 +105,11 @@ private void assertJUnitTestLogs( OutputValidator validator ) try { validator.verifyTextInLog( "Surefire report directory:" ); - validator.verifyTextInLog( "Using configured provider org.apache.maven.surefire.junitcore.JUnitCoreProvider" ); + validator.verifyTextInLog( + "Using configured provider org.apache.maven.surefire.junitcore.JUnitCoreProvider" ); validator.verifyTextInLog( "parallel='none', perCoreThreadCount=true, threadCount=0, " - + "useUnlimitedThreads=false, threadCountSuites=0, threadCountClasses=0, " - + "threadCountMethods=0, parallelOptimized=true" ); + + "useUnlimitedThreads=false, threadCountSuites=0, threadCountClasses=0, " + + "threadCountMethods=0, parallelOptimized=true" ); if ( !printsInfoLines ) { fail(); diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1209RerunAndForkCountIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1209RerunAndForkCountIT.java index 6ee87fbb0f..696e0acdb9 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1209RerunAndForkCountIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1209RerunAndForkCountIT.java @@ -24,6 +24,9 @@ import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.containsString; + /** * @author Tibor Digana (tibor17) * @see SUREFIRE-1209 @@ -32,40 +35,43 @@ public class Surefire1209RerunAndForkCountIT extends SurefireJUnit4IntegrationTestCase { + private static final String SUMMARY_COUNTS = "Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Flakes: 2"; + @Test - public void reusableForksJUnit47() - throws VerificationException + public void reusableForksJUnit47() throws VerificationException { unpack().executeTest() - .assertTestSuiteResults( 5, 0, 0, 0, 4 ); + .assertTestSuiteResults( 5, 0, 0, 0, 4 ) + .assertThatLogLine( containsString( SUMMARY_COUNTS ), is( 1 ) ); } @Test - public void notReusableForksJUnit47() - throws VerificationException + public void notReusableForksJUnit47() throws VerificationException { unpack().reuseForks( false ) .executeTest() - .assertTestSuiteResults( 5, 0, 0, 0, 4 ); + .assertTestSuiteResults( 5, 0, 0, 0, 4 ) + .assertThatLogLine( containsString( SUMMARY_COUNTS ), is( 1 ) ); } @Test - public void reusableForksJUnit4() - throws VerificationException + public void reusableForksJUnit4() throws VerificationException { - unpack().addGoal( "-Pjunit4" ) + unpack().activateProfile( "junit4" ) .executeTest() - .assertTestSuiteResults( 5, 0, 0, 0, 4 ); + .assertTestSuiteResults( 5, 0, 0, 0, 4 ) + .assertThatLogLine( containsString( SUMMARY_COUNTS ), is( 1 ) ); } @Test public void notReusableForksJUnit4() throws VerificationException { - unpack().addGoal( "-Pjunit4" ) + unpack().activateProfile( "junit4" ) .reuseForks( false ) .executeTest() - .assertTestSuiteResults( 5, 0, 0, 0, 4 ); + .assertTestSuiteResults( 5, 0, 0, 0, 4 ) + .assertThatLogLine( containsString( SUMMARY_COUNTS ), is( 1 ) ); } private SurefireLauncher unpack() diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1260NewTestsPattern.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1260NewTestsPattern.java index c4031c25e6..640c551b62 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1260NewTestsPattern.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1260NewTestsPattern.java @@ -19,7 +19,8 @@ * under the License. */ -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; /** diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java index 2e92805e48..c5d80719b4 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1265Java9IT.java @@ -44,7 +44,7 @@ public class Surefire1265Java9IT @Test public void shouldRunInPluginJava9() throws IOException { - assumeJigsaw() + assumeJava9() .executeTest() .verifyErrorFree( 2 ); } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1295AttributeJvmCrashesToTestsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1295AttributeJvmCrashesToTestsIT.java index 14ecb34fdb..9f6798ce4c 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1295AttributeJvmCrashesToTestsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1295AttributeJvmCrashesToTestsIT.java @@ -19,12 +19,12 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.surefire.its.fixture.OutputValidator; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; @@ -51,10 +51,13 @@ * @author michaeltandy * @since 2.20 */ -@RunWith( Parameterized.class ) +@RunWith( ParallelParameterized.class ) public class Surefire1295AttributeJvmCrashesToTestsIT extends SurefireJUnit4IntegrationTestCase { + /** + * + */ public enum ForkMode { DEFAULT, @@ -65,7 +68,7 @@ public enum ForkMode @Parameters public static Iterable parameters() { - return asList(new Object[][] { + return asList( new Object[][] { // exit() does not stop all Threads immediately, // see https://github.com/michaeltandy/crashjvm/issues/1 { "exit", DEFAULT }, @@ -77,14 +80,16 @@ public static Iterable parameters() { "segfault", DEFAULT }, { "segfault", ONE_FORK_NO_REUSE }, { "segfault", ONE_FORK_REUSE } - }); + } ); } @Parameter( 0 ) - public static String crashStyle; + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public String crashStyle; @Parameter( 1 ) - public static ForkMode forkStyle; + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public ForkMode forkStyle; @Test public void test() diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1367AssumptionLogsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1367AssumptionLogsIT.java index 48564fb2a8..5d05c125cf 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1367AssumptionLogsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1367AssumptionLogsIT.java @@ -31,22 +31,16 @@ * @see SUREFIRE-1367 * @since 2.20.1 */ -public class Surefire1367AssumptionLogsIT - extends SurefireJUnit4IntegrationTestCase +public class Surefire1367AssumptionLogsIT extends SurefireJUnit4IntegrationTestCase { private static final String NL = System.getProperty( "line.separator" ); @Test public void shouldSeeLogsParallelForked() { - OutputValidator outputValidator = unpack().setForkJvm() - .forkMode( "once" ) - .parallelClassesAndMethods() - .disablePerCoreThreadCount() - .threadCountClasses( 2 ) - .threadCountMethods( 2 ) - .executeTest() - .assertTestSuiteResults( 2, 0, 0, 2 ); + OutputValidator outputValidator = unpack().setForkJvm().forkMode( + "once" ).parallelClassesAndMethods().disablePerCoreThreadCount().threadCountClasses( + 2 ).threadCountMethods( 2 ).executeTest().assertTestSuiteResults( 2, 0, 0, 2 ); verifyReportA( outputValidator ); verifyReportB( outputValidator ); @@ -55,14 +49,9 @@ public void shouldSeeLogsParallelForked() @Test public void shouldSeeLogsParallelInPlugin() { - OutputValidator outputValidator = unpack().setForkJvm() - .forkMode( "never" ) - .parallelClassesAndMethods() - .disablePerCoreThreadCount() - .threadCountClasses( 2 ) - .threadCountMethods( 2 ) - .executeTest() - .assertTestSuiteResults( 2, 0, 0, 2 ); + OutputValidator outputValidator = unpack().setForkJvm().forkMode( + "never" ).parallelClassesAndMethods().disablePerCoreThreadCount().threadCountClasses( + 2 ).threadCountMethods( 2 ).executeTest().assertTestSuiteResults( 2, 0, 0, 2 ); verifyReportA( outputValidator ); verifyReportB( outputValidator ); @@ -71,10 +60,8 @@ public void shouldSeeLogsParallelInPlugin() @Test public void shouldSeeLogsForked() { - OutputValidator outputValidator = unpack().setForkJvm() - .forkMode( "once" ) - .executeTest() - .assertTestSuiteResults( 2, 0, 0, 2 ); + OutputValidator outputValidator = unpack().setForkJvm().forkMode( "once" ).executeTest().assertTestSuiteResults( + 2, 0, 0, 2 ); verifyReportA( outputValidator ); verifyReportB( outputValidator ); @@ -83,10 +70,8 @@ public void shouldSeeLogsForked() @Test public void shouldSeeLogsInPlugin() { - OutputValidator outputValidator = unpack().setForkJvm() - .forkMode( "never" ) - .executeTest() - .assertTestSuiteResults( 2, 0, 0, 2 ); + OutputValidator outputValidator = unpack().setForkJvm().forkMode( + "never" ).executeTest().assertTestSuiteResults( 2, 0, 0, 2 ); verifyReportA( outputValidator ); verifyReportB( outputValidator ); @@ -100,58 +85,34 @@ private SurefireLauncher unpack() private void verifyReportA( OutputValidator outputValidator ) { - String xmlReport = outputValidator.getSurefireReportsXmlFile( "TEST-ATest.xml" ) - .readFileToString(); - - String outputCData = "" + NL + - " "; - - assertThat( xmlReport ) - .contains( outputCData ); - - - String output = outputValidator.getSurefireReportsFile( "ATest-output.txt" ) - .readFileToString(); - - String outputExpected = "Hi" + NL + - NL + - "There!" + NL + - "Hello" + NL + - NL + - "What's up!" + NL; - - assertThat( output ) - .isEqualTo( outputExpected ); + String xmlReport = outputValidator.getSurefireReportsXmlFile( "TEST-ATest.xml" ).readFileToString(); + + String outputCData = "" + NL + " " + + ""; + + assertThat( xmlReport ).contains( outputCData ); + + + String output = outputValidator.getSurefireReportsFile( "ATest-output.txt" ).readFileToString(); + + String outputExpected = "Hi" + NL + NL + "There!" + NL + "Hello" + NL + NL + "What's up!" + NL; + + assertThat( output ).isEqualTo( outputExpected ); } private void verifyReportB( OutputValidator outputValidator ) { - String xmlReport = outputValidator.getSurefireReportsXmlFile( "TEST-BTest.xml" ) - .readFileToString(); + String xmlReport = outputValidator.getSurefireReportsXmlFile( "TEST-BTest.xml" ).readFileToString(); - String outputCData = ""; + String outputCData = ""; - assertThat( xmlReport ) - .contains( outputCData ); + assertThat( xmlReport ).contains( outputCData ); - String output = outputValidator.getSurefireReportsFile( "BTest-output.txt" ) - .readFileToString(); + String output = outputValidator.getSurefireReportsFile( "BTest-output.txt" ).readFileToString(); - String outputExpected = "Hey" + NL + - NL + - "you!" + NL; + String outputExpected = "Hey" + NL + NL + "you!" + NL; - assertThat( output ) - .isEqualTo( outputExpected ); + assertThat( output ).isEqualTo( outputExpected ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1396CustomProviderClassPathIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1396CustomProviderClassPathIT.java index 60b372fada..e0ed72ad2e 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1396CustomProviderClassPathIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1396CustomProviderClassPathIT.java @@ -32,7 +32,9 @@ public class Surefire1396CustomProviderClassPathIT @BeforeClass public static void installProvider() { - unpack( Surefire1396CustomProviderClassPathIT.class, "surefire-1396-pluggableproviders-classpath-provider", "prov" ).executeInstall(); + unpack( Surefire1396CustomProviderClassPathIT.class, + "surefire-1396-pluggableproviders-classpath-provider", "prov" ) + .executeInstall(); } @Test diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire141PluggableProvidersIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire141PluggableProvidersIT.java index 80c82b21e2..cce0000b0b 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire141PluggableProvidersIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire141PluggableProvidersIT.java @@ -135,7 +135,7 @@ public boolean accept( File dir, String name ) { return name.endsWith( "-jvmRun1.dump" ); } - }); + } ) ; assertThat( dumpFiles ) .isNotNull() .isNotEmpty(); 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 0000000000..23df0352bf --- /dev/null +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1534ReuseForksFalseWithJavaModuleIT.java @@ -0,0 +1,103 @@ +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 = assumeJava9() + .reuseForks( false ) + .forkCount( 1 ) + .executeTest(); + + validator.assertTestSuiteResults( 2, 0, 0, 0 ); + validator.verifyErrorFreeLog(); + + TestFile report = validator.getSurefireReportsFile( "TEST-it.MainTest.xml", UTF_8 ); + assertTrue( report.exists() ); + report.assertContainsText( "" ) + .assertContainsText( "" ) + .assertContainsText( "" ) + .assertContainsText( "" ) + .assertContainsText( "" ) + .assertContainsText( "Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +public class Surefire1712ExtractedModulenameWithoutASMIT + extends AbstractJigsawIT +{ + @Test + public void test() + throws IOException + { + assumeJava9() + .debugLogging() + .executeTest() + .assertTestSuiteResults( 1, 0, 0, 0 ) + .verifyErrorFreeLog() + .verifyTextInLog( "main module descriptor name: wtf.g4s8.oot" ); + } + + @Override + protected String getProjectDirectoryName() + { + return "surefire-1712-extracted-modulename-without-asm"; + } +} diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire224WellFormedXmlFailuresIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire224WellFormedXmlFailuresIT.java index 1bdb3cb2e4..b278c7a226 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire224WellFormedXmlFailuresIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire224WellFormedXmlFailuresIT.java @@ -38,7 +38,7 @@ public class Surefire224WellFormedXmlFailuresIT extends SurefireJUnit4IntegrationTestCase { - @SuppressWarnings("ConstantConditions") + @SuppressWarnings( "ConstantConditions" ) @Test public void testWellFormedXmlFailures() { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire257NotRerunningTestsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire257NotRerunningTestsIT.java index 2796b92c56..3fd4fb35a8 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire257NotRerunningTestsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire257NotRerunningTestsIT.java @@ -27,15 +27,13 @@ * * @author Kristian Rosenvold */ -public class Surefire257NotRerunningTestsIT - extends SurefireJUnit4IntegrationTestCase +public class Surefire257NotRerunningTestsIT extends SurefireJUnit4IntegrationTestCase { @Test - public void shouldNotRerun() - throws Exception + public void shouldNotRerun() throws Exception { - unpack( - "/surefire-257-rerunningTests" ).addSurefireReportGoal().addSurefireReportGoal().executeCurrentGoals().verifyTextInLog( - "Skipping execution of surefire because it has already been run for this configuration" ); + unpack( "/surefire-257-rerunningTests" ) + .addSurefireReportGoal().addSurefireReportGoal().executeCurrentGoals().verifyTextInLog( + "Skipping execution of surefire because it has already been run for this configuration" ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire260TestWithIdenticalNamesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire260TestWithIdenticalNamesIT.java index b4c26789ad..85bafc51d9 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire260TestWithIdenticalNamesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire260TestWithIdenticalNamesIT.java @@ -22,7 +22,9 @@ import java.io.IOException; import java.net.URI; -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.TestFile; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlAnchor; @@ -40,6 +42,7 @@ * * @author Kristian Rosenvold */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class Surefire260TestWithIdenticalNamesIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire569RunTestFromDependencyJarsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire569RunTestFromDependencyJarsIT.java index 3e53cca5c3..a46483c141 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire569RunTestFromDependencyJarsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire569RunTestFromDependencyJarsIT.java @@ -29,16 +29,17 @@ * * @author Aslak Knutsen */ -public class Surefire569RunTestFromDependencyJarsIT - extends SurefireJUnit4IntegrationTestCase { +public class Surefire569RunTestFromDependencyJarsIT extends SurefireJUnit4IntegrationTestCase +{ - @Test - public void shouldScanAndRunTestsInDependencyJars() throws Exception { - SurefireLauncher launcher = unpack( "surefire-569-RunTestFromDependencyJars" ); - launcher.addGoal("test").addGoal("install"); - launcher.executeCurrentGoals(); + @Test + public void shouldScanAndRunTestsInDependencyJars() throws Exception + { + SurefireLauncher launcher = unpack( "surefire-569-RunTestFromDependencyJars" ); + launcher.addGoal( "test" ).addGoal( "install" ); + launcher.executeCurrentGoals(); - OutputValidator module1 = launcher.getSubProjectValidator("module1"); - module1.assertTestSuiteResults(1, 0, 0, 0); - } + OutputValidator module1 = launcher.getSubProjectValidator( "module1" ); + module1.assertTestSuiteResults( 1, 0, 0, 0 ); + } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire570MultipleReportDirectoriesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire570MultipleReportDirectoriesIT.java index a9b437ebae..e188c8a20d 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire570MultipleReportDirectoriesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire570MultipleReportDirectoriesIT.java @@ -19,7 +19,10 @@ * under the License. */ -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; /** diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire613TestCountInParallelIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire613TestCountInParallelIT.java index 7b74409a9d..9653693a77 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire613TestCountInParallelIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire613TestCountInParallelIT.java @@ -28,6 +28,7 @@ * * @author Kristian Rosenvold */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class Surefire613TestCountInParallelIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire649EmptyStringSystemPropertiesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire649EmptyStringSystemPropertiesIT.java index d6f0a0edfd..7326244260 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire649EmptyStringSystemPropertiesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire649EmptyStringSystemPropertiesIT.java @@ -32,13 +32,11 @@ * @see SUREFIRE-649 * @since 2.18 */ -public class Surefire649EmptyStringSystemPropertiesIT - extends SurefireJUnit4IntegrationTestCase +public class Surefire649EmptyStringSystemPropertiesIT extends SurefireJUnit4IntegrationTestCase { @Test - public void systemProperties() - throws VerificationException + public void systemProperties() throws VerificationException { SurefireLauncher launcher = unpack1(); @@ -51,12 +49,11 @@ public void systemProperties() return; } } - fail("Could not find text in log: emptyProperty=''"); + fail( "Could not find text in log: emptyProperty=''" ); } @Test - public void systemPropertyVariables() - throws VerificationException + public void systemPropertyVariables() throws VerificationException { SurefireLauncher launcher = unpack2(); @@ -69,7 +66,7 @@ public void systemPropertyVariables() return; } } - fail("Could not find text in log: emptyProperty=''"); + fail( "Could not find text in log: emptyProperty=''" ); } private SurefireLauncher unpack1() diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire705ParallelForkTimeoutIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire705ParallelForkTimeoutIT.java index e1a258a748..b29bfd00c2 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire705ParallelForkTimeoutIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire705ParallelForkTimeoutIT.java @@ -27,14 +27,14 @@ * * @author Kristian Rosenvold */ -public class Surefire705ParallelForkTimeoutIT - extends SurefireJUnit4IntegrationTestCase +public class Surefire705ParallelForkTimeoutIT extends SurefireJUnit4IntegrationTestCase { @Test public void testTimeoutForked() { unpack( "/fork-timeout" ).setJUnitVersion( "4.8.1" ).addGoal( "-Djunit.version=4.8.1" ).addGoal( - "-Djunit.parallel=classes" ).addGoal( "-DtimeOut=1" ).maven().withFailure().executeTest() - .verifyTextInLog( "There was a timeout or other error in the fork" ); + "-Djunit.parallel=classes" ).addGoal( + "-DtimeOut=1" ).maven().withFailure().executeTest().verifyTextInLog( + "There was a timeout or other error in the fork" ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire747MethodParallelWithSuiteCountIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire747MethodParallelWithSuiteCountIT.java index 1eab676658..77751fe929 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire747MethodParallelWithSuiteCountIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire747MethodParallelWithSuiteCountIT.java @@ -45,6 +45,7 @@ /** * @author Kristian Rosenvold */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class Surefire747MethodParallelWithSuiteCountIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772BothReportsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772BothReportsIT.java index 96d31c104f..67329d74a4 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772BothReportsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772BothReportsIT.java @@ -19,7 +19,10 @@ * under the License. */ -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; import static org.junit.Assert.assertFalse; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772NoFailsafeReportsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772NoFailsafeReportsIT.java index af18336999..98dd5121f5 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772NoFailsafeReportsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772NoFailsafeReportsIT.java @@ -21,7 +21,10 @@ import java.io.IOException; import org.apache.maven.it.VerificationException; -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; import static org.junit.Assert.assertFalse; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772SpecifiedReportsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772SpecifiedReportsIT.java index a709f7df54..e49435248e 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772SpecifiedReportsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire772SpecifiedReportsIT.java @@ -19,7 +19,10 @@ * under the License. */ -import org.apache.maven.surefire.its.fixture.*; +import org.apache.maven.surefire.its.fixture.OutputValidator; +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.apache.maven.surefire.its.fixture.SurefireLauncher; +import org.apache.maven.surefire.its.fixture.TestFile; import org.junit.Test; import static org.junit.Assert.assertFalse; diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire803MultiFailsafeExecsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire803MultiFailsafeExecsIT.java index 658befd04d..c05c52a65d 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire803MultiFailsafeExecsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire803MultiFailsafeExecsIT.java @@ -1,4 +1,5 @@ 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 @@ -22,6 +23,9 @@ import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; +/** + * + */ public class Surefire803MultiFailsafeExecsIT extends SurefireJUnit4IntegrationTestCase { @@ -30,8 +34,11 @@ public class Surefire803MultiFailsafeExecsIT public void testSecondExecutionRunsAfterFirstExecutionFails() { unpack( - "/surefire-803-multiFailsafeExec-failureInFirst" ).maven().withFailure().executeVerify().assertIntegrationTestSuiteResults( - 4, 0, 2, 0 ); + "/surefire-803-multiFailsafeExec-failureInFirst" ) + .maven() + .withFailure() + .executeVerify() + .assertIntegrationTestSuiteResults( 4, 0, 2, 0 ); } @Test diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java index aedb82bc9a..0b75c00ff3 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire806SpecifiedTestControlsIT.java @@ -1,4 +1,5 @@ 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 @@ -23,6 +24,9 @@ import org.junit.Ignore; import org.junit.Test; +/** + * + */ public class Surefire806SpecifiedTestControlsIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire809GroupExpressionsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire809GroupExpressionsIT.java index 5ab103bfbc..3773817649 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire809GroupExpressionsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire809GroupExpressionsIT.java @@ -1,4 +1,5 @@ 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 @@ -24,6 +25,9 @@ import org.junit.Test; +/** + * + */ public class Surefire809GroupExpressionsIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire818NpeIgnoresTestsIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire818NpeIgnoresTestsIT.java index 1bf4c8dcc1..c74754174b 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire818NpeIgnoresTestsIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire818NpeIgnoresTestsIT.java @@ -33,7 +33,10 @@ public class Surefire818NpeIgnoresTestsIT @Test public void testBuildFailingWhenErrors() { - unpack( "surefire-818-ignored-tests-on-npe" ).maven().withFailure().executeTest().assertTestSuiteResults( 2, 0, - 1, 0 ); + unpack( "surefire-818-ignored-tests-on-npe" ) + .maven() + .withFailure() + .executeTest() + .assertTestSuiteResults( 2, 0, 1, 0 ); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire828EmptyGroupExprIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire828EmptyGroupExprIT.java index b59bc6a7b9..71cb02f33a 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire828EmptyGroupExprIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire828EmptyGroupExprIT.java @@ -1,4 +1,5 @@ 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 @@ -23,6 +24,9 @@ import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; +/** + * + */ public class Surefire828EmptyGroupExprIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire832ProviderSelectionIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire832ProviderSelectionIT.java index c694a3d223..6e02ed24f8 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire832ProviderSelectionIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire832ProviderSelectionIT.java @@ -1,4 +1,5 @@ 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 @@ -23,6 +24,9 @@ import org.apache.maven.surefire.its.fixture.SurefireLauncher; import org.junit.Test; +/** + * + */ public class Surefire832ProviderSelectionIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire839TestWithoutCategoriesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire839TestWithoutCategoriesIT.java index 0babe664d8..ca46340a66 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire839TestWithoutCategoriesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire839TestWithoutCategoriesIT.java @@ -1,4 +1,5 @@ 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 @@ -22,6 +23,9 @@ import org.junit.Test; +/** + * + */ public class Surefire839TestWithoutCategoriesIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire847AdditionalFailureIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire847AdditionalFailureIT.java index eaecc909b7..040dd5fa3d 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire847AdditionalFailureIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire847AdditionalFailureIT.java @@ -1,4 +1,5 @@ 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 @@ -21,6 +22,9 @@ import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Test; +/** + * + */ public class Surefire847AdditionalFailureIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire907PerThreadWithoutThreadCountIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire907PerThreadWithoutThreadCountIT.java index 8317c52719..eb7a711727 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire907PerThreadWithoutThreadCountIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire907PerThreadWithoutThreadCountIT.java @@ -1,4 +1,5 @@ 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 @@ -23,6 +24,9 @@ import org.junit.Test; +/** + * + */ public class Surefire907PerThreadWithoutThreadCountIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire920TestFailureIgnoreWithTimeoutIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire920TestFailureIgnoreWithTimeoutIT.java index 4f608950a9..b6a25eb579 100755 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire920TestFailureIgnoreWithTimeoutIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire920TestFailureIgnoreWithTimeoutIT.java @@ -1,4 +1,5 @@ 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 @@ -23,6 +24,9 @@ import org.junit.Test; +/** + * + */ public class Surefire920TestFailureIgnoreWithTimeoutIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire930TestNgSuiteXmlIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire930TestNgSuiteXmlIT.java index 5963662b2e..80b2c919fc 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire930TestNgSuiteXmlIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire930TestNgSuiteXmlIT.java @@ -1,4 +1,5 @@ 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 @@ -22,6 +23,9 @@ import org.junit.Test; +/** + * + */ public class Surefire930TestNgSuiteXmlIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire943ReportContentIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire943ReportContentIT.java index 59d21703bd..2e37775ca6 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire943ReportContentIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire943ReportContentIT.java @@ -28,11 +28,15 @@ import org.junit.Assert; import org.junit.Test; +/** + * + */ public class Surefire943ReportContentIT extends SurefireJUnit4IntegrationTestCase { @Test + @SuppressWarnings( "checkstyle:methodname" ) public void test_noParallel() throws Exception { @@ -40,6 +44,7 @@ public void test_noParallel() } @Test + @SuppressWarnings( "checkstyle:methodname" ) public void test_parallelBoth() throws Exception { @@ -74,7 +79,7 @@ private void validateFailInBeforeClass( OutputValidator validator, String classN Xpp3Dom child = children[0]; Assert.assertEquals( className, child.getAttribute( "classname" ) ); - Assert.assertEquals( className, child.getAttribute( "name" ) ); + Assert.assertEquals( "", child.getAttribute( "name" ) ); Assert.assertEquals( "Expected error tag for failed BeforeClass method for " + className, 1, child.getChildren( "error" ).length ); @@ -84,7 +89,6 @@ private void validateFailInBeforeClass( OutputValidator validator, String classN Assert.assertTrue( "time for test failure in BeforeClass is expected to be resonably low", Double.compare( Double.parseDouble( child.getAttribute( "time" ) ), 2.0d ) <= 0 ); - } private void validateSkipped( OutputValidator validator, String className ) @@ -97,7 +101,7 @@ private void validateSkipped( OutputValidator validator, String className ) Xpp3Dom child = children[0]; Assert.assertEquals( className, child.getAttribute( "classname" ) ); - Assert.assertEquals( className, child.getAttribute( "name" ) ); + Assert.assertEquals( "", child.getAttribute( "name" ) ); Assert.assertEquals( "Expected skipped tag for ignored method for " + className, 1, child.getChildren( "skipped" ).length ); @@ -150,10 +154,9 @@ private Xpp3Dom[] readTests( OutputValidator validator, String className ) throws FileNotFoundException { Xpp3Dom testResult = - Xpp3DomBuilder.build( validator.getSurefireReportsXmlFile( "TEST-" + className + ".xml" ).getFileInputStream(), - "UTF-8" ); - Xpp3Dom[] children = testResult.getChildren( "testcase" ); - return children; + Xpp3DomBuilder.build( + validator.getSurefireReportsXmlFile( "TEST-" + className + ".xml" ) + .getFileInputStream(), "UTF-8" ); + return testResult.getChildren( "testcase" ); } - } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java index a5740c083a..4be28e742e 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire946KillMainProcessInReusableForkIT.java @@ -19,48 +19,124 @@ * under the License. */ +import com.googlecode.junittoolbox.ParallelParameterized; import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import org.w3c.dom.Document; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; +import java.io.File; +import java.util.ArrayList; + +import static org.fest.assertions.Assertions.assertThat; + +/** + * + */ +@RunWith( ParallelParameterized.class ) +@SuppressWarnings( "checkstyle:magicnumber" ) public class Surefire946KillMainProcessInReusableForkIT extends SurefireJUnit4IntegrationTestCase { - // there are 10 test classes that each would wait 2 seconds. - private static final int TEST_SLEEP_TIME = 2000; + private static final Object LOCK_DEPENDENCY = new Object(); + private static final Object LOCK_PLUGIN = new Object(); - @BeforeClass - public static void installSelfdestructPlugin() - { - unpack( Surefire946KillMainProcessInReusableForkIT.class, "surefire-946-self-destruct-plugin", "plugin" ).executeInstall(); - } + // there are 10 test classes that each would wait 3.5 seconds. + private static final int TEST_SLEEP_TIME = 3_500; + + private String classifierOfDummyDependency; - @Test( timeout = 30000 ) - public void testHalt() + @Parameter + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public String shutdownMavenMethod; + + @Parameter( 1 ) + @SuppressWarnings( "checkstyle:visibilitymodifier" ) + public String shutdownSurefireMethod; + + @Parameters( name = "{0}-{1}" ) + public static Iterable data() { - doTest( "halt" ); + ArrayList args = new ArrayList<>(); + args.add( new Object[] { "halt", "exit" } ); + args.add( new Object[] { "halt", "kill" } ); + args.add( new Object[] { "exit", "exit" } ); + args.add( new Object[] { "exit", "kill" } ); + args.add( new Object[] { "interrupt", "exit" } ); + args.add( new Object[] { "interrupt", "kill" } ); + return args; } - @Test( timeout = 30000 ) - public void testExit() + @BeforeClass + public static void installSelfdestructPlugin() { - doTest( "exit" ); + synchronized ( LOCK_PLUGIN ) + { + unpack( Surefire946KillMainProcessInReusableForkIT.class, "surefire-946-self-destruct-plugin", "plugin" ) + .executeInstall(); + } } - @Test( timeout = 30000 ) - public void testInterrupt() + @Before + public void dummyDep() { - doTest( "interrupt" ); + synchronized ( LOCK_DEPENDENCY ) + { + classifierOfDummyDependency = shutdownMavenMethod + shutdownSurefireMethod; + unpack( Surefire946KillMainProcessInReusableForkIT.class, + "surefire-946-dummy-dependency", classifierOfDummyDependency ) + .sysProp( "distinct.classifier", classifierOfDummyDependency ) + .executeInstall(); + } } - private void doTest( String method ) + @Test( timeout = 60_000 ) + public void test() throws Exception { - unpack( "surefire-946-killMainProcessInReusableFork" ) - .sysProp( "selfdestruct.timeoutInMillis", "5000" ) - .sysProp( "selfdestruct.method", method ) - .sysProp( "testSleepTime", String.valueOf( TEST_SLEEP_TIME ) ) - .addGoal( "org.apache.maven.plugins.surefire:maven-selfdestruct-plugin:selfdestruct" ) - .setForkJvm() - .forkPerThread().threadCount( 1 ).reuseForks( true ).maven().withFailure().executeTest(); + unpack( "surefire-946-killMainProcessInReusableFork", + "-" + shutdownMavenMethod + "-" + shutdownSurefireMethod ) + .sysProp( "distinct.classifier", classifierOfDummyDependency ) + .sysProp( "surefire.shutdown", shutdownSurefireMethod ) + .sysProp( "selfdestruct.timeoutInMillis", "10000" ) + .sysProp( "selfdestruct.method", shutdownMavenMethod ) + .sysProp( "testSleepTime", String.valueOf( TEST_SLEEP_TIME ) ) + .addGoal( "org.apache.maven.plugins.surefire:maven-selfdestruct-plugin:selfdestruct" ) + .setForkJvm() + .forkPerThread().threadCount( 1 ).reuseForks( true ).maven().withFailure().executeTest(); + + + XPathFactory xpathFactory = XPathFactory.newInstance(); + XPath xpath = xpathFactory.newXPath(); + File settings = new File( System.getProperty( "maven.settings.file" ) ).getCanonicalFile(); + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( settings ); + String localRepository = xpath.evaluate( "/settings/localRepository", doc ); + assertThat( localRepository ) + .isNotNull() + .isNotEmpty(); + + File dep = new File( localRepository, + "org/apache/maven/plugins/surefire/surefire-946-dummy-dependency/0.1/" + + "surefire-946-dummy-dependency-0.1-" + classifierOfDummyDependency + ".jar" ); + + assertThat( dep ) + .exists(); + + boolean deleted; + int iterations = 0; + do + { + Thread.sleep( 1_000L ); + deleted = dep.delete(); + } + while ( !deleted && ++iterations < 10 ); + assertThat( deleted ) + .isTrue(); } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire972BizarreNoClassDefIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire972BizarreNoClassDefIT.java index 94db9f89ed..9f93443731 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire972BizarreNoClassDefIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire972BizarreNoClassDefIT.java @@ -1,8 +1,5 @@ package org.apache.maven.surefire.its.jiras; -import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; -import org.junit.Test; - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -21,6 +18,13 @@ * specific language governing permissions and limitations * under the License. */ + +import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; +import org.junit.Test; + +/** + * + */ public class Surefire972BizarreNoClassDefIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire975DefaultVMEncodingIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire975DefaultVMEncodingIT.java index a53c6471d9..99fee3d422 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire975DefaultVMEncodingIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire975DefaultVMEncodingIT.java @@ -25,6 +25,9 @@ import static org.apache.maven.surefire.its.fixture.HelperAssertions.convertUnicodeToUTF8; +/** + * + */ public class Surefire975DefaultVMEncodingIT extends SurefireJUnit4IntegrationTestCase { diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire979WrongClassLoaderIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire979WrongClassLoaderIT.java index d6485769cc..6172130887 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire979WrongClassLoaderIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire979WrongClassLoaderIT.java @@ -23,17 +23,22 @@ import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase; import org.junit.Test; +/** + * + */ public class Surefire979WrongClassLoaderIT extends SurefireJUnit4IntegrationTestCase { - @Test public void wrongClassloaderUSedInSmartStacktraceparser() throws Exception { OutputValidator outputValidator = - unpack( "surefire-979-smartStackTrace-wrongClassloader" ).failNever().executeTest(); - outputValidator.verifyTextInLog( "java.lang.NoClassDefFoundError: org/apache/commons/io/input/AutoCloseInputStream" ); - } + unpack( "surefire-979-smartStackTrace-wrongClassloader" ) + .failNever() + .executeTest(); + outputValidator.verifyTextInLog( + "java.lang.NoClassDefFoundError: org/apache/commons/io/input/AutoCloseInputStream" ); + } } diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire985ParameterizedRunnerAndCategoriesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire985ParameterizedRunnerAndCategoriesIT.java index b86b2918b8..8d59cbe841 100644 --- a/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire985ParameterizedRunnerAndCategoriesIT.java +++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/jiras/Surefire985ParameterizedRunnerAndCategoriesIT.java @@ -32,6 +32,9 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +/** + * + */ public class Surefire985ParameterizedRunnerAndCategoriesIT extends SurefireJUnit4IntegrationTestCase { @@ -43,7 +46,8 @@ public void test() OutputValidator validator = unpack( "surefire-985-parameterized-and-categories" ).maven().executeTest(); validator.assertTestSuiteResults( 12, 0, 0, 0 ); - assertFalse( validator.getSurefireReportsXmlFile( "TEST-sample.parameterized.Parameterized01Test.xml" ).exists() ); + assertFalse( validator.getSurefireReportsXmlFile( "TEST-sample.parameterized.Parameterized01Test.xml" ) + .exists() ); TestFile reportFile2 = validator.getSurefireReportsXmlFile( "TEST-sample.parameterized.Parameterized02Test.xml" ); diff --git a/surefire-its/src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.SucceedingTest.xml b/surefire-its/src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.SucceedingTest.xml deleted file mode 100644 index 2801bf6d0d..0000000000 --- a/surefire-its/src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.SucceedingTest.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/surefire-its/src/test/resources/fixture/testsuitexmlparser/org.apache.maven.surefire.test.FailingTest.txt b/surefire-its/src/test/resources/fixture/testsuitexmlparser/org.apache.maven.surefire.test.FailingTest.txt deleted file mode 100644 index 38abc1fb73..0000000000 --- a/surefire-its/src/test/resources/fixture/testsuitexmlparser/org.apache.maven.surefire.test.FailingTest.txt +++ /dev/null @@ -1,84 +0,0 @@ -------------------------------------------------------------------------------- -Test set: org.apache.maven.surefire.test.FailingTest -------------------------------------------------------------------------------- -Tests run: 2, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.046 sec <<< FAILURE! -defaultTestValueIs_Value(org.apache.maven.surefire.test.FailingTest) Time elapsed: 0.013 sec <<< FAILURE! -java.lang.AssertionError: -Expected: "wrong" - got: "value" - - at org.junit.Assert.assertThat(Assert.java:778) - at org.junit.Assert.assertThat(Assert.java:736) - at org.apache.maven.surefire.test.FailingTest.defaultTestValueIs_Value(FailingTest.java:23) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:601) - at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) - at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) - at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) - at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) - at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) - at org.junit.rules.TestWatchman$1.evaluate(TestWatchman.java:48) - at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) - at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) - at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) - at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) - at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) - at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) - at org.junit.runners.ParentRunner.run(ParentRunner.java:236) - at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:262) - at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:151) - at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:122) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:601) - at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) - at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) - at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) - at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:128) - at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:88) - -setTestAndRetrieveValue(org.apache.maven.surefire.test.FailingTest) Time elapsed: 0.001 sec <<< FAILURE! -java.lang.AssertionError: -Expected: "bar" - got: "foo" - - at org.junit.Assert.assertThat(Assert.java:778) - at org.junit.Assert.assertThat(Assert.java:736) - at org.apache.maven.surefire.test.FailingTest.setTestAndRetrieveValue(FailingTest.java:34) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:601) - at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) - at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) - at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) - at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) - at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) - at org.junit.rules.TestWatchman$1.evaluate(TestWatchman.java:48) - at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71) - at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) - at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) - at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) - at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) - at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) - at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) - at org.junit.runners.ParentRunner.run(ParentRunner.java:236) - at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:262) - at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:151) - at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:122) - at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) - at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) - at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) - at java.lang.reflect.Method.invoke(Method.java:601) - at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) - at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) - at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) - at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:128) - at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:88) - diff --git a/surefire-its/src/test/resources/fixture/testsuitexmlparser/org.apache.maven.surefire.test.SucceedingTest.txt b/surefire-its/src/test/resources/fixture/testsuitexmlparser/org.apache.maven.surefire.test.SucceedingTest.txt deleted file mode 100644 index 9433827ead..0000000000 --- a/surefire-its/src/test/resources/fixture/testsuitexmlparser/org.apache.maven.surefire.test.SucceedingTest.txt +++ /dev/null @@ -1,4 +0,0 @@ -------------------------------------------------------------------------------- -Test set: org.apache.maven.surefire.test.SucceedingTest -------------------------------------------------------------------------------- -Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.044 sec diff --git a/surefire-its/src/test/resources/java9-full-api/pom.xml b/surefire-its/src/test/resources/java9-full-api/pom.xml index 2e4d4f34a1..ca27e2ba9f 100644 --- a/surefire-its/src/test/resources/java9-full-api/pom.xml +++ b/surefire-its/src/test/resources/java9-full-api/pom.xml @@ -32,8 +32,18 @@ java9-full-api + + UTF-8 + ${java.specification.version} + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + maven-surefire-plugin diff --git a/surefire-its/src/test/resources/junit-pathWithUmlaut/pom.xml b/surefire-its/src/test/resources/junit-pathWithUmlaut/pom.xml index ee654917c0..6c79c081ac 100644 --- a/surefire-its/src/test/resources/junit-pathWithUmlaut/pom.xml +++ b/surefire-its/src/test/resources/junit-pathWithUmlaut/pom.xml @@ -31,6 +31,7 @@ 1.7 1.7 + false @@ -53,6 +54,14 @@ maven-clean-plugin 3.0.0 + + maven-compiler-plugin + 3.8.1 + + ${skipCompiler} + ${skipCompiler} + + diff --git a/surefire-its/src/test/resources/junit-platform-engine-jqwik/pom.xml b/surefire-its/src/test/resources/junit-platform-engine-jqwik/pom.xml index 8e27d569a9..4631deafd8 100644 --- a/surefire-its/src/test/resources/junit-platform-engine-jqwik/pom.xml +++ b/surefire-its/src/test/resources/junit-platform-engine-jqwik/pom.xml @@ -42,7 +42,7 @@ net.jqwik jqwik - 0.8.10 + ${jqwik.version} test diff --git a/surefire-its/src/test/resources/junit-platform-engine-jupiter/pom.xml b/surefire-its/src/test/resources/junit-platform-engine-jupiter/pom.xml index 192cc8a9c9..a7128ae1dd 100644 --- a/surefire-its/src/test/resources/junit-platform-engine-jupiter/pom.xml +++ b/surefire-its/src/test/resources/junit-platform-engine-jupiter/pom.xml @@ -31,7 +31,7 @@ 1.8 1.8 - 5.2.0 + UTF-8 + + + 4.0.0 + + org.apache.maven.plugins.surefire + junit-platform-rerun-failing-tests + 1.0-SNAPSHOT + Test for rerun failing tests in JUnit 5/Platform + + + 1.8 + 1.8 + + + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.version} + + + + + diff --git a/surefire-its/src/test/resources/junit-platform-rerun-failing-tests/src/test/java/junitplatform/FlakyFirstTimeTest.java b/surefire-its/src/test/resources/junit-platform-rerun-failing-tests/src/test/java/junitplatform/FlakyFirstTimeTest.java new file mode 100644 index 0000000000..5c53d6d78e --- /dev/null +++ b/surefire-its/src/test/resources/junit-platform-rerun-failing-tests/src/test/java/junitplatform/FlakyFirstTimeTest.java @@ -0,0 +1,63 @@ +package junitplatform; + +/* + * 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.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.fail; + + +public class FlakyFirstTimeTest +{ + private static int failingCount = 0; + + private static int errorCount = 0; + + + @Test + public void testFailingTestOne() + { + System.out.println( "Failing test" ); + // This test will fail with only one retry, but will pass with two + if ( failingCount < 2 ) + { + failingCount++; + fail( "Failing test" ); + } + } + + @Test + public void testErrorTestOne() throws Exception + { + System.out.println( "Error test" ); + // This test will error out with only one retry, but will pass with two + if ( errorCount < 2 ) + { + errorCount++; + throw new IllegalArgumentException( "..." ); + } + } + + @Test + public void testPassingTest() throws Exception + { + System.out.println( "Passing test" ); + } +} diff --git a/surefire-its/src/test/resources/junit-platform-rerun-failing-tests/src/test/java/junitplatform/PassingTest.java b/surefire-its/src/test/resources/junit-platform-rerun-failing-tests/src/test/java/junitplatform/PassingTest.java new file mode 100644 index 0000000000..4f80f9fea0 --- /dev/null +++ b/surefire-its/src/test/resources/junit-platform-rerun-failing-tests/src/test/java/junitplatform/PassingTest.java @@ -0,0 +1,38 @@ +package junitplatform; + +/* + * 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.junit.jupiter.api.Test; + + +public class PassingTest +{ + @Test + public void testPassingTestOne() + { + System.out.println( "Passing test one" ); + } + + @Test + public void testPassingTestTwo() throws Exception + { + System.out.println( "Passing test two" ); + } +} diff --git a/surefire-its/src/test/resources/junit-platform-tags/pom.xml b/surefire-its/src/test/resources/junit-platform-tags/pom.xml index 0fb64cf129..cef7f35ffd 100644 --- a/surefire-its/src/test/resources/junit-platform-tags/pom.xml +++ b/surefire-its/src/test/resources/junit-platform-tags/pom.xml @@ -36,7 +36,7 @@ org.junit.jupiter junit-jupiter-engine - 5.2.0 + ${junit5.version} test @@ -54,4 +54,17 @@ + + + + oss-sonatype + oss-sonatype + https://oss.sonatype.org/content/repositories/snapshots/ + + true + always + ignore + + + diff --git a/surefire-its/src/test/resources/modulepath/pom.xml b/surefire-its/src/test/resources/modulepath/pom.xml index e4a7783ad0..f5cc763a70 100644 --- a/surefire-its/src/test/resources/modulepath/pom.xml +++ b/surefire-its/src/test/resources/modulepath/pom.xml @@ -10,7 +10,8 @@ app - 9 + UTF-8 + ${java.specification.version} @@ -18,7 +19,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.6.2 + 3.8.1 org.apache.maven.plugins diff --git a/surefire-its/src/test/resources/pojo-simple/src/test/java/PojoTest.java b/surefire-its/src/test/resources/pojo-simple/src/test/java/PojoTest.java index 8e13ecbec0..18fad81681 100644 --- a/surefire-its/src/test/resources/pojo-simple/src/test/java/PojoTest.java +++ b/surefire-its/src/test/resources/pojo-simple/src/test/java/PojoTest.java @@ -19,6 +19,17 @@ public class PojoTest { + private static int calls; + + public void setUp() + { + System.out.println( "setUp called " + ++calls ); + } + + public void tearDown() + { + System.out.println( "tearDown called " + calls ); + } public void testSuccess() { diff --git a/surefire-its/src/test/resources/pom.xml b/surefire-its/src/test/resources/pom.xml index e01ed4c0c2..6a3d7e890e 100644 --- a/surefire-its/src/test/resources/pom.xml +++ b/surefire-its/src/test/resources/pom.xml @@ -21,6 +21,7 @@ ${surefire.version} never + all @@ -28,6 +29,7 @@ ${surefire.version} never + all diff --git a/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/pom.xml b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/pom.xml new file mode 100644 index 0000000000..783dbf7bca --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + + org.apache.maven.surefire + it-parent + 1.0 + + surefire-1004-RunTestFromDependencyJarsTypeAndClassifier + 0.0.1-SNAPSHOT + pom + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + + + + surefire-1004-testjar + surefire-1004-module1 + + diff --git a/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-module1/pom.xml b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-module1/pom.xml new file mode 100644 index 0000000000..6986b5cbd9 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-module1/pom.xml @@ -0,0 +1,66 @@ + + 4.0.0 + + + org.apache.maven.surefire + surefire-1004-RunTestFromDependencyJarsTypeAndClassifier + 0.0.1-SNAPSHOT + ../ + + + org.apache.maven.plugins.surefire.dependency-jar + surefire-1004-module1 + 0.0.1-SNAPSHOT + + + + junit + junit + 4.8.1 + jar + test + + + + org.apache.maven.plugins.surefire.dependency-jar + surefire-1004-testjar + ${project.version} + test-jar + test + + + org.apache.maven.plugins.surefire.dependency-jar + surefire-1004-testjar + ${project.version} + othertests + test + + + org.apache.maven.plugins.surefire.dependency-jar + surefire-1004-testjar + ${project.version} + classifiedtests + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + *TestA* + + + + org.apache.maven.plugins.surefire.dependency-jar:surefire-1004-testjar:test-jar + org.apache.maven.plugins.surefire.dependency-jar:surefire-1004-testjar:*:classifiedtests + + + + + + diff --git a/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-module1/src/test/java/org/acme/tests/ClasspathTestA.java b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-module1/src/test/java/org/acme/tests/ClasspathTestA.java new file mode 100644 index 0000000000..eb73da5df7 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-module1/src/test/java/org/acme/tests/ClasspathTestA.java @@ -0,0 +1,36 @@ +package org.acme.tests; + +/* + * 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.junit.Test; + +public class ClasspathTestA +{ + + @Test + public void verifyAllTestClassesAreInClasspath() + throws Exception + { + Class.forName( "org.acme.tests.TestA" ); + Class.forName( "org.acme.tests.TestB" ); + Class.forName( "org.acme.othertests.OtherTestA" ); + Class.forName( "org.acme.classifiedtests.ClassifiedTestA" ); + } +} diff --git a/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/pom.xml b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/pom.xml new file mode 100644 index 0000000000..4467908ab7 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/pom.xml @@ -0,0 +1,71 @@ + + 4.0.0 + + + org.apache.maven.surefire + surefire-1004-RunTestFromDependencyJarsTypeAndClassifier + 0.0.1-SNAPSHOT + ../ + + + org.apache.maven.plugins.surefire.dependency-jar + surefire-1004-testjar + 0.0.1-SNAPSHOT + + + + junit + junit + 4.8.1 + jar + test + + + + + + + maven-jar-plugin + + + main-test-jar + + test-jar + + + **/tests/** + + + + other-test-jar + + test-jar + + + **/othertests/** + othertests + + + + classified-test-jar + + test-jar + + + **/classifiedtests/** + classifiedtests + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + diff --git a/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/classifiedtests/ClassifiedTestA.java b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/classifiedtests/ClassifiedTestA.java new file mode 100644 index 0000000000..a794470f01 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/classifiedtests/ClassifiedTestA.java @@ -0,0 +1,31 @@ +package org.acme.classifiedtests; + +/* + * 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.junit.Test; + +public class ClassifiedTestA +{ + + @Test + public void shouldRun() + { + } +} diff --git a/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/othertests/OtherTestA.java b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/othertests/OtherTestA.java new file mode 100644 index 0000000000..4f479cac16 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/othertests/OtherTestA.java @@ -0,0 +1,33 @@ +package org.acme.othertests; + +/* + * 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 static org.junit.Assert.*; +import org.junit.Test; + +public class OtherTestA +{ + + @Test + public void shouldNotRun() + { + fail( "This test should not run" ); + } +} diff --git a/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/tests/TestA.java b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/tests/TestA.java new file mode 100644 index 0000000000..efcb95698c --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/tests/TestA.java @@ -0,0 +1,31 @@ +package org.acme.tests; + +/* + * 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.junit.Test; + +public class TestA +{ + + @Test + public void shouldRun() + { + } +} diff --git a/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/tests/TestB.java b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/tests/TestB.java new file mode 100644 index 0000000000..ce620c9e38 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1004-RunTestFromDependencyJarsTypeAndClassifier/surefire-1004-testjar/src/test/java/org/acme/tests/TestB.java @@ -0,0 +1,31 @@ +package org.acme.tests; + +/* + * 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.junit.Test; + +public class TestB +{ + + @Test + public void shouldRun() + { + } +} diff --git a/surefire-its/src/test/resources/surefire-1152-rerunFailingTestsCount-suite/src/test/java/jiras/surefire1152/FlakyParent.java b/surefire-its/src/test/resources/surefire-1152-rerunFailingTestsCount-suite/src/test/java/jiras/surefire1152/FlakyParent.java index 86a08db845..eae008f708 100644 --- a/surefire-its/src/test/resources/surefire-1152-rerunFailingTestsCount-suite/src/test/java/jiras/surefire1152/FlakyParent.java +++ b/surefire-its/src/test/resources/surefire-1152-rerunFailingTestsCount-suite/src/test/java/jiras/surefire1152/FlakyParent.java @@ -29,17 +29,16 @@ public class FlakyParent { // set of test classes which have previously invoked testFlakyParent - private static final Set> previouslyRun = new HashSet>(); + private static final Set> PREVIOUSLY_RUN = new HashSet<>(); @Test public void testFlakyParent() { Class clazz = getClass(); - if ( !previouslyRun.contains( clazz ) ) + if ( !PREVIOUSLY_RUN.contains( clazz ) ) { - previouslyRun.add( clazz ); + PREVIOUSLY_RUN.add( clazz ); fail( "deliberately flaky test (should pass the next time)" ); } } - } diff --git a/surefire-its/src/test/resources/surefire-1265/pom.xml b/surefire-its/src/test/resources/surefire-1265/pom.xml index ec74a49d11..078e2f8742 100644 --- a/surefire-its/src/test/resources/surefire-1265/pom.xml +++ b/surefire-its/src/test/resources/surefire-1265/pom.xml @@ -34,8 +34,7 @@ UTF-8 - 9 - 9 + ${java.specification.version} @@ -46,4 +45,14 @@ test + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + + diff --git a/surefire-its/src/test/resources/surefire-1396-pluggableproviders-classpath-provider/src/main/java/org/apache/maven/surefire/testprovider/ClassPathTestProvider.java b/surefire-its/src/test/resources/surefire-1396-pluggableproviders-classpath-provider/src/main/java/org/apache/maven/surefire/testprovider/ClassPathTestProvider.java index eeea39773b..2a15e17bfb 100644 --- a/surefire-its/src/test/resources/surefire-1396-pluggableproviders-classpath-provider/src/main/java/org/apache/maven/surefire/testprovider/ClassPathTestProvider.java +++ b/surefire-its/src/test/resources/surefire-1396-pluggableproviders-classpath-provider/src/main/java/org/apache/maven/surefire/testprovider/ClassPathTestProvider.java @@ -20,7 +20,7 @@ */ import java.lang.reflect.InvocationTargetException; -import java.util.LinkedList; +import java.util.Collections; import java.util.Map.Entry; import org.apache.maven.surefire.providerapi.AbstractProvider; @@ -42,21 +42,24 @@ public ClassPathTestProvider( ProviderParameters params ) for ( Entry propEntry : params.getProviderProperties().entrySet() ) { if ( propEntry.getKey().startsWith( "surefireClassPathUrl" ) && propEntry.getValue().contains( "slf4j" ) ) + { hasSLF4J = true; + } } } public Iterable> getSuites() { - LinkedList> ret = new LinkedList>(); - return ret; + return Collections.>emptySet(); } public RunResult invoke( Object arg0 ) throws TestSetFailedException, ReporterException, InvocationTargetException { if ( hasSLF4J ) + { throw new TestSetFailedException( "SLF4J was found on the boot classpath" ); + } return new RunResult( 1, 0, 0, 0 ); } 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 0000000000..0f5d354735 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1534-reuse-forks-false-java-module/pom.xml @@ -0,0 +1,74 @@ + + + + + + 4.0.0 + + org.apache.maven.plugins.surefire + surefire-1534 + 1.0 + + + UTF-8 + ${java.specification.version} + 5.3.2 + + + + + Mark Soderquist (mvsoder) + https://github.com/mvsoder + + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.version} + + + + + 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 0000000000..86491ffe5e --- /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 0000000000..3df6ca96b7 --- /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 0000000000..fbc0e07b09 --- /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-its/src/test/resources/surefire-1585-junit4-vintage/pom.xml b/surefire-its/src/test/resources/surefire-1585-junit4-vintage/pom.xml new file mode 100644 index 0000000000..7bdf148434 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1585-junit4-vintage/pom.xml @@ -0,0 +1,61 @@ + + + + + 4.0.0 + + org.apache.maven.plugins.surefire + surefire-1585-junit4-vintage-it + 1.0 + + + 1.8 + 1.8 + 5.4.0 + + + + + junit + junit + 4.12 + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.version} + + + org.junit.vintage + junit-vintage-engine + ${junit.vintage.version} + + + + + + diff --git a/surefire-its/src/test/resources/surefire-1585-junit4-vintage/src/test/java/JUnit4Test.java b/surefire-its/src/test/resources/surefire-1585-junit4-vintage/src/test/java/JUnit4Test.java new file mode 100644 index 0000000000..d0c1ff46c9 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1585-junit4-vintage/src/test/java/JUnit4Test.java @@ -0,0 +1,28 @@ +/* + * 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.junit.Test; + +public class JUnit4Test +{ + @Test + public void test() + { + } +} diff --git a/surefire-its/src/test/resources/surefire-1585-jupiter-api/pom.xml b/surefire-its/src/test/resources/surefire-1585-jupiter-api/pom.xml new file mode 100644 index 0000000000..652ae493b3 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1585-jupiter-api/pom.xml @@ -0,0 +1,54 @@ + + + + + 4.0.0 + + org.apache.maven.plugins.surefire + surefire-1585-jupiter-api-it + 1.0 + + + 1.8 + 1.8 + 5.4.0 + + + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.version} + + + + diff --git a/surefire-its/src/test/resources/surefire-1585-jupiter-api/src/test/java/JupiterTest.java b/surefire-its/src/test/resources/surefire-1585-jupiter-api/src/test/java/JupiterTest.java new file mode 100644 index 0000000000..398141c659 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1585-jupiter-api/src/test/java/JupiterTest.java @@ -0,0 +1,32 @@ +/* + * 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 static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; + +class JupiterTest +{ + @Test + void test( TestInfo info ) + { + assertEquals( "test(TestInfo)", info.getDisplayName(), "display name mismatch" ); + } +} diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/pom.xml b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/pom.xml new file mode 100644 index 0000000000..d75fe8e9fe --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/pom.xml @@ -0,0 +1,62 @@ + + + + + 4.0.0 + + abc + xyz + 1.0 + + + UTF-8 + ${java.specification.version} + + + + + org.hamcrest + hamcrest + 2.1 + + + org.junit.jupiter + junit-jupiter-engine + 5.5.2 + test + + + + + + + maven-compiler-plugin + 3.8.1 + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.version} + + + + diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/main/java/module-info.java b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/main/java/module-info.java new file mode 100644 index 0000000000..a0b358835c --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/main/java/module-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +module wtf.g4s8.oot +{ + exports wtf.g4s8.oot; +} diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/main/java/wtf/g4s8/oot/Foo.java b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/main/java/wtf/g4s8/oot/Foo.java new file mode 100644 index 0000000000..1540031acc --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/main/java/wtf/g4s8/oot/Foo.java @@ -0,0 +1,35 @@ +package wtf.g4s8.oot; + +/* + * 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. + */ + +public final class Foo +{ + private final int base; + + public Foo( int base ) + { + this.base = base; + } + + public int add( final int x ) + { + return this.base + x; + } +} diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java new file mode 100644 index 0000000000..7bbf986c98 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/module-info.java @@ -0,0 +1,25 @@ +/* + * 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. + */ + +module wtf.g4s8.oot.test +{ + requires wtf.g4s8.oot; + requires org.junit.jupiter.api; + requires transitive org.hamcrest; +} diff --git a/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/wtf/g4s8/oot/test/FooTest.java b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/wtf/g4s8/oot/test/FooTest.java new file mode 100644 index 0000000000..d8aa49dc38 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-1712-extracted-modulename-without-asm/src/test/java/wtf/g4s8/oot/test/FooTest.java @@ -0,0 +1,35 @@ +package wtf.g4s8.oot.test; + +/* + * 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.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import wtf.g4s8.oot.Foo; + +import static org.hamcrest.MatcherAssert.assertThat; + +public class FooTest +{ + @Test + public void addTest() + { + assertThat( new Foo( 1 ).add( 1 ), Matchers.equalTo( 2 ) ); + } +} diff --git a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports2/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml similarity index 100% rename from surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml rename to surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports2/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml diff --git a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports2/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt similarity index 86% rename from surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt rename to surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports2/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt index 9964f13275..7a2f98983b 100644 --- a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt +++ b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module1/src/test/resources/surefire-reports2/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt @@ -2,7 +2,7 @@ Test set: org.apache.maven.surefireReport.surefireReportTest.module1.MyDummyClassTest ------------------------------------------------------------------------------- Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.049 sec <<< FAILURE! -testGetFooKO(org.apache.maven.surefireReport.surefireReportTest.module1.MyDummyClassTest) Time elapsed: 0.01 sec <<< FAILURE! +org.apache.maven.surefireReport.surefireReportTest.module1.MyDummyClassTest.testGetFooKO Time elapsed: 0.01 sec <<< FAILURE! junit.framework.AssertionFailedError: expected:<18> but was:<42> at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.failNotEquals(Assert.java:280) diff --git a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports2/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml similarity index 97% rename from surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml rename to surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports2/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml index 2c9cbed200..d90475a72f 100644 --- a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml +++ b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports2/TEST-org.apache.maven.surefireReport.surefireReportTest.MyClassTest.xml @@ -57,7 +57,7 @@ - + junit.framework.AssertionFailedError: expected:<18> but was:<42> at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.failNotEquals(Assert.java:280) @@ -67,5 +67,5 @@ at org.apache.maven.surefireReport.surefireReportTest.module1.MyDummyClassTest.testGetFooKO(MyClassTest.java:10) - + diff --git a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports2/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt similarity index 86% rename from surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt rename to surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports2/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt index 9964f13275..7a2f98983b 100644 --- a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt +++ b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/module2/src/test/resources/surefire-reports2/org.apache.maven.surefireReport.surefireReportTest.MyClassTest.txt @@ -2,7 +2,7 @@ Test set: org.apache.maven.surefireReport.surefireReportTest.module1.MyDummyClassTest ------------------------------------------------------------------------------- Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.049 sec <<< FAILURE! -testGetFooKO(org.apache.maven.surefireReport.surefireReportTest.module1.MyDummyClassTest) Time elapsed: 0.01 sec <<< FAILURE! +org.apache.maven.surefireReport.surefireReportTest.module1.MyDummyClassTest.testGetFooKO Time elapsed: 0.01 sec <<< FAILURE! junit.framework.AssertionFailedError: expected:<18> but was:<42> at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.failNotEquals(Assert.java:280) diff --git a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/pom.xml b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/pom.xml index b3238ea69c..ba51625470 100644 --- a/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/pom.xml +++ b/surefire-its/src/test/resources/surefire-570-multipleReportDirectories/pom.xml @@ -45,7 +45,7 @@ ${basedir}/target/surefire-reports - ${basedir}/src/test/resources/surefire-reports + ${basedir}/src/test/resources/surefire-reports2 @@ -96,7 +96,7 @@ ${basedir}/target/surefire-reports - ${basedir}/src/test/resources/surefire-reports + ${basedir}/src/test/resources/surefire-reports2 diff --git a/surefire-its/src/test/resources/surefire-946-dummy-dependency/pom.xml b/surefire-its/src/test/resources/surefire-946-dummy-dependency/pom.xml new file mode 100644 index 0000000000..d2fdf862a1 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-946-dummy-dependency/pom.xml @@ -0,0 +1,39 @@ + + 4.0.0 + + org.apache.maven.plugins.surefire + surefire-946-dummy-dependency + 0.1 + + + UTF-8 + 1.7 + 1.7 + + + + + + + maven-surefire-plugin + ${surefire.version} + + true + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + ${distinct.classifier} + + + + + diff --git a/surefire-its/src/test/resources/surefire-946-dummy-dependency/src/main/java/dummy/DummyClass.java b/surefire-its/src/test/resources/surefire-946-dummy-dependency/src/main/java/dummy/DummyClass.java new file mode 100644 index 0000000000..014cabb067 --- /dev/null +++ b/surefire-its/src/test/resources/surefire-946-dummy-dependency/src/main/java/dummy/DummyClass.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package dummy; + +/** + * + */ +public class DummyClass +{ + @Override + public String toString() + { + return "JVM handles a file handler to 'surefire-946-dummy-dependency-0.1.jar'."; + } +} \ No newline at end of file diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/pom.xml b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/pom.xml index 53bb0a3522..2240fe4083 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/pom.xml +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/pom.xml @@ -27,11 +27,18 @@ Tests killing the main maven process when using reusable forks + UTF-8 1.7 1.7 + + org.apache.maven.plugins.surefire + surefire-946-dummy-dependency + 0.1 + ${distinct.classifier} + junit junit diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java index 8c52d1b482..77971fd31f 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic01Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic01Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic02Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic02Test.java index 6ef33f9b06..1133efea0a 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic02Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic02Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic02Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic03Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic03Test.java index b1d7c7122b..15b1bd9e75 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic03Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic03Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic03Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic04Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic04Test.java index 6d082cb930..41513369b2 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic04Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic04Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic04Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic05Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic05Test.java index 92f5f158e6..3f142611fc 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic05Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic05Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic05Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic06Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic06Test.java index 2a44568559..1925665f08 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic06Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic06Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic06Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic07Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic07Test.java index 64f180ef42..77436bb4f7 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic07Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic07Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic07Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic08Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic08Test.java index 5a4c382591..ed62c32560 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic08Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic08Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic08Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic09Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic09Test.java index 2461d116ba..87043e2891 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic09Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic09Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic09Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic10Test.java b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic10Test.java index 1e57b135d7..d481da7f5a 100644 --- a/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic10Test.java +++ b/surefire-its/src/test/resources/surefire-946-killMainProcessInReusableFork/src/test/java/junit44/environment/Basic10Test.java @@ -19,6 +19,7 @@ * under the License. */ +import dummy.DummyClass; import org.junit.AfterClass; import org.junit.Test; @@ -28,6 +29,7 @@ public class Basic10Test @Test public void testNothing() { + System.out.println( new DummyClass().toString() ); } @AfterClass diff --git a/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/pom.xml b/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/pom.xml index ad4ff008f1..5abb0524bb 100644 --- a/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/pom.xml +++ b/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/pom.xml @@ -22,12 +22,6 @@ maven-plugin-api 2.0 - - junit - junit - 3.8.1 - test - diff --git a/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/src/main/java/org/apache/maven/plugins/surefire/selfdestruct/SelfDestructMojo.java b/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/src/main/java/org/apache/maven/plugins/surefire/selfdestruct/SelfDestructMojo.java index 61016dea2f..f54620662b 100644 --- a/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/src/main/java/org/apache/maven/plugins/surefire/selfdestruct/SelfDestructMojo.java +++ b/surefire-its/src/test/resources/surefire-946-self-destruct-plugin/src/main/java/org/apache/maven/plugins/surefire/selfdestruct/SelfDestructMojo.java @@ -64,7 +64,7 @@ private enum DestructMethod * * @parameter */ - private long timeoutInMillis = 0; + private long timeoutInMillis; /** * Method of self-destruction: 'exit' will use System.exit (default), 'halt' will use Runtime.halt, 'interrupt' will @@ -77,7 +77,6 @@ private enum DestructMethod public void execute() throws MojoExecutionException { - DestructMethod destructMethod = DestructMethod.valueOf( method ); if ( timeoutInMillis > 0 ) @@ -94,7 +93,7 @@ public void execute() private void selfDestruct( DestructMethod destructMethod ) { - getLog().warn( "Self-Destructing NOW." ); + getLog().warn( "[" + destructMethod + "] Self-Destructing NOW." ); switch ( destructMethod ) { case exit: @@ -143,10 +142,9 @@ private void selfDestruct( DestructMethod destructMethod ) private class SelfDestructionTask extends TimerTask { + private final DestructMethod destructMethod; - private DestructMethod destructMethod; - - public SelfDestructionTask( DestructMethod destructMethod ) + SelfDestructionTask( DestructMethod destructMethod ) { this.destructMethod = destructMethod; } @@ -156,6 +154,5 @@ public void run() { selfDestruct( destructMethod ); } - } } diff --git a/surefire-its/src/test/resources/testng-parallel-with-annotations/src/test/java/testng/paralellwithannotations/TestNGParallelTest.java b/surefire-its/src/test/resources/testng-parallel-with-annotations/src/test/java/testng/paralellwithannotations/TestNGParallelTest.java index e6904e9b5d..0de33d60b3 100644 --- a/surefire-its/src/test/resources/testng-parallel-with-annotations/src/test/java/testng/paralellwithannotations/TestNGParallelTest.java +++ b/surefire-its/src/test/resources/testng-parallel-with-annotations/src/test/java/testng/paralellwithannotations/TestNGParallelTest.java @@ -25,16 +25,19 @@ import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; import java.util.Date; +import java.util.concurrent.atomic.AtomicInteger; /** * Test that parallel tests actually run and complete within the expected time. */ public class TestNGParallelTest { - - static int testCount = 0; - - static long startTime; + private static final long DELAY = 3_000L; + private static final int THREAD_POOL_SIZE = 2; + private static final int INVOCATION_COUNT = 3; + private static final AtomicInteger TEST_COUNT = new AtomicInteger(); + private static int testCount = 0; + private static long startTime; @BeforeSuite( alwaysRun = true ) public void startClock() @@ -47,23 +50,19 @@ public void checkTestResults() { long runtime = new Date().getTime() - startTime; System.out.println( "Runtime was: " + runtime ); - assertTrue( testCount == 3, "Expected test to be run 3 times, but was " + testCount ); - // Note, this can be < 1000 on Windows. - assertTrue( runtime < 1400, "Runtime was " + runtime + ". It should be a little over 1000ms" ); + long testCount = TEST_COUNT.get(); + assertTrue( testCount == INVOCATION_COUNT, "Expected test to be run 3 times, but was " + testCount ); + // Note, this can be < 6000 on Windows. + assertTrue( runtime < INVOCATION_COUNT * DELAY - 300L, + "Runtime was " + runtime + ". It should be a little over 3000ms but less than 6000ms." ); } - @Test( threadPoolSize = 2, invocationCount = 3 ) + @Test( threadPoolSize = THREAD_POOL_SIZE, invocationCount = INVOCATION_COUNT ) public void incrementTestCountAndSleepForOneSecond() throws InterruptedException { - incrementTestCount(); - Thread.sleep( 500 ); + TEST_COUNT.incrementAndGet(); + Thread.sleep( DELAY ); System.out.println( "Ran test" ); } - - private synchronized void incrementTestCount() - { - testCount++; - } - } diff --git a/surefire-logger-api/pom.xml b/surefire-logger-api/pom.xml index e7d1042544..6b158174b1 100644 --- a/surefire-logger-api/pom.xml +++ b/surefire-logger-api/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 surefire-logger-api @@ -49,4 +49,48 @@ - \ No newline at end of file + + + org.mockito + mockito-core + test + + + + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + + **/JUnit4SuiteTest.java + + + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + + + + + + diff --git a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerDecorator.java b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerDecorator.java index 02105fa434..0ab20cc0c9 100644 --- a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerDecorator.java +++ b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerDecorator.java @@ -1 +1,148 @@ -package org.apache.maven.plugin.surefire.log.api; /* * 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. */ /** * Decorator around {@link ConsoleLogger}. * This class is loaded in the isolated ClassLoader and the child logger in the in-plugin ClassLoader. * * @author Tibor Digana (tibor17) * @since 2.20 */ public final class ConsoleLoggerDecorator implements ConsoleLogger { private final Object logger; public ConsoleLoggerDecorator( Object logger ) { if ( logger == null ) { throw new NullPointerException( "logger argument is null in " + ConsoleLoggerDecorator.class ); } this.logger = logger; } @Override public boolean isDebugEnabled() { try { return (Boolean) logger.getClass() .getMethod( "isDebugEnabled" ) .invoke( logger ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public void debug( String message ) { try { logger.getClass() .getMethod( "debug", String.class ) .invoke( logger, message ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public boolean isInfoEnabled() { try { return (Boolean) logger.getClass() .getMethod( "isInfoEnabled" ) .invoke( logger ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public void info( String message ) { try { logger.getClass() .getMethod( "info", String.class ) .invoke( logger, message ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public boolean isWarnEnabled() { try { return (Boolean) logger.getClass() .getMethod( "isWarnEnabled" ) .invoke( logger ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public void warning( String message ) { try { logger.getClass() .getMethod( "warning", String.class ) .invoke( logger, message ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public boolean isErrorEnabled() { try { return (Boolean) logger.getClass() .getMethod( "isErrorEnabled" ) .invoke( logger ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public void error( String message ) { try { logger.getClass() .getMethod( "error", String.class ) .invoke( logger, message ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public void error( String message, Throwable t ) { try { logger.getClass() .getMethod( "error", String.class, Throwable.class ) .invoke( logger, message, t ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } @Override public void error( Throwable t ) { try { logger.getClass() .getMethod( "error", Throwable.class ) .invoke( logger, t ); } catch ( Exception e ) { throw new IllegalStateException( e.getLocalizedMessage(), e ); } } } \ No newline at end of file +package org.apache.maven.plugin.surefire.log.api; + +/* + * 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. + */ + +/** + * Decorator around {@link ConsoleLogger}. + * This class is loaded in the isolated ClassLoader and the child logger in the in-plugin ClassLoader. + * + * @author Tibor Digana (tibor17) + * @since 2.20 + */ +public final class ConsoleLoggerDecorator + implements ConsoleLogger +{ + private final Object logger; + + public ConsoleLoggerDecorator( Object logger ) + { + if ( logger == null ) + { + throw new NullPointerException( "logger argument is null in " + ConsoleLoggerDecorator.class ); + } + this.logger = logger; + } + + @Override + public boolean isDebugEnabled() + { + return invokeReturnedBoolean( "isDebugEnabled" ); + } + + @Override + public void debug( String message ) + { + invokeWithMessage( message, "debug" ); + } + + @Override + public boolean isInfoEnabled() + { + return invokeReturnedBoolean( "isInfoEnabled" ); + } + + @Override + public void info( String message ) + { + invokeWithMessage( message, "info" ); + } + + @Override + public boolean isWarnEnabled() + { + return invokeReturnedBoolean( "isWarnEnabled" ); + } + + @Override + public void warning( String message ) + { + invokeWithMessage( message, "warning" ); + } + + @Override + public boolean isErrorEnabled() + { + return invokeReturnedBoolean( "isErrorEnabled" ); + } + + @Override + public void error( String message ) + { + invokeWithMessage( message, "error" ); + } + + @Override + public void error( String message, Throwable t ) + { + try + { + logger.getClass() + .getMethod( "error", String.class, Throwable.class ) + .invoke( logger, message, t ); + } + catch ( Exception e ) + { + throw new IllegalStateException( e.getLocalizedMessage(), e ); + } + } + + @Override + public void error( Throwable t ) + { + try + { + logger.getClass() + .getMethod( "error", Throwable.class ) + .invoke( logger, t ); + } + catch ( Exception e ) + { + throw new IllegalStateException( e.getLocalizedMessage(), e ); + } + } + + private boolean invokeReturnedBoolean( String isErrorEnabled ) + { + try + { + return (Boolean) logger.getClass() + .getMethod( isErrorEnabled ) + .invoke( logger ); + } + catch ( Exception e ) + { + throw new IllegalStateException( e.getLocalizedMessage(), e ); + } + } + + private void invokeWithMessage( String message, String error ) + { + try + { + logger.getClass() + .getMethod( error, String.class ) + .invoke( logger, message ); + } + catch ( Exception e ) + { + throw new IllegalStateException( e.getLocalizedMessage(), e ); + } + } +} diff --git a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtils.java b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtils.java index 976a48cb31..df2d44fd3b 100644 --- a/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtils.java +++ b/surefire-logger-api/src/main/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtils.java @@ -33,6 +33,11 @@ private ConsoleLoggerUtils() throw new IllegalStateException( "non instantiable constructor" ); } + public static String toString( Throwable t ) + { + return toString( null, t ); + } + public static String toString( String message, Throwable t ) { StringWriter result = new StringWriter( 512 ); diff --git a/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtilsTest.java b/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtilsTest.java new file mode 100644 index 0000000000..902a17eb82 --- /dev/null +++ b/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/ConsoleLoggerUtilsTest.java @@ -0,0 +1,64 @@ +package org.apache.maven.plugin.surefire.log.api; + +/* + * 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.junit.Test; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import static org.fest.assertions.Assertions.assertThat; + +/** + * Tests for {@link ConsoleLoggerUtils}. + */ +public class ConsoleLoggerUtilsTest +{ + @Test + public void shouldPrintStacktraceAsString() + { + Exception e = new IllegalArgumentException( "wrong param" ); + String msg = ConsoleLoggerUtils.toString( e ); + + StringWriter text = new StringWriter(); + PrintWriter writer = new PrintWriter( text ); + e.printStackTrace( writer ); + String s = text.toString(); + + assertThat( msg ) + .isEqualTo( s ); + } + + @Test + public void shouldPrintStacktracWithMessageAsString() + { + Exception e = new IllegalArgumentException( "wrong param" ); + String msg = ConsoleLoggerUtils.toString( "issue", e ); + + StringWriter text = new StringWriter(); + PrintWriter writer = new PrintWriter( text ); + writer.println( "issue" ); + e.printStackTrace( writer ); + String s = text.toString(); + + assertThat( msg ) + .isEqualTo( s ); + } +} diff --git a/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/JUnit4SuiteTest.java b/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/JUnit4SuiteTest.java new file mode 100644 index 0000000000..69665a3108 --- /dev/null +++ b/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/JUnit4SuiteTest.java @@ -0,0 +1,43 @@ +package org.apache.maven.plugin.surefire.log.api; + +/* + * 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 junit.framework.JUnit4TestAdapter; +import junit.framework.Test; +import junit.framework.TestCase; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite. + * + * @author Tibor Digana (tibor17) + * @since 3.0.0-M4 + */ +@SuiteClasses( { ConsoleLoggerUtilsTest.class, LevelTest.class, LoggersTest.class } ) +@RunWith( Suite.class ) +public class JUnit4SuiteTest extends TestCase +{ + public static Test suite() + { + return new JUnit4TestAdapter( JUnit4SuiteTest.class ); + } +} diff --git a/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/LevelTest.java b/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/LevelTest.java new file mode 100644 index 0000000000..0f488801e6 --- /dev/null +++ b/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/LevelTest.java @@ -0,0 +1,73 @@ +package org.apache.maven.plugin.surefire.log.api; + +/* + * 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.junit.Test; + +import static org.apache.maven.plugin.surefire.log.api.Level.resolveLevel; +import static org.fest.assertions.Assertions.assertThat; + +/** + * Tests for {@link Level}. + */ +public class LevelTest +{ + @Test + public void shouldHaveSuccess() + { + Level level = resolveLevel( true, false, false, false, false ); + assertThat( level ).isEqualTo( Level.SUCCESS ); + } + + @Test + public void shouldNotHaveSuccess() + { + Level level = resolveLevel( false, false, false, false, false ); + assertThat( level ).isEqualTo( Level.NO_COLOR ); + } + + @Test + public void shouldBeFailure() + { + Level level = resolveLevel( false, true, false, false, false ); + assertThat( level ).isEqualTo( Level.FAILURE ); + } + + @Test + public void shouldBeError() + { + Level level = resolveLevel( false, false, true, false, false ); + assertThat( level ).isEqualTo( Level.FAILURE ); + } + + @Test + public void shouldBeSkipped() + { + Level level = resolveLevel( false, false, false, true, false ); + assertThat( level ).isEqualTo( Level.UNSTABLE ); + } + + @Test + public void shouldBeFlake() + { + Level level = resolveLevel( false, false, false, false, true ); + assertThat( level ).isEqualTo( Level.UNSTABLE ); + } +} diff --git a/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/LoggersTest.java b/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/LoggersTest.java new file mode 100644 index 0000000000..192d209913 --- /dev/null +++ b/surefire-logger-api/src/test/java/org/apache/maven/plugin/surefire/log/api/LoggersTest.java @@ -0,0 +1,137 @@ +package org.apache.maven.plugin.surefire.log.api; + +/* + * 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.junit.Test; +import org.mockito.ArgumentCaptor; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link ConsoleLoggerDecorator}, {@link NullConsoleLogger} and {@link PrintStreamLogger}. + */ +public class LoggersTest +{ + @Test + public void testPrintStreamLogger() + { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream( outputStream ); + PrintStreamLogger logger = new PrintStreamLogger( printStream ); + + + assertThat( logger.isErrorEnabled() ).isTrue(); + assertThat( logger.isWarnEnabled() ).isTrue(); + assertThat( logger.isInfoEnabled() ).isTrue(); + assertThat( logger.isDebugEnabled() ).isTrue(); + + logger.error( "error" ); + logger.debug( "debug" ); + logger.info( "info" ); + logger.warning( "warning" ); + + String line = System.lineSeparator(); + assertThat( outputStream.toString() ) + .isEqualTo( "error" + line + "debug" + line + "info" + line + "warning" + line ); + + Exception e = new Exception( "exception" ); + outputStream.reset(); + logger.error( e ); + assertThat( outputStream.toString() ) + .contains( "java.lang.Exception: exception" ) + .contains( "at " + getClass().getName() + ".testPrintStreamLogger(LoggersTest.java:61)" ); + } + + @Test( expected = NullPointerException.class ) + public void shouldThrowNPE() + { + new ConsoleLoggerDecorator( null ); + } + + @Test + public void testDecorator() + { + ConsoleLogger logger = mock( ConsoleLogger.class ); + ConsoleLoggerDecorator decorator = new ConsoleLoggerDecorator( logger ); + + assertThat( decorator.isDebugEnabled() ).isFalse(); + when( logger.isDebugEnabled() ).thenReturn( true ); + assertThat( decorator.isDebugEnabled() ).isTrue(); + + assertThat( decorator.isInfoEnabled() ).isFalse(); + when( logger.isInfoEnabled() ).thenReturn( true ); + assertThat( decorator.isInfoEnabled() ).isTrue(); + + assertThat( decorator.isWarnEnabled() ).isFalse(); + when( logger.isWarnEnabled() ).thenReturn( true ); + assertThat( decorator.isWarnEnabled() ).isTrue(); + + assertThat( decorator.isErrorEnabled() ).isFalse(); + when( logger.isErrorEnabled() ).thenReturn( true ); + assertThat( decorator.isErrorEnabled() ).isTrue(); + + ArgumentCaptor argumentMsg = ArgumentCaptor.forClass( String.class ); + decorator.debug( "debug" ); + verify( logger, times( 1 ) ).debug( argumentMsg.capture() ); + assertThat( argumentMsg.getAllValues() ).hasSize( 1 ); + assertThat( argumentMsg.getAllValues().get( 0 ) ).isEqualTo( "debug" ); + + argumentMsg = ArgumentCaptor.forClass( String.class ); + decorator.info( "info" ); + verify( logger, times( 1 ) ).info( argumentMsg.capture() ); + assertThat( argumentMsg.getAllValues() ).hasSize( 1 ); + assertThat( argumentMsg.getAllValues().get( 0 ) ).isEqualTo( "info" ); + + argumentMsg = ArgumentCaptor.forClass( String.class ); + decorator.warning( "warning" ); + verify( logger, times( 1 ) ).warning( argumentMsg.capture() ); + assertThat( argumentMsg.getAllValues() ).hasSize( 1 ); + assertThat( argumentMsg.getAllValues().get( 0 ) ).isEqualTo( "warning" ); + + argumentMsg = ArgumentCaptor.forClass( String.class ); + decorator.error( "error" ); + verify( logger, times( 1 ) ).error( argumentMsg.capture() ); + assertThat( argumentMsg.getAllValues() ).hasSize( 1 ); + assertThat( argumentMsg.getAllValues().get( 0 ) ).isEqualTo( "error" ); + + ArgumentCaptor argumentThrowable = ArgumentCaptor.forClass( Throwable.class ); + argumentMsg = ArgumentCaptor.forClass( String.class ); + Exception e = new Exception(); + decorator.error( "error", e ); + verify( logger, times( 1 ) ).error( argumentMsg.capture(), argumentThrowable.capture() ); + assertThat( argumentMsg.getAllValues() ).hasSize( 1 ); + assertThat( argumentMsg.getAllValues().get( 0 ) ).isEqualTo( "error" ); + assertThat( argumentThrowable.getAllValues() ).hasSize( 1 ); + assertThat( argumentThrowable.getAllValues().get( 0 ) ).isSameAs( e ); + + argumentThrowable = ArgumentCaptor.forClass( Throwable.class ); + decorator.error( e ); + verify( logger, times( 1 ) ).error( argumentThrowable.capture() ); + assertThat( argumentThrowable.getAllValues() ).hasSize( 1 ); + assertThat( argumentThrowable.getAllValues().get( 0 ) ).isSameAs( e ); + } +} diff --git a/surefire-providers/common-java5/pom.xml b/surefire-providers/common-java5/pom.xml index 942b0dc308..199aa30ea8 100644 --- a/surefire-providers/common-java5/pom.xml +++ b/surefire-providers/common-java5/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 common-java5 @@ -40,6 +40,21 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-shade-plugin @@ -57,8 +72,8 @@ - org.apache.maven.shared - org.apache.maven.surefire.shade.java5.org.apache.maven.shared + org.apache.maven.shared.utils + org.apache.maven.surefire.shade.java5.org.apache.maven.shared.utils @@ -68,10 +83,15 @@ maven-surefire-plugin - - **/fixture/** - + ${jvm.args.tests} ${jacoco.agent} + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + diff --git a/surefire-providers/common-java5/src/main/java/org/apache/maven/surefire/report/PojoStackTraceWriter.java b/surefire-providers/common-java5/src/main/java/org/apache/maven/surefire/report/PojoStackTraceWriter.java index 626392b8ed..2f369e84a9 100644 --- a/surefire-providers/common-java5/src/main/java/org/apache/maven/surefire/report/PojoStackTraceWriter.java +++ b/surefire-providers/common-java5/src/main/java/org/apache/maven/surefire/report/PojoStackTraceWriter.java @@ -24,6 +24,7 @@ import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Objects; /** * Write the trace out for a POJO test. @@ -109,4 +110,27 @@ private static boolean isMultiLineExceptionMessage( Throwable t ) } return false; } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + PojoStackTraceWriter that = ( PojoStackTraceWriter ) o; + return Objects.equals( t, that.t ) + && Objects.equals( testClass, that.testClass ) + && Objects.equals( testMethod, that.testMethod ); + } + + @Override + public int hashCode() + { + return Objects.hash( t, testClass, testMethod ); + } } diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ABaseClass.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ABaseClass.java index c4387d2d46..3f8692d5e0 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ABaseClass.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ABaseClass.java @@ -19,7 +19,9 @@ * under the License. */ - +/** + * + */ public class ABaseClass { public void npe() diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ASubClass.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ASubClass.java index 985447e865..77e6d8e76c 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ASubClass.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ASubClass.java @@ -19,6 +19,9 @@ * under the License. */ +/** + * + */ public class ASubClass extends ABaseClass { } diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ATestClass.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ATestClass.java index baff162e15..d7ac6b8b60 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ATestClass.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/ATestClass.java @@ -21,6 +21,9 @@ import java.io.File; +/** + * + */ @SuppressWarnings( "UnusedDeclaration" ) public class ATestClass { @@ -58,6 +61,6 @@ public void nestedNpeOutsideTest() public void aLongTestErrorMessage() { throw new RuntimeException( "This message will be truncated, somewhere over the rainbow. " - + "Gangnam style, Gangnam style, Gangnam style, , Gangnam style, Gangnam style" ); + + "Gangnam style, Gangnam style, Gangnam style, , Gangnam style, Gangnam style" ); } } diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/OutermostClass.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/OutermostClass.java index be9525e3da..91e723f526 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/OutermostClass.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/OutermostClass.java @@ -19,7 +19,8 @@ * under the License. */ -class OutermostClass { +class OutermostClass +{ void junit() { new ATestClass().failInAssert(); diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/PojoStackTraceWriterTest.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/PojoStackTraceWriterTest.java index 4bb667e692..69a3db06d7 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/PojoStackTraceWriterTest.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/PojoStackTraceWriterTest.java @@ -21,6 +21,9 @@ import junit.framework.TestCase; +/** + * + */ public class PojoStackTraceWriterTest extends TestCase { @@ -30,10 +33,9 @@ public void testTrimmedThrowableReal() PojoStackTraceWriter w = new PojoStackTraceWriter( ATestClass.AnotherTestClass.class.getName(), "testQuote", getAThrowAble() ); String out = w.writeTrimmedTraceToString(); - String expected = - "org.apache.maven.surefire.report.PojoStackTraceWriterTest$ATestClass$AnotherTestClass.getAThrowable(PojoStackTraceWriterTest.java"; + String expected = "org.apache.maven.surefire.report.PojoStackTraceWriterTest$ATestClass$AnotherTestClass" + + ".getAThrowable(PojoStackTraceWriterTest.java"; assertTrue( out.contains( expected ) ); - } public void testMultiLineMessage() diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/RunnableTestClass1.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/RunnableTestClass1.java index 521c8734a3..2d236d665d 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/RunnableTestClass1.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/RunnableTestClass1.java @@ -1,29 +1,30 @@ package org.apache.maven.surefire.report; +/* + * 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.util.internal.DaemonThreadFactory; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; -/* -* 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. -*/ class RunnableTestClass1 implements Callable { diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/RunnableTestClass2.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/RunnableTestClass2.java index b782df8ed0..77da1c713e 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/RunnableTestClass2.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/RunnableTestClass2.java @@ -1,25 +1,26 @@ package org.apache.maven.surefire.report; +/* + * 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.util.concurrent.Callable; -/* -* 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. -*/ class RunnableTestClass2 implements Callable @@ -30,7 +31,7 @@ public Object call() throws Exception { InnerRunnableTestClass.cThrows(); - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } static class InnerRunnableTestClass diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/SmartStackTraceParserTest.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/SmartStackTraceParserTest.java index f057ce5c43..593a8c2f52 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/SmartStackTraceParserTest.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/SmartStackTraceParserTest.java @@ -29,8 +29,13 @@ import junit.framework.TestCase; import org.apache.maven.surefire.util.internal.DaemonThreadFactory; -import static org.apache.maven.surefire.report.SmartStackTraceParser.*; +import static org.apache.maven.surefire.report.SmartStackTraceParser.findTopmostWithClass; +import static org.apache.maven.surefire.report.SmartStackTraceParser.focusInsideClass; +import static org.apache.maven.surefire.report.SmartStackTraceParser.stackTraceWithFocusOnClassAsString; +/** + * + */ @SuppressWarnings( "ThrowableResultOfMethodCallIgnored" ) public class SmartStackTraceParserTest extends TestCase @@ -44,9 +49,10 @@ public void testGetString() } catch ( AssertionError e ) { - SmartStackTraceParser smartStackTraceParser = new SmartStackTraceParser( ATestClass.class.getName(), e, null ); + SmartStackTraceParser smartStackTraceParser = + new SmartStackTraceParser( ATestClass.class.getName(), e, null ); String res = smartStackTraceParser.getString(); - assertEquals( "ATestClass.failInAssert:30 X is not Z", res ); + assertEquals( "ATestClass.failInAssert:33 X is not Z", res ); } } @@ -62,7 +68,7 @@ public void testGetStringFromNested() SmartStackTraceParser smartStackTraceParser = new SmartStackTraceParser( ATestClass.class.getName(), e, null ); String res = smartStackTraceParser.getString(); - assertEquals( "ATestClass.failInAssert:30 X is not Z", res ); + assertEquals( "ATestClass.failInAssert:33 X is not Z", res ); } } @@ -94,7 +100,7 @@ public void testNestedFailure() SmartStackTraceParser smartStackTraceParser = new SmartStackTraceParser( ATestClass.class.getName(), e, null ); String res = smartStackTraceParser.getString(); - assertEquals( "ATestClass.nestedFailInAssert:35->failInAssert:30 X is not Z", res ); + assertEquals( "ATestClass.nestedFailInAssert:38->failInAssert:33 X is not Z", res ); } } @@ -110,7 +116,7 @@ public void testNestedNpe() SmartStackTraceParser smartStackTraceParser = new SmartStackTraceParser( ATestClass.class.getName(), e, null ); String res = smartStackTraceParser.getString(); - assertEquals( "ATestClass.nestedNpe:45->npe:40 NullPointer It was null", res ); + assertEquals( "ATestClass.nestedNpe:48->npe:43 NullPointer It was null", res ); } } @@ -126,7 +132,7 @@ public void testNestedNpeOutsideTest() SmartStackTraceParser smartStackTraceParser = new SmartStackTraceParser( ATestClass.class.getName(), e, null ); String res = smartStackTraceParser.getString(); - assertEquals( "ATestClass.nestedNpeOutsideTest:55->npeOutsideTest:50 » NullPointer", res ); + assertEquals( "ATestClass.nestedNpeOutsideTest:58->npeOutsideTest:53 » NullPointer", res ); } } @@ -142,7 +148,7 @@ public void testLongMessageTruncation() SmartStackTraceParser smartStackTraceParser = new SmartStackTraceParser( ATestClass.class.getName(), e, null ); String res = smartStackTraceParser.getString(); - assertEquals( "ATestClass.aLongTestErrorMessage:60 Runtime This message will be truncated, so...", + assertEquals( "ATestClass.aLongTestErrorMessage:63 Runtime This message will be truncated, so...", res ); } } @@ -159,7 +165,7 @@ public void testFailureInBaseClass() SmartStackTraceParser smartStackTraceParser = new SmartStackTraceParser( ASubClass.class.getName(), e, null ); String res = smartStackTraceParser.getString(); - assertEquals( "ASubClass>ABaseClass.npe:27 » NullPointer It was null", res ); + assertEquals( "ASubClass>ABaseClass.npe:29 » NullPointer It was null", res ); } } @@ -322,7 +328,8 @@ public void testStackTraceWithFocusOnClassAsString() { String trace = stackTraceWithFocusOnClassAsString( e, StackTraceFocusedOnClass.B.class.getName() ); - assertEquals( "java.lang.RuntimeException: java.lang.IllegalStateException: java.io.IOException: I/O error\n" + assertEquals( + "java.lang.RuntimeException: java.lang.IllegalStateException: java.io.IOException: I/O error\n" + "\tat org.apache.maven.surefire.report.StackTraceFocusedOnClass$B.b(StackTraceFocusedOnClass.java:65)\n" + "Caused by: java.lang.IllegalStateException: java.io.IOException: I/O error\n" + "\tat org.apache.maven.surefire.report.StackTraceFocusedOnClass$B.b(StackTraceFocusedOnClass.java:61)\n" diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/StackTraceFocusedOnClass.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/StackTraceFocusedOnClass.java index 64449c07ec..b544c0478d 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/StackTraceFocusedOnClass.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/StackTraceFocusedOnClass.java @@ -32,7 +32,7 @@ void throwException() } } - static abstract class A + abstract static class A { abstract void abs() throws IOException; diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/TestClass1.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/TestClass1.java index 5b34f67a97..e878fd03c3 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/TestClass1.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/TestClass1.java @@ -18,6 +18,7 @@ * specific language governing permissions and limitations * under the License. */ + class TestClass1 { static class InnerBTestClass diff --git a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/TestClass2.java b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/TestClass2.java index ae55026f9c..4c986f0b32 100644 --- a/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/TestClass2.java +++ b/surefire-providers/common-java5/src/test/java/org/apache/maven/surefire/report/TestClass2.java @@ -18,6 +18,7 @@ * specific language governing permissions and limitations * under the License. */ + class TestClass2 { static class InnerCTestClass diff --git a/surefire-providers/common-junit3/pom.xml b/surefire-providers/common-junit3/pom.xml index edc24a16ae..a8c292a9b1 100644 --- a/surefire-providers/common-junit3/pom.xml +++ b/surefire-providers/common-junit3/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 common-junit3 @@ -40,4 +40,37 @@ + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + + + + + diff --git a/surefire-providers/common-junit3/src/test/java/org/apache/maven/surefire/common/junit3/JUnit3TestCheckerTest.java b/surefire-providers/common-junit3/src/test/java/org/apache/maven/surefire/common/junit3/JUnit3TestCheckerTest.java index 2397e8b025..7fd71f5fea 100644 --- a/surefire-providers/common-junit3/src/test/java/org/apache/maven/surefire/common/junit3/JUnit3TestCheckerTest.java +++ b/surefire-providers/common-junit3/src/test/java/org/apache/maven/surefire/common/junit3/JUnit3TestCheckerTest.java @@ -19,8 +19,6 @@ * under the License. */ -import org.apache.maven.surefire.testset.TestSetFailedException; - import junit.framework.TestCase; import junit.framework.TestResult; @@ -33,25 +31,21 @@ public class JUnit3TestCheckerTest private final JUnit3TestChecker jUnit3TestChecker = new JUnit3TestChecker( this.getClass().getClassLoader() ); public void testValidJunit4Annotated() - throws TestSetFailedException { assertTrue( jUnit3TestChecker.accept( JUnit3TestCheckerTest.class ) ); } public void testValidJunit4itsAJunit3Test() - throws TestSetFailedException { assertTrue( jUnit3TestChecker.accept( AlsoValid.class ) ); } public void testValidJunitSubclassWithoutOwnTestmethods() - throws TestSetFailedException { assertTrue( jUnit3TestChecker.accept( SubClassWithoutOwnTestMethods.class ) ); } public void testInvalidTest() - throws TestSetFailedException { assertFalse( jUnit3TestChecker.accept( NotValidTest.class ) ); } @@ -77,7 +71,9 @@ public void testIinnerClassNotAutomaticallyTc() assertFalse( jUnit3TestChecker.accept( NestedTC.Inner.class ) ); } - + /** + * + */ public static class AlsoValid extends TestCase { @@ -87,6 +83,9 @@ public void testSomething() } } + /** + * + */ public static class SuiteOnlyTest { public static junit.framework.Test suite() @@ -95,6 +94,9 @@ public static junit.framework.Test suite() } } + /** + * + */ public static class CustomSuiteOnlyTest { public static MySuite2 suite() @@ -103,6 +105,9 @@ public static MySuite2 suite() } } + /** + * + */ public static class MySuite2 implements junit.framework.Test { @@ -119,6 +124,9 @@ public void run( TestResult testResult ) } + /** + * + */ public static class NotValidTest { public void testSomething() @@ -126,6 +134,9 @@ public void testSomething() } } + /** + * + */ public abstract static class BaseClassWithTest extends TestCase { @@ -134,6 +145,9 @@ public void testWeAreAlsoATest() } } + /** + * + */ public static class SubClassWithoutOwnTestMethods extends BaseClassWithTest { diff --git a/surefire-providers/common-junit4/pom.xml b/surefire-providers/common-junit4/pom.xml index fdc54fd165..2cb43fcf84 100644 --- a/surefire-providers/common-junit4/pom.xml +++ b/surefire-providers/common-junit4/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 common-junit4 @@ -49,4 +49,37 @@ ${project.version} + + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + + + + diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java index d19a0e1c9f..702ee7ff57 100644 --- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java +++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java @@ -20,14 +20,17 @@ */ import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set; +import org.apache.maven.surefire.util.internal.ClassMethod; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; import org.junit.runner.notification.Failure; -import static org.apache.maven.surefire.util.internal.StringUtils.isBlank; +import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractClassName; +import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractMethodName; import static org.junit.runner.Description.TEST_MECHANISM; /** @@ -75,33 +78,30 @@ public static boolean isFailureInsideJUnitItself( Description failure ) * @param description method(class) or method[#](class) or method[#whatever-literals](class) * @return method JUnit test method */ - public static ClassMethod cutTestClassAndMethod( Description description ) + public static ClassMethod toClassMethod( Description description ) { - String name = description.getDisplayName(); - String clazz = null; - String method = null; - if ( name != null ) + String clazz = extractClassName( description.getDisplayName() ); + if ( clazz == null || isInsaneJunitNullString( clazz ) ) { - // The order is : 1.method and then 2.class - // method(class) - name = name.trim(); - if ( name.endsWith( ")" ) ) + // This can happen upon early failures (class instantiation error etc) + Iterator it = description.getChildren().iterator(); + if ( it.hasNext() ) { - int classBracket = name.lastIndexOf( '(' ); - if ( classBracket != -1 ) - { - clazz = tryBlank( name.substring( classBracket + 1, name.length() - 1 ) ); - method = tryBlank( name.substring( 0, classBracket ) ); - } + description = it.next(); + clazz = extractClassName( description.getDisplayName() ); + } + if ( clazz == null ) + { + clazz = "Test Instantiation Error"; } } + String method = extractMethodName( description.getDisplayName() ); return new ClassMethod( clazz, method ); } - private static String tryBlank( String s ) + private static boolean isInsaneJunitNullString( String value ) { - s = s.trim(); - return isBlank( s ) ? null : s; + return "null".equals( value ); } public static Filter createMatchAnyDescriptionFilter( Iterable descriptions ) diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java index bbdeabb9ec..9efe4258ba 100644 --- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java +++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector.java @@ -117,7 +117,7 @@ public int hashCode() @Override public boolean equals( Object obj ) { - return obj instanceof Annotation && obj instanceof Ignore && equalValue( ( Ignore ) obj ); + return obj instanceof Ignore && equalValue( ( Ignore ) obj ); } @Override diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java index 7ed2ad9e76..c4a7991178 100644 --- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java +++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java @@ -24,17 +24,17 @@ import org.apache.maven.surefire.report.SimpleReportEntry; import org.apache.maven.surefire.report.StackTraceWriter; import org.apache.maven.surefire.testset.TestSetFailedException; +import org.apache.maven.surefire.util.internal.ClassMethod; import org.junit.runner.Description; import org.junit.runner.Result; import org.junit.runner.notification.Failure; import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.isFailureInsideJUnitItself; +import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.toClassMethod; import static org.apache.maven.surefire.common.junit4.JUnit4Reflector.getAnnotatedIgnoreValue; import static org.apache.maven.surefire.report.SimpleReportEntry.assumption; import static org.apache.maven.surefire.report.SimpleReportEntry.ignored; import static org.apache.maven.surefire.report.SimpleReportEntry.withException; -import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractClassName; -import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractMethodName; /** * RunListener for JUnit4, delegates to our own RunListener @@ -47,7 +47,8 @@ public class JUnit4RunListener /** * This flag is set after a failure has occurred so that a {@link RunListener#testSucceeded} event is not fired. - * This is necessary because JUnit4 always fires a {@link org.junit.runner.notification.RunListener#testRunFinished} + * This is necessary because JUnit4 always fires a + * {@link org.junit.runner.notification.RunListener#testRunFinished(Result)} * event-- even if there was a failure. */ private final ThreadLocal failureFlag = new InheritableThreadLocal<>(); @@ -74,7 +75,8 @@ public void testIgnored( Description description ) throws Exception { String reason = getAnnotatedIgnoreValue( description ); - reporter.testSkipped( ignored( getClassName( description ), description.getDisplayName(), reason ) ); + ClassMethod classMethod = toClassMethod( description ); + reporter.testSkipped( ignored( classMethod.getClazz(), null, classMethod.getMethod(), null, reason ) ); } /** @@ -108,16 +110,10 @@ public void testFailure( Failure failure ) { try { - String testHeader = failure.getTestHeader(); - if ( isInsaneJunitNullString( testHeader ) ) - { - testHeader = "Failure when constructing test"; - } - - String testClassName = getClassName( failure.getDescription() ); StackTraceWriter stackTrace = createStackTraceWriter( failure ); - - ReportEntry report = withException( testClassName, testHeader, stackTrace ); + ClassMethod classMethod = toClassMethod( failure.getDescription() ); + ReportEntry report = + withException( classMethod.getClazz(), null, classMethod.getMethod(), null, stackTrace ); if ( failure.getException() instanceof AssertionError ) { @@ -134,14 +130,15 @@ public void testFailure( Failure failure ) } } - @SuppressWarnings( "UnusedDeclaration" ) public void testAssumptionFailure( Failure failure ) { try { Description desc = failure.getDescription(); - String test = getClassName( desc ); - reporter.testAssumptionFailure( assumption( test, desc.getDisplayName(), failure.getMessage() ) ); + ClassMethod classMethod = toClassMethod( desc ); + ReportEntry report = assumption( classMethod.getClazz(), null, classMethod.getMethod(), null, + failure.getMessage() ); + reporter.testAssumptionFailure( report ); } finally { @@ -173,25 +170,6 @@ public void testExecutionSkippedByUser() reporter.testExecutionSkippedByUser(); } - private String getClassName( Description description ) - { - String name = extractDescriptionClassName( description ); - if ( name == null || isInsaneJunitNullString( name ) ) - { - // This can happen upon early failures (class instantiation error etc) - Description subDescription = description.getChildren().get( 0 ); - if ( subDescription != null ) - { - name = extractDescriptionClassName( subDescription ); - } - if ( name == null ) - { - name = "Test Instantiation Error"; - } - } - return name; - } - protected StackTraceWriter createStackTraceWriter( Failure failure ) { return new JUnit4StackTraceWriter( failure ); @@ -199,17 +177,8 @@ protected StackTraceWriter createStackTraceWriter( Failure failure ) protected SimpleReportEntry createReportEntry( Description description ) { - return new SimpleReportEntry( getClassName( description ), description.getDisplayName() ); - } - - protected String extractDescriptionClassName( Description description ) - { - return extractClassName( description.getDisplayName() ); - } - - protected String extractDescriptionMethodName( Description description ) - { - return extractMethodName( description.getDisplayName() ); + ClassMethod classMethod = toClassMethod( description ); + return new SimpleReportEntry( classMethod.getClazz(), null, classMethod.getMethod(), null ); } public static void rethrowAnyTestMechanismFailures( Result run ) @@ -224,9 +193,4 @@ public static void rethrowAnyTestMechanismFailures( Result run ) } } } - - private static boolean isInsaneJunitNullString( String value ) - { - return "null".equals( value ); - } } diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4StackTraceWriter.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4StackTraceWriter.java index 78cefb6394..f60a30d9af 100644 --- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4StackTraceWriter.java +++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4StackTraceWriter.java @@ -22,10 +22,10 @@ import org.apache.maven.surefire.report.SafeThrowable; import org.apache.maven.surefire.report.SmartStackTraceParser; import org.apache.maven.surefire.report.StackTraceWriter; +import org.apache.maven.surefire.util.internal.ClassMethod; import org.junit.runner.notification.Failure; -import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractClassName; -import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractMethodName; +import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.toClassMethod; import static org.apache.maven.surefire.report.SmartStackTraceParser.stackTraceWithFocusOnClassAsString; /** @@ -37,8 +37,7 @@ public class JUnit4StackTraceWriter implements StackTraceWriter { - // Member Variables - protected final Failure junitFailure; + private final Failure junitFailure; /** * Constructor. @@ -78,24 +77,14 @@ public String writeTraceToString() return ""; } - protected String getTestClassName() - { - return extractClassName( junitFailure.getDescription().getDisplayName() ); - } - - protected String getTestMethodName() - { - return extractMethodName( junitFailure.getDescription().getDisplayName() ); - } - @Override - @SuppressWarnings( "ThrowableResultOfMethodCallIgnored" ) public String smartTrimmedStackTrace() { Throwable exception = junitFailure.getException(); + ClassMethod classMethod = toClassMethod( junitFailure.getDescription() ); return exception == null ? junitFailure.getMessage() - : new SmartStackTraceParser( getTestClassName(), exception, getTestMethodName() ).getString(); + : new SmartStackTraceParser( classMethod.getClazz(), exception, classMethod.getMethod() ).getString(); } /** @@ -106,7 +95,7 @@ public String smartTrimmedStackTrace() @Override public String writeTrimmedTraceToString() { - String testClass = getTestClassName(); + String testClass = toClassMethod( junitFailure.getDescription() ).getClazz(); try { Throwable e = junitFailure.getException(); diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java index c2c6df80b0..de0ddc4fc8 100644 --- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java +++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/Notifier.java @@ -32,7 +32,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; -import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.cutTestClassAndMethod; +import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.toClassMethod; import static org.apache.maven.surefire.util.internal.ConcurrencyUtils.countDownToZero; /** @@ -100,7 +100,7 @@ public final void fireTestStarted( Description description ) throws StoppedByUse super.fireTestStarted( description ); if ( !testClassNames.isEmpty() ) { - testClassNames.remove( cutTestClassAndMethod( description ).getClazz() ); + testClassNames.remove( toClassMethod( description ).getClazz() ); } } diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java index 18f05929ea..6f93ae5488 100644 --- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java +++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/junit4/MockReporter.java @@ -25,6 +25,7 @@ import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.TestSetReportEntry; +import org.apache.maven.surefire.report.RunMode; /** * Internal tests use only. @@ -93,6 +94,12 @@ public void testExecutionSkippedByUser() { } + @Override + public RunMode markAs( RunMode currentRunMode ) + { + return null; + } + public void testSkippedByUser( ReportEntry report ) { testSkipped( report ); diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java index 163308c46d..9431b0ef8f 100644 --- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java +++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java @@ -20,6 +20,7 @@ */ import junit.framework.TestCase; +import org.apache.maven.surefire.util.internal.ClassMethod; import org.junit.runner.Description; import org.junit.runner.notification.Failure; @@ -27,7 +28,7 @@ import java.util.List; import java.util.Set; -import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.*; +import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.generateFailingTestDescriptions; /** * @author Qingzhou Luo @@ -55,34 +56,34 @@ public void testGenerateFailingTestDescriptions() assertEquals( 4, result.size() ); - assertTrue( result.contains( test1Description) ); - assertTrue( result.contains( test2Description) ); - assertTrue( result.contains( test3Description) ); - assertTrue( result.contains( test4Description) ); + assertTrue( result.contains( test1Description ) ); + assertTrue( result.contains( test2Description ) ); + assertTrue( result.contains( test3Description ) ); + assertTrue( result.contains( test4Description ) ); } - public void testIllegalTestDescription$NegativeTest() + public void testIllegalTestDescriptionNegativeTest() { Description test = Description.createSuiteDescription( "someTestMethod" ); - ClassMethod classMethod = cutTestClassAndMethod( test ); - assertFalse( classMethod.isValid() ); + ClassMethod classMethod = JUnit4ProviderUtil.toClassMethod( test ); + assertFalse( classMethod.isValidTest() ); } public void testOldJUnitParameterizedDescriptionParser() { Description test = Description.createTestDescription( T1.class, " \n testMethod[5] " ); assertEquals( " \n testMethod[5] (" + T1.class.getName() + ")", test.getDisplayName() ); - ClassMethod classMethod = cutTestClassAndMethod( test ); - assertTrue( classMethod.isValid() ); - assertEquals( "testMethod[5]", classMethod.getMethod() ); + ClassMethod classMethod = JUnit4ProviderUtil.toClassMethod( test ); + assertTrue( classMethod.isValidTest() ); + assertEquals( " \n testMethod[5] ", classMethod.getMethod() ); assertEquals( T1.class.getName(), classMethod.getClazz() ); } public void testNewJUnitParameterizedDescriptionParser() { Description test = Description.createTestDescription( T1.class, "flakyTest[3: (Test11); Test12; Test13;]" ); - ClassMethod classMethod = cutTestClassAndMethod( test ); - assertTrue( classMethod.isValid() ); + ClassMethod classMethod = JUnit4ProviderUtil.toClassMethod( test ); + assertTrue( classMethod.isValidTest() ); assertEquals( "flakyTest[3: (Test11); Test12; Test13;]", classMethod.getMethod() ); assertEquals( T1.class.getName(), classMethod.getClazz() ); } diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java index df4819cc3f..94c246171f 100644 --- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java +++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4Reflector40Test.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.common.junit4; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -36,13 +37,16 @@ public void testGetAnnotatedIgnore() assertNull( annotatedIgnore ); } - private static final String reason = "Ignorance is bliss"; + private static final String REASON = "Ignorance is bliss"; + /** + * + */ public static class IgnoreWithDescription { @Test - @Ignore( reason ) + @Ignore( REASON ) public void testSomething2() { } diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java index baf458966d..33bc4b8c66 100644 --- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java +++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4RunListenerTest.java @@ -87,7 +87,9 @@ public void run() Assert.assertEquals( "Succeeded tests", 1, reporter.getTestSucceeded() ); } - + /** + * + */ public static class STest1 { @Test @@ -97,6 +99,9 @@ public void testSomething() } } + /** + * + */ public static class STest2 { @Test @@ -105,5 +110,4 @@ public void testSomething2() } } - } diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java index a20473476c..d7b0eaea77 100644 --- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java +++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4TestCheckerTest.java @@ -1,4 +1,5 @@ package org.apache.maven.surefire.junit4; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -120,6 +121,9 @@ public void testCannotLoadRunWithAnnotation() assertTrue( checker.accept( testClass ) ); } + /** + * + */ public static class AlsoValid extends TestCase { @@ -129,6 +133,9 @@ public void testSomething() } } + /** + * + */ public static class SuiteOnlyTest { public static junit.framework.Test suite() @@ -137,6 +144,9 @@ public static junit.framework.Test suite() } } + /** + * + */ public static class CustomSuiteOnlyTest { public static MySuite2 suite() @@ -145,6 +155,9 @@ public static MySuite2 suite() } } + /** + * + */ public static class MySuite2 implements junit.framework.Test { @@ -160,7 +173,9 @@ public void run( TestResult testResult ) } } - + /** + * + */ @SuppressWarnings( { "UnusedDeclaration" } ) public static class NotValidTest { @@ -169,6 +184,9 @@ public void testSomething() } } + /** + * + */ public abstract static class BaseClassWithTest { @Test @@ -177,11 +195,17 @@ public void weAreAlsoATest() } } + /** + * + */ public static class SubClassWithoutOwnTestMethods extends BaseClassWithTest { } + /** + * + */ @RunWith( Suite.class ) public static class SuiteValid1 { @@ -206,6 +230,9 @@ public void run( RunNotifier runNotifier ) } } + /** + * + */ @RunWith( CustomRunner.class ) public static class SuiteValidCustomRunner { @@ -216,6 +243,9 @@ public void testSomething() } + /** + * + */ @RunWith( MySuite.class ) public static class SuiteValid2 { @@ -225,6 +255,9 @@ public void testSomething() } } + /** + * + */ public static class SimpleJUnit4TestClass { @Test @@ -251,5 +284,4 @@ public class Inner } } - } diff --git a/surefire-providers/common-junit48/pom.xml b/surefire-providers/common-junit48/pom.xml index b8007d058f..64a90ca874 100644 --- a/surefire-providers/common-junit48/pom.xml +++ b/surefire-providers/common-junit48/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 common-junit48 @@ -57,13 +57,36 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin + ${jvm.args.tests} ${jacoco.agent} **/JUnit4SuiteTest.java + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + diff --git a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/GroupMatcherCategoryFilter.java b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/GroupMatcherCategoryFilter.java index c91bb12fde..484defd41e 100644 --- a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/GroupMatcherCategoryFilter.java +++ b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/GroupMatcherCategoryFilter.java @@ -98,7 +98,7 @@ private boolean shouldRun( Description description, Description parent, Class } else { - Set> cats = new HashSet>(); + Set> cats = new HashSet<>(); Category cat = description.getAnnotation( Category.class ); if ( cat != null ) { diff --git a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/JUnit46StackTraceWriter.java b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/JUnit46StackTraceWriter.java deleted file mode 100644 index 4051e19fa5..0000000000 --- a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/JUnit46StackTraceWriter.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.apache.maven.surefire.common.junit48; - -/* - * 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.common.junit4.JUnit4StackTraceWriter; -import org.junit.runner.notification.Failure; - -/** - * A stacktrace writer that requires at least junit 4.6 to run. Note that we only use this for 4.8 and higher - *
- * Writes out a specific {@link org.junit.runner.notification.Failure} for - * surefire as a stacktrace. - * - * @author Karl M. Davis - * @author Kristian Rosenvold - */ -public class JUnit46StackTraceWriter - extends JUnit4StackTraceWriter -{ - - /** - * Constructor. - * - * @param junitFailure the {@link org.junit.runner.notification.Failure} that this will be operating on - */ - public JUnit46StackTraceWriter( Failure junitFailure ) - { - super( junitFailure ); - } - - - @Override - protected final String getTestClassName() - { - return junitFailure.getDescription().getClassName(); - } - - @Override - protected String getTestMethodName() - { - return junitFailure.getDescription().getMethodName(); - } -} diff --git a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java index b91cdd86f2..4d16da7ad3 100644 --- a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java +++ b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java @@ -38,18 +38,31 @@ import static org.junit.runner.Description.createSuiteDescription; import static org.junit.runner.Description.createTestDescription; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +/** + * + */ +@SuppressWarnings( "checkstyle:constantname" ) public class FilterFactoryTest { + /** + * + */ @RunWith( org.junit.runners.Suite.class ) @org.junit.runners.Suite.SuiteClasses( { FirstClass.class, SecondClass.class } ) - static public class Suite + public static class Suite { } - static public class FirstClass + /** + * + */ + public static class FirstClass { @Test public void testMethod() @@ -70,7 +83,10 @@ public void otherMethod() } } - static public class SecondClass + /** + * + */ + public static class SecondClass { @Test public void testMethod() @@ -85,7 +101,10 @@ public void secondTestMethod() } } - static public class ThirdClass + /** + * + */ + public static class ThirdClass { @Test public void testMethod() @@ -164,7 +183,8 @@ public void testSanity() @Test public void testNegativeIllegalRegex() { - try { + try + { new TestListResolver( "#%regex[.*.Test.class]" ); } catch ( IllegalArgumentException e ) @@ -176,7 +196,8 @@ public void testNegativeIllegalRegex() @Test public void testNegativeIllegalRegex2() { - try { + try + { new TestListResolver( "%regex[.*.Test.class]#" ); } catch ( IllegalArgumentException e ) @@ -262,7 +283,8 @@ public void testBackwardsCompatibilityBlankMethodFilter() } @Test - public void testBackwardsCompatibilityTestParameterClass() { + public void testBackwardsCompatibilityTestParameterClass() + { Filter filter = createMethodFilter( firstClassName ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class ).filterWith( filter ) ); @@ -273,7 +295,8 @@ public void testBackwardsCompatibilityTestParameterClass() { } @Test - public void testBackwardsCompatibilityTestParameterJavaClass() { + public void testBackwardsCompatibilityTestParameterJavaClass() + { Filter filter = createMethodFilter( firstClassName + ".java" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class ).filterWith( filter ) ); @@ -284,7 +307,8 @@ public void testBackwardsCompatibilityTestParameterJavaClass() { } @Test - public void testBackwardsCompatibilityTestParameterMethod1() { + public void testBackwardsCompatibilityTestParameterMethod1() + { Filter filter = createMethodFilter( firstClassName + ".java#testMethod" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class ).filterWith( filter ) ); @@ -295,7 +319,8 @@ public void testBackwardsCompatibilityTestParameterMethod1() { } @Test - public void testBackwardsCompatibilityTestParameterMethod2() { + public void testBackwardsCompatibilityTestParameterMethod2() + { Filter filter = createMethodFilter( firstClassName + "#testMethod" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class ).filterWith( filter ) ); @@ -306,7 +331,8 @@ public void testBackwardsCompatibilityTestParameterMethod2() { } @Test - public void testBackwardsCompatibilityTestParameterMethod3() { + public void testBackwardsCompatibilityTestParameterMethod3() + { Filter filter = createMethodFilter( firstClassName + "#testMethod" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class ).filterWith( filter ) ); @@ -317,7 +343,8 @@ public void testBackwardsCompatibilityTestParameterMethod3() { } @Test - public void testRegexWithWildcard() { + public void testRegexWithWildcard() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".*]" ); JUnitCore core = new JUnitCore(); @@ -329,7 +356,8 @@ public void testRegexWithWildcard() { } @Test - public void testRegexWithWildcardClass() { + public void testRegexWithWildcardClass() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".*.class]" ); JUnitCore core = new JUnitCore(); @@ -341,7 +369,8 @@ public void testRegexWithWildcardClass() { } @Test - public void testRegexWithExactClass() { + public void testRegexWithExactClass() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".class]" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class ).filterWith( filter ) ); @@ -352,7 +381,8 @@ public void testRegexWithExactClass() { } @Test - public void testRegexWithWildcardJavaClassNegativeTest() { + public void testRegexWithWildcardJavaClassNegativeTest() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".*.class]" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class ).filterWith( filter ) ); @@ -363,7 +393,8 @@ public void testRegexWithWildcardJavaClassNegativeTest() { } @Test - public void testRegexWithTwoClasses() { + public void testRegexWithTwoClasses() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".*|" + secondClassRegex + ".*]" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class, ThirdClass.class ) @@ -375,7 +406,8 @@ public void testRegexWithTwoClasses() { } @Test - public void testRegexWithTwoClassesComplement() { + public void testRegexWithTwoClassesComplement() + { Filter filter = createMethodFilter( "!%regex[" + firstClassRegex + ".*|" + secondClassRegex + ".*]" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class, ThirdClass.class ) @@ -387,7 +419,8 @@ public void testRegexWithTwoClassesComplement() { } @Test - public void testRegexWithTwoClassesAndOneMethod() { + public void testRegexWithTwoClassesAndOneMethod() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".*|" + secondClassRegex + ".* # otherMethod]" ); JUnitCore core = new JUnitCore(); @@ -400,7 +433,8 @@ public void testRegexWithTwoClassesAndOneMethod() { } @Test - public void testRegexWithTwoClassesAndOneMethodComplement() { + public void testRegexWithTwoClassesAndOneMethodComplement() + { Filter filter = createMethodFilter( "!%regex[" + firstClassRegex + ".*|" + secondClassRegex + ".*# otherMethod]" ); JUnitCore core = new JUnitCore(); @@ -413,7 +447,8 @@ public void testRegexWithTwoClassesAndOneMethodComplement() { } @Test - public void testRegexWithTwoClassesAndWildcardMethod() { + public void testRegexWithTwoClassesAndWildcardMethod() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".*|" + secondClassRegex + ".*#test.* ]" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class, ThirdClass.class ) @@ -425,7 +460,8 @@ public void testRegexWithTwoClassesAndWildcardMethod() { } @Test - public void testRegexWithTwoClassesAndRegexMethodComplement() { + public void testRegexWithTwoClassesAndRegexMethodComplement() + { Filter filter = createMethodFilter( "!%regex[" + firstClassRegex + ".*|" + secondClassRegex + ".*#test.*]" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class, ThirdClass.class ) @@ -437,7 +473,8 @@ public void testRegexWithTwoClassesAndRegexMethodComplement() { } @Test - public void testRegexWithTwoClassesAndRegexMethods() { + public void testRegexWithTwoClassesAndRegexMethods() + { Filter filter = createMethodFilter( "%regex[ " + firstClassRegex + ".*|" + secondClassRegex + ".* # test.*|other.* ]" ); JUnitCore core = new JUnitCore(); @@ -450,7 +487,8 @@ public void testRegexWithTwoClassesAndRegexMethods() { } @Test - public void testRegexWithTwoClassesAndRegexMethodsComplement() { + public void testRegexWithTwoClassesAndRegexMethodsComplement() + { Filter filter = createMethodFilter( "!%regex[" + firstClassRegex + ".*|" + secondClassRegex + ".* # test.*|other.* ]" ); JUnitCore core = new JUnitCore(); @@ -463,7 +501,8 @@ public void testRegexWithTwoClassesAndRegexMethodsComplement() { } @Test - public void testMultipleRegexClasses() { + public void testMultipleRegexClasses() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".*], %regex[" + secondClassRegex + ".*]" ); JUnitCore core = new JUnitCore(); @@ -476,7 +515,8 @@ public void testMultipleRegexClasses() { } @Test - public void testMultipleRegexClassesComplement() { + public void testMultipleRegexClassesComplement() + { Filter filter = createMethodFilter( "!%regex[" + firstClassRegex + ".*] , !%regex[" + secondClassRegex + ".*]" ); JUnitCore core = new JUnitCore(); @@ -489,7 +529,8 @@ public void testMultipleRegexClassesComplement() { } @Test - public void testMultipleClasses() { + public void testMultipleClasses() + { Filter filter = createMethodFilter( firstClassName + "," + secondClassName ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class, ThirdClass.class ) @@ -501,7 +542,8 @@ public void testMultipleClasses() { } @Test - public void testMultipleClassesMethods() { + public void testMultipleClassesMethods() + { Filter filter = createMethodFilter( firstClassName + "#other*," + secondClassName + "#*TestMethod" ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class, ThirdClass.class ) @@ -513,7 +555,8 @@ public void testMultipleClassesMethods() { } @Test - public void testMultipleClassesAndMultipleMethodsWithWildcards() { + public void testMultipleClassesAndMultipleMethodsWithWildcards() + { Filter filter = createMethodFilter( firstClassName + "#other*+second*Method," + secondClassName + "#*TestMethod" ); JUnitCore core = new JUnitCore(); @@ -526,7 +569,8 @@ public void testMultipleClassesAndMultipleMethodsWithWildcards() { } @Test - public void testMultipleClassesAndMultipleMethodsWithRegex() { + public void testMultipleClassesAndMultipleMethodsWithRegex() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".class#other.*|second.*Method]," + "%regex[" + secondClassRegex + ".class#.*TestMethod]" ); JUnitCore core = new JUnitCore(); @@ -539,7 +583,8 @@ public void testMultipleClassesAndMultipleMethodsWithRegex() { } @Test - public void testMultipleClassesAndMultipleMethodsMix() { + public void testMultipleClassesAndMultipleMethodsMix() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".class # other.*|second.*Method]," + secondClassName + "#*TestMethod" ); JUnitCore core = new JUnitCore(); @@ -552,7 +597,8 @@ public void testMultipleClassesAndMultipleMethodsMix() { } @Test - public void testMultipleClassesAndMultipleMethods() { + public void testMultipleClassesAndMultipleMethods() + { Filter filter = createMethodFilter( firstClassName + "#other*+secondTestMethod," + secondClassName + "#*TestMethod" ); JUnitCore core = new JUnitCore(); @@ -565,7 +611,8 @@ public void testMultipleClassesAndMultipleMethods() { } @Test - public void testMultipleClassesComplement() { + public void testMultipleClassesComplement() + { Filter filter = createMethodFilter( "!" + firstClassName + ",!" + secondClassName ); JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( FirstClass.class, SecondClass.class, ThirdClass.class ) @@ -577,7 +624,8 @@ public void testMultipleClassesComplement() { } @Test - public void testMultipleRegexClassesMethods() { + public void testMultipleRegexClassesMethods() + { Filter filter = createMethodFilter( "%regex[" + firstClassRegex + ".* # test.*|other.*]," + "%regex[" + secondClassRegex + ".*#second.*]" ); @@ -591,7 +639,8 @@ public void testMultipleRegexClassesMethods() { } @Test - public void testMultipleRegexClassesMethodsComplement() { + public void testMultipleRegexClassesMethodsComplement() + { Filter filter = createMethodFilter( "!%regex[" + firstClassRegex + ".* # test.*|other.*]," + "!%regex[" + secondClassRegex + ".*#second.*]" ); @@ -827,7 +876,7 @@ public void testShouldNotRunNonExistingMethodJUnitCoreSuite() JUnitCore core = new JUnitCore(); Result result = core.run( Request.classes( Suite.class ).filterWith( filter ) ); assertTrue( result.wasSuccessful() ); - assertEquals( 0, result.getRunCount() );//running the Suite + assertEquals( 0, result.getRunCount() ); //running the Suite assertEquals( 0, result.getFailureCount() ); assertEquals( 0, result.getIgnoreCount() ); } diff --git a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/JUnit48TestCheckerTest.java b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/JUnit48TestCheckerTest.java index 9ea0829c7b..42bbdaabac 100644 --- a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/JUnit48TestCheckerTest.java +++ b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/JUnit48TestCheckerTest.java @@ -1,13 +1,5 @@ package org.apache.maven.surefire.common.junit48; -import org.junit.Test; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -27,6 +19,14 @@ * under the License. */ +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + /** * @author Kristian Rosenvold */ @@ -34,7 +34,6 @@ public class JUnit48TestCheckerTest { @Test public void valid48Class() - throws Exception { JUnit48TestChecker tc = new JUnit48TestChecker( this.getClass().getClassLoader() ); assertTrue( tc.accept( BasicTest.class ) ); @@ -42,16 +41,20 @@ public void valid48Class() @Test public void notValid48Class() - throws Exception { JUnit48TestChecker tc = new JUnit48TestChecker( this.getClass().getClassLoader() ); assertFalse( tc.accept( BasicTest2.class ) ); } - + /** + * + */ @RunWith( Enclosed.class ) public abstract static class BasicTest { + /** + * + */ public static class InnerTest { @Test @@ -61,9 +64,15 @@ public void testSomething() } } + /** + * + */ @RunWith( Parameterized.class ) public abstract static class BasicTest2 { + /** + * + */ public static class InnerTest { @Test diff --git a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/JUnit4SuiteTest.java b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/JUnit4SuiteTest.java index 547c381c2c..191e1e8f98 100644 --- a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/JUnit4SuiteTest.java +++ b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/JUnit4SuiteTest.java @@ -21,8 +21,8 @@ import junit.framework.JUnit4TestAdapter; import junit.framework.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; +import junit.framework.TestCase; +import junit.framework.TestSuite; /** * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite. @@ -30,16 +30,14 @@ * @author Tibor Digana (tibor17) * @since 2.19 */ -@Suite.SuiteClasses( { - FilterFactoryTest.class, - JUnit48ReflectorTest.class, - JUnit48TestCheckerTest.class -} ) -@RunWith( Suite.class ) -public class JUnit4SuiteTest +public class JUnit4SuiteTest extends TestCase { public static Test suite() { - return new JUnit4TestAdapter( JUnit4SuiteTest.class ); + TestSuite suite = new TestSuite(); + suite.addTestSuite( JUnit48ReflectorTest.class ); + suite.addTest( new JUnit4TestAdapter( JUnit48TestCheckerTest.class ) ); + suite.addTest( new JUnit4TestAdapter( FilterFactoryTest.class ) ); + return suite; } } diff --git a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/ATest.java b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/ATest.java index 59cc2eb6d5..4a9e17a0f2 100644 --- a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/ATest.java +++ b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/ATest.java @@ -18,6 +18,10 @@ * specific language governing permissions and limitations * under the License. */ + +/** + * + */ public class ATest { } diff --git a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/a/ATest.java b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/a/ATest.java index 333ffe8416..28e6e1cd18 100644 --- a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/a/ATest.java +++ b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/a/ATest.java @@ -18,6 +18,10 @@ * specific language governing permissions and limitations * under the License. */ + +/** + * + */ public class ATest { } diff --git a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/pt/PT.java b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/pt/PT.java index d16153bf91..a6f1df47e6 100644 --- a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/pt/PT.java +++ b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/tests/pt/PT.java @@ -25,6 +25,9 @@ import java.util.Arrays; +/** + * + */ @RunWith( Parameterized.class ) public class PT { diff --git a/surefire-providers/pom.xml b/surefire-providers/pom.xml index 94816f4383..bfb36fd81c 100644 --- a/surefire-providers/pom.xml +++ b/surefire-providers/pom.xml @@ -24,7 +24,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 surefire-providers @@ -62,7 +62,7 @@ org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 diff --git a/surefire-providers/surefire-junit-platform/pom.xml b/surefire-providers/surefire-junit-platform/pom.xml index 4f1f1d0b77..072b339864 100644 --- a/surefire-providers/surefire-junit-platform/pom.xml +++ b/surefire-providers/surefire-junit-platform/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 surefire-junit-platform @@ -95,11 +95,21 @@ junit-jupiter-engine test + + org.junit.jupiter + junit-jupiter-params + test + org.mockito mockito-core test + + org.powermock + powermock-reflect + test + org.assertj assertj-core @@ -109,6 +119,21 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + org.codehaus.mojo animal-sniffer-maven-plugin @@ -136,9 +161,14 @@ maven-surefire-plugin - 3.0.0-M2 + 3.0.0-M3 + ${jvm.args.tests} ${jacoco.agent} ${java.home}/bin/java + true + + **/JUnit47SuiteTest.java + diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java index fef72e600e..65ca79ec1b 100644 --- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java +++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java @@ -31,6 +31,7 @@ import static org.apache.maven.surefire.util.TestsToRun.fromClass; import static org.junit.platform.commons.util.StringUtils.isBlank; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; import java.io.IOException; @@ -42,6 +43,7 @@ import java.util.Map; import java.util.Optional; import java.util.Properties; +import java.util.HashSet; import java.util.logging.Logger; import org.apache.maven.surefire.providerapi.AbstractProvider; @@ -60,6 +62,7 @@ import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.TagFilter; +import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.launcher.core.LauncherFactory; @@ -147,7 +150,26 @@ private TestsToRun scanClasspath() private void invokeAllTests( TestsToRun testsToRun, RunListener runListener ) { LauncherDiscoveryRequest discoveryRequest = buildLauncherDiscoveryRequest( testsToRun ); - launcher.execute( discoveryRequest, new RunListenerAdapter( runListener ) ); + RunListenerAdapter adapter = new RunListenerAdapter( runListener ); + launcher.execute( discoveryRequest, adapter ); + // Rerun failing tests if requested + int count = parameters.getTestRequest().getRerunFailingTestsCount(); + if ( count > 0 && adapter.hasFailingTests() ) + { + for ( int i = 0; i < count; i++ ) + { + // Replace the "discoveryRequest" so that it only specifies the failing tests + discoveryRequest = buildLauncherDiscoveryRequestForRerunFailures( adapter ); + // Reset adapter's recorded failures and invoke the failed tests again + adapter.reset(); + launcher.execute( discoveryRequest, adapter ); + // If no tests fail in the rerun, we're done + if ( !adapter.hasFailingTests() ) + { + break; + } + } + } } private LauncherDiscoveryRequest buildLauncherDiscoveryRequest( TestsToRun testsToRun ) @@ -156,7 +178,19 @@ private LauncherDiscoveryRequest buildLauncherDiscoveryRequest( TestsToRun tests request().filters( filters ).configurationParameters( configurationParameters ); for ( Class testClass : testsToRun ) { - builder.selectors( selectClass( testClass ) ); + builder.selectors( selectClass( testClass.getName() ) ); + } + return builder.build(); + } + + private LauncherDiscoveryRequest buildLauncherDiscoveryRequestForRerunFailures( RunListenerAdapter adapter ) + { + LauncherDiscoveryRequestBuilder builder = request().filters( filters ).configurationParameters( + configurationParameters ); + // Iterate over recorded failures + for ( TestIdentifier identifier : new HashSet<>( adapter.getFailures().keySet() ) ) + { + builder.selectors( selectUniqueId( identifier.getUniqueId() ) ); } return builder.build(); } 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 85227f3ef9..5e1e631aff 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,13 +19,16 @@ * under the License. */ -import static org.apache.maven.surefire.report.SimpleReportEntry.ignored; -import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; -import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; +import static java.util.Collections.emptyMap; +import static java.util.stream.Collectors.joining; +import static org.apache.maven.surefire.util.internal.ObjectUtils.systemProps; +import java.util.Map; +import java.util.Objects; import java.util.Optional; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Pattern; import org.apache.maven.surefire.report.PojoStackTraceWriter; import org.apache.maven.surefire.report.RunListener; @@ -38,7 +41,6 @@ import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; -import org.junit.platform.launcher.listeners.LegacyReportingUtils; /** * @since 2.22.0 @@ -46,12 +48,12 @@ final class RunListenerAdapter implements TestExecutionListener { + private static final Pattern COMMA_PATTERN = Pattern.compile( "," ); + private final ConcurrentMap testStartTime = new ConcurrentHashMap<>(); + private final ConcurrentMap failures = new ConcurrentHashMap<>(); private final RunListener runListener; - - private TestPlan testPlan; - - private Set testSetNodes = ConcurrentHashMap.newKeySet(); + private volatile TestPlan testPlan; RunListenerAdapter( RunListener runListener ) { @@ -61,13 +63,15 @@ final class RunListenerAdapter @Override public void testPlanExecutionStarted( TestPlan testPlan ) { - updateTestPlan( testPlan ); + this.testPlan = testPlan; + failures.clear(); } @Override public void testPlanExecutionFinished( TestPlan testPlan ) { - updateTestPlan( null ); + this.testPlan = null; + testStartTime.clear(); } @Override @@ -76,197 +80,216 @@ public void executionStarted( TestIdentifier testIdentifier ) if ( testIdentifier.isContainer() && testIdentifier.getSource().filter( ClassSource.class::isInstance ).isPresent() ) { - startTestSetIfPossible( testIdentifier ); + testStartTime.put( testIdentifier, System.currentTimeMillis() ); + runListener.testSetStarting( createReportEntry( testIdentifier ) ); } - if ( testIdentifier.isTest() ) + else if ( testIdentifier.isTest() ) { - ensureTestSetStarted( testIdentifier ); + testStartTime.put( testIdentifier, System.currentTimeMillis() ); runListener.testStarting( createReportEntry( testIdentifier ) ); } } @Override - public void executionSkipped( TestIdentifier testIdentifier, String reason ) + public void executionFinished( TestIdentifier testIdentifier, TestExecutionResult testExecutionResult ) { - ensureTestSetStarted( testIdentifier ); - String source = getLegacyReportingClassName( testIdentifier ); - runListener.testSkipped( ignored( source, getLegacyReportingName( testIdentifier ), reason ) ); - completeTestSetIfNecessary( testIdentifier ); - } + boolean isClass = testIdentifier.isContainer() + && testIdentifier.getSource().filter( ClassSource.class::isInstance ).isPresent(); - @Override - public void executionFinished( - TestIdentifier testIdentifier, TestExecutionResult testExecutionResult ) - { - if ( testExecutionResult.getStatus() == ABORTED ) - { - runListener.testAssumptionFailure( createReportEntry( testIdentifier, testExecutionResult ) ); - } - else if ( testExecutionResult.getStatus() == FAILED ) - { - reportFailedTest( testIdentifier, testExecutionResult ); - } - else if ( testIdentifier.isTest() ) + boolean isTest = testIdentifier.isTest(); + + if ( isClass || isTest ) { - runListener.testSucceeded( createReportEntry( testIdentifier ) ); + Integer elapsed = computeElapsedTime( testIdentifier ); + switch ( testExecutionResult.getStatus() ) + { + case ABORTED: + if ( isTest ) + { + runListener.testAssumptionFailure( + createReportEntry( testIdentifier, testExecutionResult, elapsed ) ); + } + else + { + runListener.testSetCompleted( createReportEntry( testIdentifier, testExecutionResult, + systemProps(), null, elapsed ) ); + } + break; + case FAILED: + if ( !isTest ) + { + runListener.testSetCompleted( createReportEntry( testIdentifier, testExecutionResult, + systemProps(), null, elapsed ) ); + } + else if ( testExecutionResult.getThrowable() + .filter( AssertionError.class::isInstance ).isPresent() ) + { + runListener.testFailed( createReportEntry( testIdentifier, testExecutionResult, elapsed ) ); + } + else + { + runListener.testError( createReportEntry( testIdentifier, testExecutionResult, elapsed ) ); + } + failures.put( testIdentifier, testExecutionResult ); + break; + default: + if ( isTest ) + { + runListener.testSucceeded( createReportEntry( testIdentifier, null, elapsed ) ); + } + else + { + runListener.testSetCompleted( + createReportEntry( testIdentifier, null, systemProps(), null, elapsed ) ); + } + } } - completeTestSetIfNecessary( testIdentifier ); } - private void updateTestPlan( TestPlan testPlan ) + private Integer computeElapsedTime( TestIdentifier testIdentifier ) { - this.testPlan = testPlan; - testSetNodes.clear(); + Long startTime = testStartTime.remove( testIdentifier ); + long endTime = System.currentTimeMillis(); + return startTime == null ? null : (int) ( endTime - startTime ); } - private void ensureTestSetStarted( TestIdentifier testIdentifier ) + @Override + public void executionSkipped( TestIdentifier testIdentifier, String reason ) { - if ( isTestSetStarted( testIdentifier ) ) - { - return; - } - if ( testIdentifier.isTest() ) + testStartTime.remove( testIdentifier ); + runListener.testSkipped( createReportEntry( testIdentifier, null, emptyMap(), reason, null ) ); + } + + private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier, + TestExecutionResult testExecutionResult, + Map systemProperties, + String reason, + Integer elapsedTime ) + { + String[] classMethodName = toClassMethodName( testIdentifier ); + String className = classMethodName[0]; + String classText = classMethodName[1]; + if ( Objects.equals( className, classText ) ) { - startTestSet( testPlan.getParent( testIdentifier ).orElse( testIdentifier ) ); + classText = null; } - else + String methodName = testIdentifier.isTest() ? classMethodName[2] : null; + String methodText = testIdentifier.isTest() ? classMethodName[3] : null; + if ( Objects.equals( methodName, methodText ) ) { - startTestSet( testIdentifier ); + methodText = null; } + StackTraceWriter stw = + testExecutionResult == null ? null : toStackTraceWriter( className, methodName, testExecutionResult ); + return new SimpleReportEntry( className, classText, methodName, methodText, + stw, elapsedTime, reason, systemProperties ); } - private boolean isTestSetStarted( TestIdentifier testIdentifier ) + private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier ) { - return testSetNodes.contains( testIdentifier ) - || testPlan.getParent( testIdentifier ).map( this::isTestSetStarted ).orElse( false ); + return createReportEntry( testIdentifier, null, null ); } - private void startTestSetIfPossible( TestIdentifier testIdentifier ) + private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier, + TestExecutionResult testExecutionResult, Integer elapsedTime ) { - if ( !isTestSetStarted( testIdentifier ) ) - { - startTestSet( testIdentifier ); - } + return createReportEntry( testIdentifier, testExecutionResult, emptyMap(), null, elapsedTime ); } - private void completeTestSetIfNecessary( TestIdentifier testIdentifier ) + private StackTraceWriter toStackTraceWriter( String realClassName, String realMethodName, + TestExecutionResult testExecutionResult ) { - if ( testSetNodes.contains( testIdentifier ) ) + switch ( testExecutionResult.getStatus() ) { - completeTestSet( testIdentifier ); + case ABORTED: + case FAILED: + // Failed tests must have a StackTraceWriter, otherwise Surefire will fail + Throwable exception = testExecutionResult.getThrowable().orElse( null ); + return toStackTraceWriter( realClassName, realMethodName, exception ); + default: + return testExecutionResult.getThrowable() + .map( t -> toStackTraceWriter( realClassName, realMethodName, t ) ) + .orElse( null ); } } - private void startTestSet( TestIdentifier testIdentifier ) + private StackTraceWriter toStackTraceWriter( String realClassName, String realMethodName, Throwable throwable ) { - runListener.testSetStarting( createTestSetReportEntry( testIdentifier ) ); - testSetNodes.add( testIdentifier ); + return new PojoStackTraceWriter( realClassName, realMethodName, throwable ); } - private void completeTestSet( TestIdentifier testIdentifier ) + /** + *
    + *
  • [0] class name - used in stacktrace parser
  • + *
  • [1] class display name
  • + *
  • [2] method signature - used in stacktrace parser
  • + *
  • [3] method display name
  • + *
+ * + * @param testIdentifier a class or method + * @return 4 elements string array + */ + private String[] toClassMethodName( TestIdentifier testIdentifier ) { - runListener.testSetCompleted( createTestSetReportEntry( testIdentifier ) ); - testSetNodes.remove( testIdentifier ); - } + Optional testSource = testIdentifier.getSource(); + String display = testIdentifier.getDisplayName(); - private void reportFailedTest( - TestIdentifier testIdentifier, TestExecutionResult testExecutionResult ) - { - SimpleReportEntry reportEntry = createReportEntry( testIdentifier, testExecutionResult ); - if ( testExecutionResult.getThrowable().filter( AssertionError.class::isInstance ).isPresent() ) + if ( testSource.filter( MethodSource.class::isInstance ).isPresent() ) { - runListener.testFailed( reportEntry ); + MethodSource methodSource = testSource.map( MethodSource.class::cast ).get(); + String realClassName = methodSource.getClassName(); + + String[] source = testPlan.getParent( testIdentifier ) + .map( this::toClassMethodName ) + .map( s -> new String[] { s[0], s[1] } ) + .orElse( new String[] { realClassName, realClassName } ); + + String simpleClassNames = COMMA_PATTERN.splitAsStream( methodSource.getMethodParameterTypes() ) + .map( s -> s.substring( 1 + s.lastIndexOf( '.' ) ) ) + .collect( joining( "," ) ); + + boolean hasParams = !simpleClassNames.isEmpty(); + String methodName = methodSource.getMethodName(); + String methodSign = methodName + '(' + simpleClassNames + ')'; + String description = testIdentifier.getLegacyReportingName(); + boolean useDesc = description.startsWith( methodSign ); + String methodDesc = hasParams ? ( useDesc ? description : methodSign ) : methodName; + String methodDisp = methodSign.equals( display ) ? methodDesc : display; + + return new String[] {source[0], source[1], methodDesc, methodDisp}; } - else + else if ( testSource.filter( ClassSource.class::isInstance ).isPresent() ) { - runListener.testError( reportEntry ); + ClassSource classSource = testSource.map( ClassSource.class::cast ).get(); + String className = classSource.getClassName(); + String simpleClassName = className.substring( 1 + className.lastIndexOf( '.' ) ); + String source = display.equals( simpleClassName ) ? className : display; + return new String[] {className, source, null, null}; } - } - - private SimpleReportEntry createTestSetReportEntry( TestIdentifier testIdentifier ) - { - return new SimpleReportEntry( - JUnitPlatformProvider.class.getName(), testIdentifier.getLegacyReportingName() ); - } - - private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier ) - { - return createReportEntry( testIdentifier, (StackTraceWriter) null ); - } - - private SimpleReportEntry createReportEntry( - TestIdentifier testIdentifier, TestExecutionResult testExecutionResult ) - { - return createReportEntry( - testIdentifier, getStackTraceWriter( testIdentifier, testExecutionResult ) ); - } - - private SimpleReportEntry createReportEntry( - TestIdentifier testIdentifier, StackTraceWriter stackTraceWriter ) - { - String source = getLegacyReportingClassName( testIdentifier ); - String name = getLegacyReportingName( testIdentifier ); - - return SimpleReportEntry.withException( source, name, stackTraceWriter ); - } - - private String getLegacyReportingName( TestIdentifier testIdentifier ) - { - // Surefire cuts off the name at the first '(' character. Thus, we have to pick a different - // character to represent parentheses. "()" are removed entirely to maximize compatibility with - // existing reporting tools because in the old days test methods used to not have parameters. - return testIdentifier - .getLegacyReportingName() - .replace( "()", "" ) - .replace( '(', '{' ) - .replace( ')', '}' ); - } - - private String getLegacyReportingClassName( TestIdentifier testIdentifier ) - { - return LegacyReportingUtils.getClassName( testPlan, testIdentifier ); - } - - private StackTraceWriter getStackTraceWriter( - TestIdentifier testIdentifier, TestExecutionResult testExecutionResult ) - { - Optional throwable = testExecutionResult.getThrowable(); - if ( testExecutionResult.getStatus() == FAILED ) + else { - // Failed tests must have a StackTraceWriter, otherwise Surefire will fail - return getStackTraceWriter( testIdentifier, throwable.orElse( null ) ); + String source = testPlan.getParent( testIdentifier ) + .map( TestIdentifier::getDisplayName ).orElse( display ); + return new String[] {source, source, display, display}; } - return throwable.map( t -> getStackTraceWriter( testIdentifier, t ) ).orElse( null ); } - private StackTraceWriter getStackTraceWriter( TestIdentifier testIdentifier, Throwable throwable ) + /** + * @return Map of tests that failed. + */ + Map getFailures() { - String className = getClassName( testIdentifier ); - String methodName = getMethodName( testIdentifier ).orElse( "" ); - return new PojoStackTraceWriter( className, methodName, throwable ); + return failures; } - private String getClassName( TestIdentifier testIdentifier ) + boolean hasFailingTests() { - TestSource testSource = testIdentifier.getSource().orElse( null ); - if ( testSource instanceof ClassSource ) - { - return ( (ClassSource) testSource ).getJavaClass().getName(); - } - if ( testSource instanceof MethodSource ) - { - return ( (MethodSource) testSource ).getClassName(); - } - return testPlan.getParent( testIdentifier ).map( this::getClassName ).orElse( "" ); + return !getFailures().isEmpty(); } - private Optional getMethodName( TestIdentifier testIdentifier ) + void reset() { - TestSource testSource = testIdentifier.getSource().orElse( null ); - if ( testSource instanceof MethodSource ) - { - return Optional.of( ( (MethodSource) testSource ).getMethodName() ); - } - return Optional.empty(); + getFailures().clear(); + testPlan = null; } } diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilter.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilter.java index c054c85a6e..891676bc63 100644 --- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilter.java +++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/TestPlanScannerFilter.java @@ -50,7 +50,7 @@ final class TestPlanScannerFilter public boolean accept( Class testClass ) { LauncherDiscoveryRequest discoveryRequest = request() - .selectors( selectClass( testClass ) ) + .selectors( selectClass( testClass.getName() ) ) .filters( includeAndExcludeFilters ).build(); TestPlan testPlan = launcher.discover( discoveryRequest ); diff --git a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnit47SuiteTest.java b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnit47SuiteTest.java new file mode 100644 index 0000000000..7db25c9b20 --- /dev/null +++ b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnit47SuiteTest.java @@ -0,0 +1,43 @@ +package org.apache.maven.surefire.junitplatform; + +/* + * 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 junit.framework.JUnit4TestAdapter; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite. + * + * @since 3.0.0-M4 + */ +public class JUnit47SuiteTest extends TestCase +{ + public static Test suite() + { + TestSuite suite = new TestSuite(); + suite.addTest( new JUnit4TestAdapter( JUnitPlatformProviderTest.class ) ); + suite.addTest( new JUnit4TestAdapter( RunListenerAdapterTest.class ) ); + suite.addTest( new JUnit4TestAdapter( TestMethodFilterTest.class ) ); + suite.addTest( new JUnit4TestAdapter( TestPlanScannerFilterTest.class ) ); + return suite; + } +} diff --git a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProviderTest.java b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProviderTest.java index c1629052a5..16a7343a95 100644 --- a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProviderTest.java +++ b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProviderTest.java @@ -26,10 +26,11 @@ import static org.apache.maven.surefire.booter.ProviderParameterNames.TESTNG_GROUPS_PROP; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.mockito.AdditionalMatchers.gt; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.inOrder; @@ -43,6 +44,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -60,8 +62,10 @@ import org.apache.maven.surefire.util.RunOrderCalculator; import org.apache.maven.surefire.util.ScanResult; import org.apache.maven.surefire.util.TestsToRun; +import org.fest.assertions.Assertions; import org.junit.Test; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; @@ -147,6 +151,247 @@ public void singleTestClassIsInvoked() assertEquals( TestClass1.TESTS_FAILED, summary.getTestsFailedCount() ); } + @Test + public void failingTestCaseAfterRerun() + throws Exception + { + Launcher launcher = LauncherFactory.create(); + ProviderParameters parameters = providerParametersMock(); + // Mock the rerun variable + when( parameters.getTestRequest().getRerunFailingTestsCount() ).thenReturn( 1 ); + + JUnitPlatformProvider provider = new JUnitPlatformProvider( parameters, launcher ); + + TestPlanSummaryListener executionListener = new TestPlanSummaryListener(); + launcher.registerTestExecutionListeners( executionListener ); + + invokeProvider( provider, TestClass2.class ); + + assertThat( executionListener.summaries ).hasSize( 2 ); + TestExecutionSummary summary = executionListener.summaries.get( 0 ); + assertEquals( TestClass2.TESTS_FOUND, summary.getTestsFoundCount() ); + assertEquals( TestClass2.TESTS_STARTED, summary.getTestsStartedCount() ); + assertEquals( TestClass2.TESTS_SKIPPED, summary.getTestsSkippedCount() ); + assertEquals( TestClass2.TESTS_SUCCEEDED, summary.getTestsSucceededCount() ); + assertEquals( TestClass2.TESTS_ABORTED, summary.getTestsAbortedCount() ); + assertEquals( TestClass2.TESTS_FAILED, summary.getTestsFailedCount() ); + + // Should only be re-running one unit test + // - And it should only fail + summary = executionListener.summaries.get( 1 ); + assertEquals( 1, summary.getTestsFoundCount() ); + assertEquals( 1, summary.getTestsStartedCount() ); + assertEquals( 0, summary.getTestsSkippedCount() ); + assertEquals( 0, summary.getTestsSucceededCount() ); + assertEquals( 0, summary.getTestsAbortedCount() ); + assertEquals( 1, summary.getTestsFailedCount() ); + } + + @Test + public void rerunStillFailing() + throws Exception + { + Launcher launcher = LauncherFactory.create(); + ProviderParameters parameters = providerParametersMock(); + // Mock the rerun variable + when( parameters.getTestRequest().getRerunFailingTestsCount() ).thenReturn( 2 ); + + JUnitPlatformProvider provider = new JUnitPlatformProvider( parameters, launcher ); + TestPlanSummaryListener executionListener = new TestPlanSummaryListener(); + launcher.registerTestExecutionListeners( executionListener ); + + // 3 unit tests: + // - fail always + // - fail twice (pass on 2nd rerun) + // - pass always + invokeProvider( provider, TestClass4.class ); + + assertThat( executionListener.summaries ).hasSize( 3 ); + TestExecutionSummary summary = executionListener.summaries.get( 0 ); + assertEquals( 6, summary.getTestsFoundCount() ); + assertEquals( 5, summary.getTestsStartedCount() ); + assertEquals( 1, summary.getTestsSkippedCount() ); + assertEquals( 1, summary.getTestsSucceededCount() ); + assertEquals( 1, summary.getTestsAbortedCount() ); + assertEquals( 3, summary.getTestsFailedCount() ); + Set failDisplays = new HashSet<>(); + for ( TestExecutionSummary.Failure failure : summary.getFailures() ) + { + failDisplays.add( failure.getTestIdentifier().getDisplayName() ); + } + assertEquals( 3, failDisplays.size() ); + assertTrue( failDisplays.contains( "Fails twice" ) ); + assertTrue( failDisplays.contains( "testAlwaysFail()" ) ); + assertTrue( failDisplays.contains( "testAlwaysError()" ) ); + + // Should rerun both of the failures + summary = executionListener.summaries.get( 1 ); + assertEquals( 3, summary.getTestsFoundCount() ); + assertEquals( 3, summary.getTestsStartedCount() ); + assertEquals( 0, summary.getTestsSkippedCount() ); + assertEquals( 0, summary.getTestsSucceededCount() ); + assertEquals( 0, summary.getTestsAbortedCount() ); + assertEquals( 3, summary.getTestsFailedCount() ); + failDisplays.clear(); + for ( TestExecutionSummary.Failure failure : summary.getFailures() ) + { + failDisplays.add( failure.getTestIdentifier().getDisplayName() ); + } + assertEquals( 3, failDisplays.size() ); + assertTrue( failDisplays.contains( "Fails twice" ) ); + assertTrue( failDisplays.contains( "testAlwaysFail()" ) ); + assertTrue( failDisplays.contains( "testAlwaysError()" ) ); + + // now only one failure should remain + summary = executionListener.summaries.get( 2 ); + assertEquals( 3, summary.getTestsFoundCount() ); + assertEquals( 3, summary.getTestsStartedCount() ); + assertEquals( 0, summary.getTestsSkippedCount() ); + assertEquals( 1, summary.getTestsSucceededCount() ); + assertEquals( 0, summary.getTestsAbortedCount() ); + assertEquals( 2, summary.getTestsFailedCount() ); + failDisplays.clear(); + for ( TestExecutionSummary.Failure failure : summary.getFailures() ) + { + failDisplays.add( failure.getTestIdentifier().getDisplayName() ); + } + assertEquals( 2, failDisplays.size() ); + assertTrue( failDisplays.contains( "testAlwaysFail()" ) ); + assertTrue( failDisplays.contains( "testAlwaysError()" ) ); + } + + @Test + public void rerunWithSuccess() + throws Exception + { + Launcher launcher = LauncherFactory.create(); + ProviderParameters parameters = providerParametersMock(); + // Mock the rerun variable + when( parameters.getTestRequest().getRerunFailingTestsCount() ).thenReturn( 2 ); + when( parameters.getProviderProperties() ) + .thenReturn( singletonMap( JUnitPlatformProvider.CONFIGURATION_PARAMETERS, + "forkCount = 1\nreuseForks = true" ) ); + + JUnitPlatformProvider provider = new JUnitPlatformProvider( parameters, launcher ); + TestPlanSummaryListener executionListener = new TestPlanSummaryListener(); + launcher.registerTestExecutionListeners( executionListener ); + + invokeProvider( provider, TestClass5.class ); + + assertThat( executionListener.summaries ).hasSize( 3 ); + TestExecutionSummary summary = executionListener.summaries.get( 0 ); + assertEquals( 1, summary.getTestsFoundCount() ); + assertEquals( 1, summary.getTestsStartedCount() ); + assertEquals( 0, summary.getTestsSucceededCount() ); + assertEquals( 1, summary.getTestsFailedCount() ); + + summary = executionListener.summaries.get( 1 ); + assertEquals( 1, summary.getTestsFoundCount() ); + assertEquals( 1, summary.getTestsStartedCount() ); + assertEquals( 0, summary.getTestsSucceededCount() ); + assertEquals( 1, summary.getTestsFailedCount() ); + + summary = executionListener.summaries.get( 2 ); + assertEquals( 1, summary.getTestsFoundCount() ); + assertEquals( 1, summary.getTestsStartedCount() ); + assertEquals( 1, summary.getTestsSucceededCount() ); + assertEquals( 0, summary.getTestsFailedCount() ); + } + + @Test + public void runDisplayNameTest() throws Exception + { + Launcher launcher = LauncherFactory.create(); + ProviderParameters parameters = providerParametersMock(); + JUnitPlatformProvider provider = new JUnitPlatformProvider( parameters, launcher ); + + RunListener listener = mock( RunListener.class ); + ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( ReportEntry.class ); + RunListenerAdapter adapter = new RunListenerAdapter( listener ); + + launcher.registerTestExecutionListeners( adapter ); + + invokeProvider( provider, DisplayNameTest.class ); + + verify( listener, times( 1 ) ).testStarting( entryCaptor.capture() ); + List reportEntries = entryCaptor.getAllValues(); + + assertEquals( 1, reportEntries.size() ); + + assertEquals( DisplayNameTest.class.getName(), reportEntries.get( 0 ).getSourceName() ); + assertEquals( "<< ✨ >>", reportEntries.get( 0 ).getSourceText() ); + assertEquals( "test1", reportEntries.get( 0 ).getName() ); + assertEquals( "73$71 ✔", reportEntries.get( 0 ).getNameText() ); + } + + @Test + public void rerunParameterized() + throws Exception + { + Launcher launcher = LauncherFactory.create(); + ProviderParameters parameters = providerParametersMock(); + // Mock the rerun variable + when( parameters.getTestRequest().getRerunFailingTestsCount() ).thenReturn( 2 ); + when( parameters.getProviderProperties() ) + .thenReturn( singletonMap( JUnitPlatformProvider.CONFIGURATION_PARAMETERS, + "forkCount = 1\nreuseForks = true" ) ); + + JUnitPlatformProvider provider = new JUnitPlatformProvider( parameters, launcher ); + + TestPlanSummaryListener executionListener = new TestPlanSummaryListener(); + + RunListener listener = mock( RunListener.class ); + ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( ReportEntry.class ); + RunListenerAdapter adapter = new RunListenerAdapter( listener ); + + launcher.registerTestExecutionListeners( executionListener, adapter ); + + invokeProvider( provider, TestClass7.class ); + + assertThat( executionListener.summaries ).hasSize( 3 ); + + verify( listener, times( 4 ) ).testStarting( entryCaptor.capture() ); + List reportEntries = entryCaptor.getAllValues(); + + assertEquals( TestClass7.class.getName(), reportEntries.get( 0 ).getSourceName() ); + assertNull( reportEntries.get( 0 ).getSourceText() ); + assertEquals( "testParameterizedTestCases(String, boolean)[1]", reportEntries.get( 0 ).getName() ); + assertEquals( "[1] Always pass, true", reportEntries.get( 0 ).getNameText() ); + + assertEquals( TestClass7.class.getName(), reportEntries.get( 1 ).getSourceName() ); + assertNull( reportEntries.get( 1 ).getSourceText() ); + assertEquals( "testParameterizedTestCases(String, boolean)[2]", reportEntries.get( 1 ).getName() ); + assertEquals( "[2] Always fail, false", reportEntries.get( 1 ).getNameText() ); + + assertEquals( TestClass7.class.getName(), reportEntries.get( 2 ).getSourceName() ); + assertNull( reportEntries.get( 2 ).getSourceText() ); + assertEquals( "testParameterizedTestCases(String, boolean)[2]", reportEntries.get( 2 ).getName() ); + assertEquals( "[2] Always fail, false", reportEntries.get( 2 ).getNameText() ); + + assertEquals( TestClass7.class.getName(), reportEntries.get( 3 ).getSourceName() ); + assertNull( reportEntries.get( 3 ).getSourceText() ); + assertEquals( "testParameterizedTestCases(String, boolean)[2]", reportEntries.get( 3 ).getName() ); + assertEquals( "[2] Always fail, false", reportEntries.get( 3 ).getNameText() ); + + TestExecutionSummary summary = executionListener.summaries.get( 0 ); + assertEquals( 2, summary.getTestsFoundCount() ); + assertEquals( 2, summary.getTestsStartedCount() ); + assertEquals( 1, summary.getTestsSucceededCount() ); + assertEquals( 1, summary.getTestsFailedCount() ); + + summary = executionListener.summaries.get( 1 ); + assertEquals( 1, summary.getTestsFoundCount() ); + assertEquals( 1, summary.getTestsStartedCount() ); + assertEquals( 0, summary.getTestsSucceededCount() ); + assertEquals( 1, summary.getTestsFailedCount() ); + + summary = executionListener.summaries.get( 2 ); + assertEquals( 1, summary.getTestsFoundCount() ); + assertEquals( 1, summary.getTestsStartedCount() ); + assertEquals( 0, summary.getTestsSucceededCount() ); + assertEquals( 1, summary.getTestsFailedCount() ); + } + @Test public void allDiscoveredTestsAreInvokedForNullArgument() throws Exception @@ -163,30 +408,38 @@ public void allDiscoveredTestsAreInvokedForNullArgument() invokeProvider( provider, null ); InOrder inOrder = inOrder( runListener ); - inOrder - .verify( runListener ) - .testSetStarting( - new SimpleReportEntry( - JUnitPlatformProvider.class.getName(), - TestClass1.class.getName() ) ); - inOrder - .verify( runListener ) - .testSetCompleted( - new SimpleReportEntry( - JUnitPlatformProvider.class.getName(), - TestClass1.class.getName() ) ); - inOrder - .verify( runListener ) - .testSetStarting( - new SimpleReportEntry( - JUnitPlatformProvider.class.getName(), - TestClass2.class.getName() ) ); - inOrder - .verify( runListener ) - .testSetCompleted( - new SimpleReportEntry( - JUnitPlatformProvider.class.getName(), - TestClass2.class.getName() ) ); + + ArgumentCaptor report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + inOrder.verify( runListener ) + .testSetStarting( report.capture() ); + Assertions.assertThat( report.getValue().getSourceName() ) + .isEqualTo( TestClass1.class.getName() ); + Assertions.assertThat( report.getValue().getName() ) + .isNull(); + + report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + inOrder.verify( runListener ) + .testSetCompleted( report.capture() ); + Assertions.assertThat( report.getValue().getSourceName() ) + .isEqualTo( TestClass1.class.getName() ); + Assertions.assertThat( report.getValue().getName() ) + .isNull(); + + report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + inOrder.verify( runListener ) + .testSetStarting( report.capture() ); + Assertions.assertThat( report.getValue().getSourceName() ) + .isEqualTo( TestClass2.class.getName() ); + Assertions.assertThat( report.getValue().getName() ) + .isNull(); + + report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + inOrder.verify( runListener ) + .testSetCompleted( report.capture() ); + Assertions.assertThat( report.getValue().getSourceName() ) + .isEqualTo( TestClass2.class.getName() ); + Assertions.assertThat( report.getValue().getName() ) + .isNull(); assertThat( executionListener.summaries ).hasSize( 1 ); TestExecutionSummary summary = executionListener.summaries.get( 0 ); @@ -212,16 +465,14 @@ public void outputIsCaptured() invokeProvider( provider, VerboseTestClass.class ); - ArgumentCaptor captor = ArgumentCaptor.forClass( byte[].class ); - // @formatter:off + ArgumentCaptor captor = ArgumentCaptor.forClass( String.class ); verify( (ConsoleOutputReceiver) runListener ) - .writeTestOutput( captor.capture(), eq( 0 ), gt( 6 ), eq( true ) ); + .writeTestOutput( captor.capture(), eq( true ), eq( true ) ); verify( (ConsoleOutputReceiver) runListener ) - .writeTestOutput( captor.capture(), eq( 0 ), gt( 6 ), eq( false ) ); + .writeTestOutput( captor.capture(), eq( true ), eq( false ) ); assertThat( captor.getAllValues() ) - .extracting( bytes -> new String( bytes, 0, 6 ) ) - .containsExactly( "stdout", "stderr" ); - // @formatter:on + .hasSize( 2 ) + .containsExactly( "stdout", "stderr" ); } @Test @@ -522,7 +773,6 @@ private static TestsToRun newTestsToRun( Class... testClasses ) private static class TestPlanSummaryListener extends SummaryGeneratingListener { - private final List summaries = new ArrayList<>(); @Override @@ -701,4 +951,87 @@ void prefix2Suffix2() throw new RuntimeException(); } } + + static class TestClass4 + { + static int count; + + @org.junit.jupiter.api.DisplayName( "Always passes" ) + @org.junit.jupiter.api.Test + void testPass() + { + } + + @org.junit.jupiter.api.Test + void testAborted() + { + assumeFalse( true ); + throw new IllegalStateException( "this exception should never happen" ); + } + + @org.junit.jupiter.api.Test + void testAlwaysError() + { + throw new Error( "some error" ); + } + + @org.junit.jupiter.api.Test + void testAlwaysFail() + { + assertTrue( false ); + } + + @org.junit.jupiter.api.Test + @org.junit.jupiter.api.Disabled + void testAlwaysSkipped() + { + throw new IllegalStateException( "this test should be never called" ); + } + + @org.junit.jupiter.api.DisplayName( "Fails twice" ) + @org.junit.jupiter.api.Test + void testFailTwice() + { + count += 1; + assertTrue( count >= 3 ); + } + } + + static class TestClass5 + { + static int count; + + @org.junit.jupiter.api.Test + void testFailTwice1() + { + count += 1; + assertTrue( count >= 3 ); + } + } + + static class TestClass7 + { + static List params() + { + return Arrays.asList( new Object[] { "Always pass", true }, + new Object[] { "Always fail", false } ); + } + + @org.junit.jupiter.params.ParameterizedTest + @org.junit.jupiter.params.provider.MethodSource( "params" ) + void testParameterizedTestCases( String testName, boolean value ) + { + assertTrue( value ); + } + } + + @DisplayName( "<< ✨ >>" ) + static class DisplayNameTest + { + @org.junit.jupiter.api.Test + @DisplayName( "73$71 ✔" ) + void test1() + { + } + } } diff --git a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTest.java b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTest.java index 0ccb4feff8..6e9eeeb6c2 100644 --- a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTest.java +++ b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/RunListenerAdapterTest.java @@ -22,27 +22,35 @@ import static java.util.Collections.emptyList; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; +import static org.fest.assertions.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.engine.TestDescriptor.Type.CONTAINER; import static org.junit.platform.engine.TestDescriptor.Type.TEST; +import static org.junit.platform.engine.TestExecutionResult.aborted; +import static org.junit.platform.engine.TestExecutionResult.failed; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static org.powermock.reflect.Whitebox.getInternalState; +import java.lang.reflect.Method; +import java.util.Map; import java.util.Optional; +import org.apache.maven.surefire.report.PojoStackTraceWriter; import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.SimpleReportEntry; +import org.apache.maven.surefire.report.StackTraceWriter; +import org.apache.maven.surefire.report.TestSetReportEntry; import org.junit.Before; import org.junit.Test; import org.junit.jupiter.api.DisplayName; @@ -50,17 +58,17 @@ import org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.TestDescriptor; -import org.junit.platform.engine.TestDescriptor.Type; -import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.EngineDescriptor; +import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; +import org.opentest4j.TestSkippedException; /** * Unit tests for {@link RunListenerAdapter}. @@ -69,7 +77,7 @@ */ public class RunListenerAdapterTest { - private static final ConfigurationParameters CONFIG_PARAMS = mock(ConfigurationParameters.class); + private static final ConfigurationParameters CONFIG_PARAMS = mock( ConfigurationParameters.class ); private RunListener listener; @@ -120,8 +128,10 @@ public void notifiedWithCompatibleNameForMethodWithArguments() verify( listener ).testStarting( entryCaptor.capture() ); ReportEntry entry = entryCaptor.getValue(); - assertEquals( MY_TEST_METHOD_NAME + "{String}", entry.getName() ); + assertEquals( MY_TEST_METHOD_NAME + "(String)", entry.getName() ); + assertNull( entry.getNameText() ); assertEquals( MyTestClass.class.getName(), entry.getSourceName() ); + assertNull( entry.getSourceText() ); assertNull( entry.getStackTraceWriter() ); } @@ -136,24 +146,48 @@ public void notifiedEagerlyForTestSetWhenClassExecutionStarted() parent.addChild( child ); TestPlan plan = TestPlan.from( singletonList( engine ) ); + String className = MyTestClass.class.getName(); + adapter.testPlanExecutionStarted( plan ); adapter.executionStarted( TestIdentifier.from( engine ) ); adapter.executionStarted( TestIdentifier.from( parent ) ); - verify( listener ).testSetStarting( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), - MyTestClass.class.getName() ) ); + verify( listener ) + .testSetStarting( new SimpleReportEntry( className, null, null, null ) ); verifyNoMoreInteractions( listener ); adapter.executionStarted( TestIdentifier.from( child ) ); - verify( listener ).testStarting( new SimpleReportEntry( MyTestClass.class.getName(), MY_TEST_METHOD_NAME ) ); + verify( listener ) + .testStarting( new SimpleReportEntry( className, null, MY_TEST_METHOD_NAME, null ) ); verifyNoMoreInteractions( listener ); adapter.executionFinished( TestIdentifier.from( child ), successful() ); - verify( listener ).testSucceeded( new SimpleReportEntry( MyTestClass.class.getName(), MY_TEST_METHOD_NAME ) ); + ArgumentCaptor report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + verify( listener ).testSucceeded( report.capture() ); + assertThat( report.getValue().getSourceName() ) + .isEqualTo( className ); + assertThat( report.getValue().getSourceText() ) + .isNull(); + assertThat( report.getValue().getName() ) + .isEqualTo( MY_TEST_METHOD_NAME ); + assertThat( report.getValue().getNameText() ) + .isNull(); + assertThat( report.getValue().getElapsed() ) + .isNotNull(); + assertThat( report.getValue().getSystemProperties() ) + .isEmpty(); verifyNoMoreInteractions( listener ); adapter.executionFinished( TestIdentifier.from( parent ), successful() ); - verify( listener ).testSetCompleted( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), - MyTestClass.class.getName() ) ); + report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + verify( listener ).testSetCompleted( report.capture() ); + assertThat( report.getValue().getSourceName() ) + .isEqualTo( className ); + assertThat( report.getValue().getName() ) + .isNull(); + assertThat( report.getValue().getElapsed() ) + .isNotNull(); + assertThat( report.getValue().getSystemProperties() ) + .isNotEmpty(); verifyNoMoreInteractions( listener ); adapter.executionFinished( TestIdentifier.from( engine ), successful() ); @@ -161,53 +195,118 @@ public void notifiedEagerlyForTestSetWhenClassExecutionStarted() } @Test - public void notifiedLazilyForTestSetWhenFirstTestWithoutClassDescriptorParentStarted() + public void displayNamesInClassAndMethods() + throws Exception { EngineDescriptor engine = newEngineDescriptor(); - TestDescriptor parent = newTestDescriptor( engine.getUniqueId().append( "container", "noClass" ), "parent", - CONTAINER ); + TestDescriptor parent = newClassDescriptor( "parent" ); engine.addChild( parent ); - TestDescriptor child1 = newTestDescriptor( parent.getUniqueId().append( "test", "child1" ), "child1", TEST ); + + UniqueId id1 = parent.getUniqueId().append( MyTestClass.class.getName(), MY_NAMED_TEST_METHOD_NAME ); + Method m1 = MyTestClass.class.getDeclaredMethod( MY_NAMED_TEST_METHOD_NAME ); + TestDescriptor child1 = new TestMethodTestDescriptorWithDisplayName( id1, MyTestClass.class, m1, "dn1" ); parent.addChild( child1 ); - TestDescriptor child2 = newTestDescriptor( parent.getUniqueId().append( "test", "child2" ), "child2", TEST ); + + UniqueId id2 = parent.getUniqueId().append( MyTestClass.class.getName(), MY_TEST_METHOD_NAME ); + Method m2 = MyTestClass.class.getDeclaredMethod( MY_TEST_METHOD_NAME, String.class ); + TestDescriptor child2 = new TestMethodTestDescriptor( id2, MyTestClass.class, m2 ); parent.addChild( child2 ); + TestPlan plan = TestPlan.from( singletonList( engine ) ); + InOrder inOrder = inOrder( listener ); + adapter.testPlanExecutionStarted( plan ); + adapter.executionStarted( TestIdentifier.from( engine ) ); adapter.executionStarted( TestIdentifier.from( parent ) ); + ArgumentCaptor report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + inOrder.verify( listener ).testSetStarting( report.capture() ); + assertThat( report.getValue().getSourceName() ) + .isEqualTo( MyTestClass.class.getName() ); + assertThat( report.getValue().getSourceText() ) + .isEqualTo( "parent" ); + assertThat( report.getValue().getName() ) + .isNull(); + assertThat( report.getValue().getSystemProperties() ) + .isEmpty(); verifyZeroInteractions( listener ); adapter.executionStarted( TestIdentifier.from( child1 ) ); - InOrder inOrder = inOrder( listener ); inOrder.verify( listener ) - .testSetStarting( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), "parent" ) ); - inOrder.verify( listener ).testStarting( new SimpleReportEntry( "parent", "child1" ) ); + .testStarting( new SimpleReportEntry( MyTestClass.class.getName(), "parent", + MY_NAMED_TEST_METHOD_NAME, "dn1" ) ); inOrder.verifyNoMoreInteractions(); adapter.executionFinished( TestIdentifier.from( child1 ), successful() ); - verify( listener ).testSucceeded( new SimpleReportEntry( "parent", "child1" ) ); - verifyNoMoreInteractions( listener ); + report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + inOrder.verify( listener ).testSucceeded( report.capture() ); + assertThat( report.getValue().getSourceName() ) + .isEqualTo( MyTestClass.class.getName() ); + assertThat( report.getValue().getSourceText() ) + .isEqualTo( "parent" ); + assertThat( report.getValue().getName() ) + .isEqualTo( MY_NAMED_TEST_METHOD_NAME ); + assertThat( report.getValue().getNameText() ) + .isEqualTo( "dn1" ); + assertThat( report.getValue().getElapsed() ) + .isNotNull(); + assertThat( report.getValue().getSystemProperties() ) + .isEmpty(); + inOrder.verifyNoMoreInteractions(); adapter.executionStarted( TestIdentifier.from( child2 ) ); - verify( listener ).testStarting( new SimpleReportEntry( "parent", "child2" ) ); - verifyNoMoreInteractions( listener ); + inOrder.verify( listener ) + .testStarting( new SimpleReportEntry( MyTestClass.class.getName(), "parent", + MY_TEST_METHOD_NAME + "(String)", null ) ); + inOrder.verifyNoMoreInteractions(); - adapter.executionFinished( TestIdentifier.from( child2 ), successful() ); - verify( listener ).testSucceeded( new SimpleReportEntry( "parent", "child2" ) ); - verifyNoMoreInteractions( listener ); + Exception assumptionFailure = new Exception(); + adapter.executionFinished( TestIdentifier.from( child2 ), aborted( assumptionFailure ) ); + report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + inOrder.verify( listener ).testAssumptionFailure( report.capture() ); + assertThat( report.getValue().getSourceName() ) + .isEqualTo( MyTestClass.class.getName() ); + assertThat( report.getValue().getSourceText() ) + .isEqualTo( "parent" ); + assertThat( report.getValue().getName() ) + .isEqualTo( MY_TEST_METHOD_NAME + "(String)" ); + assertThat( report.getValue().getNameText() ) + .isNull(); + assertThat( report.getValue().getElapsed() ) + .isNotNull(); + assertThat( report.getValue().getSystemProperties() ) + .isEmpty(); + assertThat( report.getValue().getStackTraceWriter() ) + .isNotNull(); + assertThat( report.getValue().getStackTraceWriter().getThrowable().getTarget() ) + .isSameAs( assumptionFailure ); + inOrder.verifyNoMoreInteractions(); adapter.executionFinished( TestIdentifier.from( parent ), successful() ); - verify( listener ) - .testSetCompleted( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), "parent" ) ); - verifyNoMoreInteractions( listener ); + inOrder.verify( listener ).testSetCompleted( report.capture() ); + assertThat( report.getValue().getSourceName() ) + .isEqualTo( MyTestClass.class.getName() ); + assertThat( report.getValue().getSourceText() ) + .isEqualTo( "parent" ); + assertThat( report.getValue().getName() ) + .isNull(); + assertThat( report.getValue().getNameText() ) + .isNull(); + assertThat( report.getValue().getElapsed() ) + .isNotNull(); + assertThat( report.getValue().getSystemProperties() ) + .isNotEmpty(); + assertThat( report.getValue().getStackTraceWriter() ) + .isNull(); + inOrder.verifyNoMoreInteractions(); adapter.executionFinished( TestIdentifier.from( engine ), successful() ); - verifyNoMoreInteractions( listener ); + inOrder.verifyNoMoreInteractions(); } @Test - public void notifiedForTestSetForSingleNodeEngine() + public void notifiedForUnclassifiedTestIdentifier() { EngineDescriptor engine = new EngineDescriptor( UniqueId.forEngine( "engine" ), "engine" ) { @@ -220,19 +319,42 @@ public Type getType() TestPlan plan = TestPlan.from( singletonList( engine ) ); adapter.testPlanExecutionStarted( plan ); + assertThat( (TestPlan) getInternalState( adapter, "testPlan" ) ) + .isSameAs( plan ); + assertThat( (Map) getInternalState( adapter, "testStartTime" ) ) + .isEmpty(); + + adapter.executionStarted( TestIdentifier.from( engine ) ); - InOrder inOrder = inOrder( listener ); - inOrder.verify( listener ) - .testSetStarting( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), "engine" ) ); - inOrder.verify( listener ).testStarting( new SimpleReportEntry( "", "engine" ) ); - inOrder.verifyNoMoreInteractions(); + verify( listener ) + .testStarting( new SimpleReportEntry( "engine", null, "engine", null ) ); + verifyNoMoreInteractions( listener ); adapter.executionFinished( TestIdentifier.from( engine ), successful() ); - inOrder = inOrder( listener ); - inOrder.verify( listener ).testSucceeded( new SimpleReportEntry( "", "engine" ) ); - inOrder.verify( listener ) - .testSetCompleted( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), "engine" ) ); - inOrder.verifyNoMoreInteractions(); + ArgumentCaptor report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + verify( listener ).testSucceeded( report.capture() ); + assertThat( report.getValue().getSourceName() ) + .isEqualTo( "engine" ); + assertThat( report.getValue().getSourceText() ) + .isNull(); + assertThat( report.getValue().getName() ) + .isEqualTo( "engine" ); + assertThat( report.getValue().getNameText() ) + .isNull(); + assertThat( report.getValue().getElapsed() ) + .isNotNull(); + assertThat( report.getValue().getStackTraceWriter() ) + .isNull(); + assertThat( report.getValue().getSystemProperties() ) + .isEmpty(); + + adapter.testPlanExecutionFinished( plan ); + assertThat( (TestPlan) getInternalState( adapter, "testPlan" ) ) + .isNull(); + assertThat( (Map) getInternalState( adapter, "testStartTime" ) ) + .isEmpty(); + + verifyNoMoreInteractions( listener ); } @Test @@ -264,7 +386,7 @@ public void notifiedWithCorrectNamesWhenClassExecutionSkipped() verify( listener ).testSkipped( entryCaptor.capture() ); ReportEntry entry = entryCaptor.getValue(); - assertTrue( MyTestClass.class.getTypeName().contains( entry.getName() ) ); + assertNull( entry.getName() ); assertEquals( MyTestClass.class.getTypeName(), entry.getSourceName() ); } @@ -279,48 +401,59 @@ public void notifiedWhenEngineExecutionSkipped() public void notifiedWhenMethodExecutionAborted() throws Exception { - adapter.executionFinished( newMethodIdentifier(), TestExecutionResult.aborted( null ) ); + adapter.executionFinished( newMethodIdentifier(), aborted( null ) ); verify( listener ).testAssumptionFailure( any() ); } @Test public void notifiedWhenClassExecutionAborted() { - adapter.executionFinished( newClassIdentifier(), TestExecutionResult.aborted( null ) ); - verify( listener ).testAssumptionFailure( any() ); + TestSkippedException t = new TestSkippedException( "skipped" ); + adapter.executionFinished( newClassIdentifier(), aborted( t ) ); + String source = MyTestClass.class.getName(); + StackTraceWriter stw = new PojoStackTraceWriter( source, null, t ); + ArgumentCaptor report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + verify( listener ).testSetCompleted( report.capture() ); + assertThat( report.getValue().getSourceName() ) + .isEqualTo( source ); + assertThat( report.getValue().getStackTraceWriter() ) + .isEqualTo( stw ); } @Test - public void notifiedWhenMethodExecutionFailedWithAnAssertionError() + public void notifiedWhenMethodExecutionFailed() throws Exception { - adapter.executionFinished( newMethodIdentifier(), TestExecutionResult.failed( new AssertionError() ) ); + adapter.executionFinished( newMethodIdentifier(), failed( new AssertionError() ) ); verify( listener ).testFailed( any() ); } @Test - public void notifiedWhenMethodExecutionFailedWithANonAssertionError() + public void notifiedWhenMethodExecutionFailedWithError() throws Exception { - adapter.executionFinished( newMethodIdentifier(), TestExecutionResult.failed( new RuntimeException() ) ); + adapter.executionFinished( newMethodIdentifier(), failed( new RuntimeException() ) ); verify( listener ).testError( any() ); } @Test public void notifiedWithCorrectNamesWhenClassExecutionFailed() { - ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( ReportEntry.class ); + ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( TestSetReportEntry.class ); TestPlan testPlan = TestPlan.from( singletonList( new EngineDescriptor( newId(), "Luke's Plan" ) ) ); adapter.testPlanExecutionStarted( testPlan ); - adapter.executionFinished( - identifiersAsParentOnTestPlan( testPlan, newEngineDescriptor(), newClassDescriptor() ), - TestExecutionResult.failed( new AssertionError() ) ); - verify( listener ).testFailed( entryCaptor.capture() ); + adapter.executionFinished( identifiersAsParentOnTestPlan( testPlan, newClassDescriptor() ), + failed( new AssertionError() ) ); + verify( listener ).testSetCompleted( entryCaptor.capture() ); ReportEntry entry = entryCaptor.getValue(); assertEquals( MyTestClass.class.getTypeName(), entry.getSourceName() ); + assertNull( entry.getName() ); assertNotNull( entry.getStackTraceWriter() ); + assertNotNull( entry.getStackTraceWriter().getThrowable() ); + assertThat( entry.getStackTraceWriter().getThrowable().getTarget() ) + .isInstanceOf( AssertionError.class ); } @Test @@ -342,10 +475,34 @@ public void notifiedForTestSetWhenClassExecutionSucceeded() adapter.executionFinished( TestIdentifier.from( classDescriptor ), successful() ); - verify( listener ).testSetCompleted( new SimpleReportEntry( JUnitPlatformProvider.class.getName(), - MyTestClass.class.getName() ) ); + String className = MyTestClass.class.getName(); + + verify( listener ) + .testSetStarting( new SimpleReportEntry( className, null, null, null ) ); + + ArgumentCaptor report = ArgumentCaptor.forClass( SimpleReportEntry.class ); + verify( listener ) + .testSetCompleted( report.capture() ); + + assertThat( report.getValue().getSourceName() ) + .isEqualTo( className ); + assertThat( report.getValue().getSourceText() ) + .isNull(); + assertThat( report.getValue().getName() ) + .isNull(); + assertThat( report.getValue().getNameText() ) + .isNull(); + assertThat( report.getValue().getStackTraceWriter() ) + .isNull(); + assertThat( report.getValue().getElapsed() ) + .isNotNull(); + assertThat( report.getValue().getSystemProperties() ) + .isNotEmpty(); + + verify( listener, never() ) + .testSucceeded( any() ); - verify( listener, never() ).testSucceeded( any() ); + verifyNoMoreInteractions( listener ); } @Test @@ -365,6 +522,9 @@ public void notifiedWithParentDisplayNameWhenTestClassUnknown() ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( ReportEntry.class ); verify( listener ).testStarting( entryCaptor.capture() ); assertEquals( parentDisplay, entryCaptor.getValue().getSourceName() ); + assertNull( entryCaptor.getValue().getSourceText() ); + assertNull( entryCaptor.getValue().getName() ); + assertNull( entryCaptor.getValue().getNameText() ); } @Test @@ -375,7 +535,7 @@ public void stackTraceWriterPresentWhenParentHasSource() TestIdentifier child = newSourcelessChildIdentifierWithParent( plan, "Parent", ClassSource.from( MyTestClass.class ) ); - adapter.executionFinished( child, TestExecutionResult.failed( new RuntimeException() ) ); + adapter.executionFinished( child, failed( new RuntimeException() ) ); ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( ReportEntry.class ); verify( listener ).testError( entryCaptor.capture() ); assertNotNull( entryCaptor.getValue().getStackTraceWriter() ); @@ -388,7 +548,7 @@ public void stackTraceWriterDefaultsToTestClass() adapter.testPlanExecutionStarted( plan ); TestIdentifier child = newSourcelessChildIdentifierWithParent( plan, "Parent", null ); - adapter.executionFinished( child, TestExecutionResult.failed( new RuntimeException( "message" ) ) ); + adapter.executionFinished( child, failed( new RuntimeException( "message" ) ) ); ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( ReportEntry.class ); verify( listener ).testError( entryCaptor.capture() ); assertNotNull( entryCaptor.getValue().getStackTraceWriter() ); @@ -401,7 +561,7 @@ public void stackTraceWriterDefaultsToTestClass() public void stackTraceWriterPresentEvenWithoutException() throws Exception { - adapter.executionFinished( newMethodIdentifier(), TestExecutionResult.failed( null ) ); + adapter.executionFinished( newMethodIdentifier(), failed( null ) ); ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( ReportEntry.class ); verify( listener ).testError( entryCaptor.capture() ); assertNotNull( entryCaptor.getValue().getStackTraceWriter() ); @@ -411,8 +571,8 @@ public void stackTraceWriterPresentEvenWithoutException() public void displayNamesIgnoredInReport() throws NoSuchMethodException { - TestMethodTestDescriptor descriptor = new TestMethodTestDescriptor( newId(), MyTestClass.class, - MyTestClass.class.getDeclaredMethod( "myNamedTestMethod" ) ); + TestMethodTestDescriptorWithDisplayName descriptor = new TestMethodTestDescriptorWithDisplayName( newId(), + MyTestClass.class, MyTestClass.class.getDeclaredMethod( "myNamedTestMethod" ), "some display name" ); TestIdentifier factoryIdentifier = TestIdentifier.from( descriptor ); ArgumentCaptor entryCaptor = ArgumentCaptor.forClass( ReportEntry.class ); @@ -422,7 +582,10 @@ public void displayNamesIgnoredInReport() ReportEntry value = entryCaptor.getValue(); + assertEquals( MyTestClass.class.getName(), value.getSourceName() ); + assertNull( value.getSourceText() ); assertEquals( "myNamedTestMethod", value.getName() ); + assertEquals( "some display name", value.getNameText() ); } private static TestIdentifier newMethodIdentifier() @@ -445,9 +608,17 @@ private static TestIdentifier newClassIdentifier() return TestIdentifier.from( newClassDescriptor() ); } + private static TestDescriptor newClassDescriptor( String displayName ) + { + return new ClassTestDescriptor( UniqueId.root( "class", MyTestClass.class.getName() ), + c -> displayName, MyTestClass.class, CONFIG_PARAMS ) + { }; + } + private static TestDescriptor newClassDescriptor() { - return new ClassTestDescriptor( UniqueId.root( "class", MyTestClass.class.getName() ), MyTestClass.class, CONFIG_PARAMS ); + return new ClassTestDescriptor( UniqueId.root( "class", MyTestClass.class.getName() ), + MyTestClass.class, CONFIG_PARAMS ); } private static TestIdentifier newSourcelessChildIdentifierWithParent( @@ -490,18 +661,6 @@ private static EngineDescriptor newEngineDescriptor() return new EngineDescriptor( UniqueId.forEngine( "engine" ), "engine" ); } - private TestDescriptor newTestDescriptor( UniqueId uniqueId, String displayName, Type type ) - { - return new AbstractTestDescriptor( uniqueId, displayName ) - { - @Override - public Type getType() - { - return type; - } - }; - } - private static TestIdentifier identifiersAsParentOnTestPlan( TestPlan plan, TestDescriptor parent, TestDescriptor child ) { @@ -516,12 +675,20 @@ private static TestIdentifier identifiersAsParentOnTestPlan( return childIdentifier; } + private static TestIdentifier identifiersAsParentOnTestPlan( TestPlan plan, TestDescriptor root ) + { + TestIdentifier rootIdentifier = TestIdentifier.from( root ); + plan.add( rootIdentifier ); + return rootIdentifier; + } + private static UniqueId newId() { return UniqueId.forEngine( "engine" ); } private static final String MY_TEST_METHOD_NAME = "myTestMethod"; + private static final String MY_NAMED_TEST_METHOD_NAME = "myNamedTestMethod"; private static class MyTestClass { @@ -541,4 +708,19 @@ void myNamedTestMethod() { } } + + static class TestMethodTestDescriptorWithDisplayName extends AbstractTestDescriptor + { + private TestMethodTestDescriptorWithDisplayName( UniqueId uniqueId, + Class testClass, Method testMethod, String displayName ) + { + super( uniqueId, displayName, MethodSource.from( testClass, testMethod ) ); + } + + @Override + public Type getType() + { + return Type.TEST; + } + } } diff --git a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestMethodFilterTest.java b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestMethodFilterTest.java index 6d4394e7ea..a03d58bdd0 100644 --- a/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestMethodFilterTest.java +++ b/surefire-providers/surefire-junit-platform/src/test/java/org/apache/maven/surefire/junitplatform/TestMethodFilterTest.java @@ -42,7 +42,7 @@ */ public class TestMethodFilterTest { - private static final ConfigurationParameters CONFIG_PARAMS = mock(ConfigurationParameters.class); + private static final ConfigurationParameters CONFIG_PARAMS = mock( ConfigurationParameters.class ); private final TestListResolver resolver = mock( TestListResolver.class ); @@ -96,6 +96,9 @@ private static ClassTestDescriptor newClassTestDescriptor() return new ClassTestDescriptor( uniqueId, TestClass.class, CONFIG_PARAMS ); } + /** + * + */ public static class TestClass { public void testMethod() diff --git a/surefire-providers/surefire-junit3/pom.xml b/surefire-providers/surefire-junit3/pom.xml index a8661b43ef..bac9a82163 100644 --- a/surefire-providers/surefire-junit3/pom.xml +++ b/surefire-providers/surefire-junit3/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 surefire-junit3 @@ -44,4 +44,37 @@ ${project.version}
+ + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + + + + diff --git a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java index b8c83e1f8f..e625888bb2 100644 --- a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java +++ b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/JUnit3Provider.java @@ -28,6 +28,7 @@ import org.apache.maven.surefire.report.ReporterFactory; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.SimpleReportEntry; +import org.apache.maven.surefire.report.TestSetReportEntry; import org.apache.maven.surefire.suite.RunResult; import org.apache.maven.surefire.testset.TestSetFailedException; import org.apache.maven.surefire.util.ReflectionUtils; @@ -98,8 +99,8 @@ else if ( forkTestSet instanceof Class ) { final RunListener reporter = reporterFactory.createReporter(); ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter ); - final Map systemProperties = systemProps(); - final String smClassName = systemProperties.get( "surefire.security.manager" ); + Map systemProperties = systemProps(); + String smClassName = System.getProperty( "surefire.security.manager" ); if ( smClassName != null ) { SecurityManager securityManager = @@ -112,7 +113,6 @@ else if ( forkTestSet instanceof Class ) SurefireTestSet surefireTestSet = createTestSet( clazz ); executeTestSet( surefireTestSet, reporter, testClassLoader, systemProperties ); } - } finally { @@ -122,7 +122,6 @@ else if ( forkTestSet instanceof Class ) } private SurefireTestSet createTestSet( Class clazz ) - throws TestSetFailedException { return reflector.isJUnit3Available() && jUnit3TestChecker.accept( clazz ) ? new JUnitTestSet( clazz, reflector ) @@ -133,13 +132,19 @@ private void executeTestSet( SurefireTestSet testSet, RunListener reporter, Clas Map systemProperties ) throws TestSetFailedException { - SimpleReportEntry report = new SimpleReportEntry( getClass().getName(), testSet.getName(), systemProperties ); - - reporter.testSetStarting( report ); + String clazz = testSet.getName(); - testSet.execute( reporter, classLoader ); - - reporter.testSetCompleted( report ); + try + { + TestSetReportEntry started = new SimpleReportEntry( clazz, null, null, null ); + reporter.testSetStarting( started ); + testSet.execute( reporter, classLoader ); + } + finally + { + TestSetReportEntry completed = new SimpleReportEntry( clazz, null, null, null, systemProperties ); + reporter.testSetCompleted( completed ); + } } private TestsToRun scanClassPath() diff --git a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/PojoTestSet.java b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/PojoTestSet.java index 1b23322a5e..d0dab065c7 100644 --- a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/PojoTestSet.java +++ b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/PojoTestSet.java @@ -23,7 +23,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; -import java.util.List; +import java.util.Collection; import org.apache.maven.surefire.report.LegacyPojoStackTraceWriter; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.SimpleReportEntry; @@ -41,20 +41,21 @@ public class PojoTestSet { private static final String TEST_METHOD_PREFIX = "test"; - private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; + private static final String SETUP_METHOD_NAME = "setUp"; - private final Object testObject; + private static final String TEARDOWN_METHOD_NAME = "tearDown"; + + private static final Object[] EMPTY_OBJECT_ARRAY = {}; private final Class testClass; - private List testMethods; + private final Collection testMethods = new ArrayList<>(); private Method setUpMethod; private Method tearDownMethod; public PojoTestSet( final Class testClass ) - throws TestSetFailedException { if ( testClass == null ) { @@ -62,19 +63,11 @@ public PojoTestSet( final Class testClass ) } this.testClass = testClass; - - try - { - testObject = testClass.newInstance(); - } - catch ( ReflectiveOperationException e ) - { - throw new TestSetFailedException( "Unable to instantiate POJO '" + testClass + "'", e ); - } } @Override public void execute( RunListener reportManager, ClassLoader loader ) + throws TestSetFailedException { if ( reportManager == null ) { @@ -85,47 +78,59 @@ public void execute( RunListener reportManager, ClassLoader loader ) } private void executeTestMethods( RunListener reportManager ) + throws TestSetFailedException { if ( reportManager == null ) { throw new NullPointerException( "reportManager is null" ); } - if ( testMethods == null ) - { - discoverTestMethods(); - } + discoverTestMethods(); - boolean abort = false; - - for ( int i = 0; i < testMethods.size() && !abort; ++i ) + for ( Method testMethod : testMethods ) { - abort = executeTestMethod( testMethods.get( i ), EMPTY_OBJECT_ARRAY, reportManager ); + boolean abort = executeTestMethod( testMethod, reportManager ); + if ( abort ) + { + break; + } } } - private boolean executeTestMethod( Method method, Object[] args, RunListener reportManager ) + private boolean executeTestMethod( Method method, RunListener reportManager ) + throws TestSetFailedException { - if ( method == null || args == null || reportManager == null ) + if ( method == null || reportManager == null ) { throw new NullPointerException(); } + final Object testObject; + + try + { + testObject = testClass.newInstance(); + } + catch ( ReflectiveOperationException e ) + { + throw new TestSetFailedException( "Unable to instantiate POJO '" + testClass + "'.", e ); + } + final String testClassName = getTestClass().getName(); final String methodName = method.getName(); - final String userFriendlyMethodName = methodName + '(' + ( args.length == 0 ? "" : "Reporter" ) + ')'; + final String userFriendlyMethodName = methodName + "()"; final String testName = getTestName( userFriendlyMethodName ); - reportManager.testStarting( new SimpleReportEntry( testClassName, testName ) ); + reportManager.testStarting( new SimpleReportEntry( testClassName, null, testName, null ) ); try { - setUpFixture(); + setUpFixture( testObject ); } catch ( Throwable e ) { StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter( testClassName, methodName, e ); - reportManager.testFailed( withException( testClassName, testName, stackTraceWriter ) ); + reportManager.testFailed( withException( testClassName, null, testName, null, stackTraceWriter ) ); // A return value of true indicates to this class's executeTestMethods // method that it should abort and not attempt to execute @@ -138,34 +143,34 @@ private boolean executeTestMethod( Method method, Object[] args, RunListener rep // Make sure that tearDownFixture try { - method.invoke( testObject, args ); - reportManager.testSucceeded( new SimpleReportEntry( testClassName, testName ) ); + method.invoke( testObject, EMPTY_OBJECT_ARRAY ); + reportManager.testSucceeded( new SimpleReportEntry( testClassName, null, testName, null ) ); } catch ( InvocationTargetException e ) { Throwable t = e.getTargetException(); StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter( testClassName, methodName, t ); - reportManager.testFailed( withException( testClassName, testName, stackTraceWriter ) ); + reportManager.testFailed( withException( testClassName, null, testName, null, stackTraceWriter ) ); // Don't return here, because tearDownFixture should be called even // if the test method throws an exception. } catch ( Throwable t ) { StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter( testClassName, methodName, t ); - reportManager.testFailed( withException( testClassName, testName, stackTraceWriter ) ); + reportManager.testFailed( withException( testClassName, null, testName, null, stackTraceWriter ) ); // Don't return here, because tearDownFixture should be called even // if the test method throws an exception. } try { - tearDownFixture(); + tearDownFixture( testObject ); } catch ( Throwable t ) { StackTraceWriter stackTraceWriter = new LegacyPojoStackTraceWriter( testClassName, methodName, t ); // Treat any exception from tearDownFixture as a failure of the test. - reportManager.testFailed( withException( testClassName, testName, stackTraceWriter ) ); + reportManager.testFailed( withException( testClassName, null, testName, null, stackTraceWriter ) ); // A return value of true indicates to this class's executeTestMethods // method that it should abort and not attempt to execute @@ -193,7 +198,7 @@ private String getTestName( String testMethodName ) return getTestClass().getName() + "." + testMethodName; } - private void setUpFixture() + private void setUpFixture( Object testObject ) throws Throwable { if ( setUpMethod != null ) @@ -202,7 +207,7 @@ private void setUpFixture() } } - private void tearDownFixture() + private void tearDownFixture( Object testObject ) throws Throwable { if ( tearDownMethod != null ) @@ -213,35 +218,19 @@ private void tearDownFixture() private void discoverTestMethods() { - if ( testMethods == null ) + for ( Method m : getTestClass().getMethods() ) { - testMethods = new ArrayList<>(); - - Method[] methods = getTestClass().getMethods(); - - for ( Method m : methods ) + if ( isNoArgsInstanceMethod( m ) ) { if ( isValidTestMethod( m ) ) { - String simpleName = m.getName(); - - // name must have 5 or more chars - if ( simpleName.length() > 4 ) - { - String firstFour = simpleName.substring( 0, 4 ); - - // name must start with "test" - if ( firstFour.equals( TEST_METHOD_PREFIX ) ) - { - testMethods.add( m ); - } - } + testMethods.add( m ); } - else if ( m.getName().equals( "setUp" ) && m.getParameterTypes().length == 0 ) + else if ( SETUP_METHOD_NAME.equals( m.getName() ) ) { setUpMethod = m; } - else if ( m.getName().equals( "tearDown" ) && m.getParameterTypes().length == 0 ) + else if ( TEARDOWN_METHOD_NAME.equals( m.getName() ) ) { tearDownMethod = m; } @@ -249,17 +238,19 @@ else if ( m.getName().equals( "tearDown" ) && m.getParameterTypes().length == 0 } } - private static boolean isValidTestMethod( Method m ) + private static boolean isNoArgsInstanceMethod( Method m ) { boolean isInstanceMethod = !Modifier.isStatic( m.getModifiers() ); - boolean returnsVoid = m.getReturnType().equals( void.class ); - boolean hasNoParams = m.getParameterTypes().length == 0; - return isInstanceMethod && returnsVoid && hasNoParams; } + private static boolean isValidTestMethod( Method m ) + { + return m.getName().startsWith( TEST_METHOD_PREFIX ); + } + @Override public String getName() { diff --git a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java index 78e78ade26..db0563a875 100644 --- a/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java +++ b/surefire-providers/surefire-junit3/src/main/java/org/apache/maven/surefire/junit/TestListenerInvocationHandler.java @@ -20,14 +20,19 @@ */ import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; + import org.apache.maven.surefire.report.LegacyPojoStackTraceWriter; import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.SimpleReportEntry; +import org.apache.maven.surefire.report.StackTraceWriter; + +import static org.apache.maven.surefire.report.SimpleReportEntry.withException; +import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractClassName; +import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractMethodName; /** * Invocation Handler for TestListener proxies to delegate to our {@link RunListener} @@ -149,25 +154,24 @@ public Object invoke( Object proxy, Method method, Object[] args ) // Handler for TestListener.startTest(Test) private void handleStartTest( Object[] args ) { - ReportEntry report = new SimpleReportEntry( args[0].getClass().getName(), args[0].toString() ); + ReportEntry report = createStartEndReportEntry( args ); reporter.testStarting( report ); } // Handler for TestListener.addFailure(Test, Throwable) private void handleAddError( Object[] args ) - throws IllegalAccessException, InvocationTargetException + throws ReflectiveOperationException { - ReportEntry report = SimpleReportEntry.withException( args[0].getClass().getName(), args[0].toString(), - getStackTraceWriter( args ) ); + ReportEntry report = toReportEntryWithException( args ); reporter.testError( report ); failedTestsSet.add( new FailedTest( args[0], Thread.currentThread() ) ); } - private LegacyPojoStackTraceWriter getStackTraceWriter( Object[] args ) - throws IllegalAccessException, InvocationTargetException + private static LegacyPojoStackTraceWriter toStackTraceWriter( Object[] args ) + throws ReflectiveOperationException { String testName; @@ -185,10 +189,9 @@ private LegacyPojoStackTraceWriter getStackTraceWriter( Object[] args ) } private void handleAddFailure( Object[] args ) - throws IllegalAccessException, InvocationTargetException + throws ReflectiveOperationException { - ReportEntry report = SimpleReportEntry.withException( args[0].getClass().getName(), args[0].toString(), - getStackTraceWriter( args ) ); + ReportEntry report = toReportEntryWithException( args ); reporter.testFailed( report ); @@ -201,9 +204,25 @@ private void handleEndTest( Object[] args ) if ( !testHadFailed ) { - ReportEntry report = new SimpleReportEntry( args[0].getClass().getName(), args[0].toString() ); + ReportEntry report = createStartEndReportEntry( args ); reporter.testSucceeded( report ); } } + + private static ReportEntry toReportEntryWithException( Object[] args ) + throws ReflectiveOperationException + { + String description = args[0].toString(); + String className = extractClassName( description ); + String methodName = extractMethodName( description ); + StackTraceWriter stackTraceWriter = toStackTraceWriter( args ); + return withException( className, null, methodName, null, stackTraceWriter ); + } + + private static SimpleReportEntry createStartEndReportEntry( Object[] args ) + { + String description = args[0].toString(); + return new SimpleReportEntry( extractClassName( description ), null, extractMethodName( description ), null ); + } } diff --git a/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java b/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java index 977ac9ee4c..f8d4ba78e8 100644 --- a/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java +++ b/surefire-providers/surefire-junit3/src/test/java/org/apache/maven/surefire/junit/JUnitTestSetTest.java @@ -25,11 +25,15 @@ import org.apache.maven.surefire.common.junit3.JUnit3Reflector; import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.RunListener; +import org.apache.maven.surefire.report.RunMode; import org.apache.maven.surefire.report.TestSetReportEntry; import java.util.ArrayList; import java.util.List; +/** + * + */ public class JUnitTestSetTest extends TestCase { @@ -42,12 +46,17 @@ public void testExecuteSuiteClass() JUnitTestSet testSet = new JUnitTestSet( Suite.class, reflector ); SuccessListener listener = new SuccessListener(); testSet.execute( listener, testClassLoader ); - List succeededTests = listener.getSucceededTests(); + List succeededTests = listener.getSucceededTests(); assertEquals( 1, succeededTests.size() ); - assertEquals( "testSuccess(org.apache.maven.surefire.junit.JUnitTestSetTest$AlwaysSucceeds)", - ( (ReportEntry) succeededTests.get( 0 ) ).getName() ); + assertEquals( "org.apache.maven.surefire.junit.JUnitTestSetTest$AlwaysSucceeds", + succeededTests.get( 0 ).getSourceName() ); + assertEquals( "testSuccess", + succeededTests.get( 0 ).getName() ); } + /** + * + */ public static final class AlwaysSucceeds extends TestCase { @@ -57,6 +66,9 @@ public void testSuccess() } } + /** + * + */ public static class SuccessListener implements RunListener { @@ -81,7 +93,7 @@ public void testStarting( ReportEntry report ) @Override public void testSucceeded( ReportEntry report ) { - this.succeededTests.add( report ); + succeededTests.add( report ); } @Override @@ -113,18 +125,26 @@ public void testExecutionSkippedByUser() { } + public RunMode markAs( RunMode currentRunMode ) + { + return RunMode.NORMAL_RUN; + } + public void testSkippedByUser( ReportEntry report ) { testSkipped( report ); } - public List getSucceededTests() + List getSucceededTests() { return succeededTests; } } + /** + * + */ public static class Suite { diff --git a/surefire-providers/surefire-junit4/pom.xml b/surefire-providers/surefire-junit4/pom.xml index 514a8e259a..fc242cfd57 100644 --- a/surefire-providers/surefire-junit4/pom.xml +++ b/surefire-providers/surefire-junit4/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 surefire-junit4 @@ -44,4 +44,40 @@ ${project.version} + + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + + **/JUnit4SuiteTest.java + + + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + + + + diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java index c31a01998f..b9649331ae 100644 --- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java +++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java @@ -231,7 +231,7 @@ public void update( Command command ) private void executeTestSet( Class clazz, RunListener reporter, Notifier notifier ) { - final SimpleReportEntry report = new SimpleReportEntry( getClass().getName(), clazz.getName(), systemProps() ); + final SimpleReportEntry report = new SimpleReportEntry( clazz.getName(), null, null, null, systemProps() ); reporter.testSetStarting( report ); try { @@ -250,7 +250,7 @@ private void executeTestSet( Class clazz, RunListener reporter, Notifier noti String reportName = report.getName(); String reportSourceName = report.getSourceName(); PojoStackTraceWriter stackWriter = new PojoStackTraceWriter( reportSourceName, reportName, e ); - reporter.testError( withException( reportSourceName, reportName, stackWriter ) ); + reporter.testError( withException( reportSourceName, null, reportName, null, stackWriter ) ); } } finally diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/TestResolverFilter.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/TestResolverFilter.java index 4205b1475f..72669a8ebf 100644 --- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/TestResolverFilter.java +++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/TestResolverFilter.java @@ -1 +1 @@ -package org.apache.maven.surefire.junit4; /* * 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.common.junit4.ClassMethod; import org.apache.maven.surefire.testset.TestListResolver; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.cutTestClassAndMethod; import static org.apache.maven.surefire.testset.TestListResolver.toClassFileName; /** * Method filter used in {@link JUnit4Provider}. */ final class TestResolverFilter extends Filter { private final TestListResolver methodFilter; TestResolverFilter( TestListResolver methodFilter ) { this.methodFilter = methodFilter; } @Override public boolean shouldRun( Description description ) { // class: Java class name; method: 1. "testMethod" or 2. "testMethod[5+whatever]" in @Parameterized final ClassMethod cm = cutTestClassAndMethod( description ); final boolean isSuite = description.isSuite(); final boolean isValidTest = description.isTest() && cm.isValid(); final String clazz = cm.getClazz(); final String method = cm.getMethod(); return isSuite || isValidTest && methodFilter.shouldRun( toClassFileName( clazz ), method ); } @Override public String describe() { return methodFilter.toString(); } } \ No newline at end of file +package org.apache.maven.surefire.junit4; /* * 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.util.internal.ClassMethod; import org.apache.maven.surefire.testset.TestListResolver; import org.junit.runner.Description; import org.junit.runner.manipulation.Filter; import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.toClassMethod; import static org.apache.maven.surefire.testset.TestListResolver.toClassFileName; /** * Method filter used in {@link JUnit4Provider}. */ final class TestResolverFilter extends Filter { private final TestListResolver methodFilter; TestResolverFilter( TestListResolver methodFilter ) { this.methodFilter = methodFilter; } @Override public boolean shouldRun( Description description ) { // class: Java class name; method: 1. "testMethod" or 2. "testMethod[5+whatever]" in @Parameterized final ClassMethod cm = toClassMethod( description ); final boolean isSuite = description.isSuite(); final boolean isValidTest = description.isTest() && cm.isValidTest(); final String clazz = cm.getClazz(); final String method = cm.getMethod(); return isSuite || isValidTest && methodFilter.shouldRun( toClassFileName( clazz ), method ); } @Override public String describe() { return methodFilter.toString(); } } \ No newline at end of file diff --git a/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java b/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java index bf6cafc3a6..b949baa27d 100644 --- a/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java +++ b/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4ProviderTest.java @@ -19,24 +19,30 @@ * under the License. */ -import junit.framework.TestCase; import org.apache.maven.surefire.booter.BaseProviderFactory; import org.apache.maven.surefire.testset.TestRequest; +import org.junit.Test; import org.junit.runner.Description; import java.util.HashMap; import static java.util.Arrays.asList; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.isEmptyOrNullString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertNotNull; import static org.junit.runner.Description.createSuiteDescription; /** * @author Kristian Rosenvold */ public class JUnit4ProviderTest - extends TestCase { + @Test public void testCreateProvider() { assertNotNull( getJUnit4Provider() ); @@ -51,12 +57,15 @@ private JUnit4Provider getJUnit4Provider() return new JUnit4Provider( providerParameters ); } + @Test public void testShouldCreateDescription() { - class A { + class A + { } - class B { + class B + { } Description d = JUnit4Provider.createTestsDescription( asList( A.class, B.class ) ); @@ -68,5 +77,4 @@ class B { Description b = createSuiteDescription( B.class ); assertThat( d.getChildren(), contains( a, b ) ); } - } diff --git a/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4SuiteTest.java b/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4SuiteTest.java new file mode 100644 index 0000000000..2d4fb72882 --- /dev/null +++ b/surefire-providers/surefire-junit4/src/test/java/org/apache/maven/surefire/junit4/JUnit4SuiteTest.java @@ -0,0 +1,35 @@ +package org.apache.maven.surefire.junit4; + +/* + * 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 junit.framework.JUnit4TestAdapter; +import junit.framework.Test; +import junit.framework.TestCase; + +/** + * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite. + */ +public class JUnit4SuiteTest extends TestCase +{ + public static Test suite() + { + return new JUnit4TestAdapter( JUnit4ProviderTest.class ); + } +} diff --git a/surefire-providers/surefire-junit47/pom.xml b/surefire-providers/surefire-junit47/pom.xml index a691633747..14475a0f1b 100644 --- a/surefire-providers/surefire-junit47/pom.xml +++ b/surefire-providers/surefire-junit47/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 surefire-junit47 @@ -58,6 +58,21 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-dependency-plugin @@ -155,11 +170,19 @@ maven-surefire-plugin + ${jvm.args.tests} ${jacoco.agent} true **/JUnit47SuiteTest.java + + + org.apache.maven.surefire + surefire-shadefire + 3.0.0-M3 + + diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java index be02d4ea4c..244b83f269 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/ConcurrentRunListener.java @@ -25,6 +25,7 @@ import org.apache.maven.surefire.report.ReportEntry; import org.apache.maven.surefire.report.ReporterFactory; import org.apache.maven.surefire.report.RunListener; +import org.apache.maven.surefire.report.RunMode; import org.apache.maven.surefire.report.StackTraceWriter; import org.apache.maven.surefire.report.TestSetReportEntry; import org.apache.maven.surefire.testset.TestSetFailedException; @@ -131,6 +132,11 @@ public void testExecutionSkippedByUser() getRunListener().testExecutionSkippedByUser(); } + public RunMode markAs( RunMode currentRunMode ) + { + return reporterManagerThreadLocal.get().markAs( currentRunMode ); + } + @Override public void testAssumptionFailure( ReportEntry failure ) { @@ -213,18 +219,18 @@ public static ConcurrentRunListener createInstance( Map classMe @Override - public void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) + public void writeTestOutput( String output, boolean newLine, boolean stdout ) { TestMethod threadTestMethod = getThreadTestMethod(); if ( threadTestMethod != null ) { LogicalStream logicalStream = threadTestMethod.getLogicalStream(); - logicalStream.write( stdout, buf, off, len ); + logicalStream.write( stdout, output, newLine ); } else { // Not able to associate output with any thread. Just dump to console - consoleStream.println( buf, off, len ); + consoleStream.println( output ); } } } diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java index ae00fdbbaa..03e314ee37 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListener.java @@ -20,7 +20,7 @@ */ import org.apache.maven.surefire.common.junit4.JUnit4RunListener; -import org.apache.maven.surefire.common.junit48.JUnit46StackTraceWriter; +import org.apache.maven.surefire.common.junit4.JUnit4StackTraceWriter; import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.StackTraceWriter; import org.junit.runner.Description; @@ -29,6 +29,8 @@ import java.util.Map; +import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractClassName; + /** * Noteworthy things about JUnit4 listening: *
@@ -95,7 +97,7 @@ private boolean asTestLeaf( Description description ) { if ( description.isTest() ) { - final String testClassName = extractDescriptionClassName( description ); + final String testClassName = extractClassName( description.getDisplayName() ); if ( testClassName != null ) { final TestSet testSet; @@ -121,18 +123,6 @@ private boolean asTestLeaf( Description description ) @Override protected StackTraceWriter createStackTraceWriter( Failure failure ) { - return new JUnit46StackTraceWriter( failure ); - } - - @Override - protected String extractDescriptionClassName( Description description ) - { - return description.getClassName(); - } - - @Override - protected String extractDescriptionMethodName( Description description ) - { - return description.getMethodName(); + return new JUnit4StackTraceWriter( failure ); } } diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/LogicalStream.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/LogicalStream.java index 068674f1f3..c75c063749 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/LogicalStream.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/LogicalStream.java @@ -21,60 +21,40 @@ import org.apache.maven.surefire.report.ConsoleOutputReceiver; -import java.util.Arrays; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; /** * A stream-like object that preserves ordering between stdout/stderr */ -public final class LogicalStream +final class LogicalStream { private final Queue output = new ConcurrentLinkedQueue<>(); private static final class Entry { private final boolean stdout; + private final String text; + private final boolean newLine; - private final byte[] b; - - private final int off; - - private final int len; - - private Entry( boolean stdout, byte[] b, int off, int len ) + Entry( boolean stdout, String text, boolean newLine ) { this.stdout = stdout; - this.b = Arrays.copyOfRange( b, off, off + len ); - this.off = 0; - this.len = len; - } - - private void writeDetails( ConsoleOutputReceiver outputReceiver ) - { - outputReceiver.writeTestOutput( b, off, len, stdout ); + this.text = text; + this.newLine = newLine; } } - public void write( boolean stdout, byte b[], int off, int len ) + synchronized void write( boolean stdout, String text, boolean newLine ) { - if ( !isBlankLine( b, len ) ) - { - Entry entry = new Entry( stdout, b, off, len ); - output.add( entry ); - } + output.add( new Entry( stdout, text, newLine ) ); } - public void writeDetails( ConsoleOutputReceiver outputReceiver ) + void writeDetails( ConsoleOutputReceiver outputReceiver ) { for ( Entry entry = output.poll(); entry != null; entry = output.poll() ) { - entry.writeDetails( outputReceiver ); + outputReceiver.writeTestOutput( entry.text, entry.newLine, entry.stdout ); } } - - private static boolean isBlankLine( byte[] b, int len ) - { - return b == null || len == 0; - } } diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java index f8d2fb7246..135ba4e525 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/NonConcurrentRunListener.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.surefire.util.internal.ClassMethod; import org.apache.maven.surefire.common.junit4.JUnit4RunListener; import org.apache.maven.surefire.report.ConsoleOutputReceiver; import org.apache.maven.surefire.report.RunListener; @@ -32,6 +33,7 @@ import java.util.Collections; import java.util.Map; +import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.toClassMethod; import static org.apache.maven.surefire.util.internal.ObjectUtils.systemProps; /** @@ -53,23 +55,23 @@ public NonConcurrentRunListener( RunListener reporter ) super( reporter ); } - @Override - public void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) + public synchronized void writeTestOutput( String output, boolean newLine, boolean stdout ) { // We can write immediately: no parallelism and a single class. - ( (ConsoleOutputReceiver) reporter ).writeTestOutput( buf, off, len, stdout ); + ( (ConsoleOutputReceiver) reporter ).writeTestOutput( output, newLine, stdout ); } @Override protected SimpleReportEntry createReportEntry( Description description ) { - return new SimpleReportEntry( extractDescriptionClassName( description ), description.getDisplayName() ); + ClassMethod classMethod = toClassMethod( description ); + return new SimpleReportEntry( classMethod.getClazz(), null, classMethod.getMethod(), null ); } private TestSetReportEntry createReportEntryForTestSet( Description description, Map systemProps ) { - String testClassName = extractDescriptionClassName( description ); - return new SimpleReportEntry( testClassName, testClassName, systemProps ); + ClassMethod classMethod = toClassMethod( description ); + return new SimpleReportEntry( classMethod.getClazz(), null, null, null, systemProps ); } private TestSetReportEntry createTestSetReportEntryStarted( Description description ) @@ -82,18 +84,6 @@ private TestSetReportEntry createTestSetReportEntryFinished( Description descrip return createReportEntryForTestSet( description, systemProps() ); } - @Override - protected String extractDescriptionClassName( Description description ) - { - return description.getClassName(); - } - - @Override - protected String extractDescriptionMethodName( Description description ) - { - return description.getMethodName(); - } - @Override public void testStarted( Description description ) throws Exception diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestMethod.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestMethod.java index ae89fbfc02..846bf99899 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestMethod.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestMethod.java @@ -185,12 +185,12 @@ LogicalStream getLogicalStream() } @Override - public void writeTestOutput( byte[] buf, int off, int len, boolean stdout ) + public void writeTestOutput( String output, boolean newLine, boolean stdout ) { - getLogicalStream().write( stdout, buf, off, len ); + getLogicalStream().write( stdout, output, newLine ); } - public TestSet getTestSet() + TestSet getTestSet() { return testSet; } diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java index e710cda2d6..0ffcbe30a7 100644 --- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java +++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/TestSet.java @@ -120,7 +120,7 @@ private TestSetReportEntry createReportEntryCompleted( int elapsed ) private TestSetReportEntry createReportEntry( Integer elapsed, Map systemProps ) { - return new SimpleReportEntry( testClassName, testClassName, null, elapsed, systemProps ); + return new SimpleReportEntry( testClassName, null, testClassName, null, null, elapsed, systemProps ); } public void incrementTestMethodCount() diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java index a4f6e52910..5813ad9947 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConcurrentRunListenerTest.java @@ -39,7 +39,7 @@ import org.junit.runner.Computer; import org.junit.runner.JUnitCore; -/* +/** * @author Kristian Rosenvold */ public class ConcurrentRunListenerTest @@ -206,6 +206,9 @@ private org.junit.runner.notification.RunListener createRunListener( ReporterFac } + /** + * + */ public static class DummyWithOneIgnore { @Test @@ -225,6 +228,9 @@ public void testStub2() } } + /** + * + */ public static class DummyWithFailure { @Test @@ -244,6 +250,9 @@ public void testAfterFail() } } + /** + * + */ public static class DummyAllOk { @@ -263,6 +272,9 @@ public void testStub2A() } } + /** + * + */ public static class Dummy3 { @@ -281,6 +293,9 @@ public void testStub2A() } } + /** + * + */ public static class Junit3Tc1 extends TestCase { @@ -304,6 +319,9 @@ public static junit.framework.Test suite() } } + /** + * + */ public static class Junit3Tc2 extends TestCase { @@ -331,6 +349,9 @@ public static junit.framework.Test suite() } } + /** + * + */ public static class Junit3OddTest1 extends TestCase { @@ -355,6 +376,9 @@ public void testMe() } } + /** + * + */ public static class Junit3WithNestedSuite extends TestCase { diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConfigurableParallelComputerTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConfigurableParallelComputerTest.java index ca50956a36..6942010100 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConfigurableParallelComputerTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/ConfigurableParallelComputerTest.java @@ -199,13 +199,13 @@ private long runIt( Class[] realClasses, JUnitCore jUnitCore, Computer comput return System.currentTimeMillis() - start; } - private long timedRun( int NUMTESTS, Result result, Class[] realClasses, JUnitCore jUnitCore, Computer computer ) + private long timedRun( int numTests, Result result, Class[] realClasses, JUnitCore jUnitCore, Computer computer ) throws ExecutionException { long time = runIt( realClasses, jUnitCore, computer ); assertEquals( "No tests should fail, right ?", 0, result.getFailures().size() ); assertEquals( "All tests should succeed, right ?", 0, result.getIgnoreCount() ); - assertEquals( "All tests should succeed, right ?", NUMTESTS * 3, result.getRunCount() ); + assertEquals( "All tests should succeed, right ?", numTests * 3, result.getRunCount() ); return time; } @@ -241,6 +241,9 @@ static void sleepReallyEvenOnWindows( long ms ) } } + /** + * + */ public static class Dummy { @Test @@ -261,6 +264,9 @@ public void testStub2() } } + /** + * + */ public static class Dummy2 { @Test @@ -276,6 +282,9 @@ public void testDummy2() } } + /** + * + */ public static class SlowTest { final int scaling = 100; @@ -302,6 +311,9 @@ public void testNotMuch3() } } + /** + * + */ public static class FailingAssertions { @Test @@ -321,6 +333,9 @@ public void testWithFail() } } + /** + * + */ public static class Failure { @Test diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/DiagnosticRunListener.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/DiagnosticRunListener.java index 0dfb1a3b94..dbc082e8fe 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/DiagnosticRunListener.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/DiagnosticRunListener.java @@ -1,19 +1,41 @@ package org.apache.maven.surefire.junitcore; /* - * Copyright 2002-2009 the original author or authors. + * 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 * - * Licensed 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 * - * 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. + */ + +/* + * 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 * - * 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. + * 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. * * Also licensed under CPL http://junit.sourceforge.net/cpl-v10.html */ @@ -25,7 +47,7 @@ import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunListener; -/* +/** * @author Kristian Rosenvold, kristianAzeniorD0Tno */ public class DiagnosticRunListener diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit47SuiteTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit47SuiteTest.java index 99546273d0..02534eed7c 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit47SuiteTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit47SuiteTest.java @@ -21,12 +21,12 @@ import junit.framework.JUnit4TestAdapter; import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; import org.apache.maven.surefire.junitcore.pc.OptimizedParallelComputerTest; import org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilderTest; import org.apache.maven.surefire.junitcore.pc.ParallelComputerUtilTest; import org.apache.maven.surefire.junitcore.pc.SchedulingStrategiesTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; /** * Adapt the JUnit47 tests which use only annotations to the JUnit3 test suite. @@ -34,27 +34,25 @@ * @author Tibor Digana (tibor17) * @since 2.16 */ -@Suite.SuiteClasses( { - Surefire746Test.class, - Surefire813IncorrectResultTest.class, - ParallelComputerUtilTest.class, - ParallelComputerBuilderTest.class, - SchedulingStrategiesTest.class, - OptimizedParallelComputerTest.class, - ConcurrentRunListenerTest.class, - ConfigurableParallelComputerTest.class, - JUnit4Reflector481Test.class, - JUnitCoreParametersTest.class, - JUnitCoreRunListenerTest.class, - MavenSurefireJUnit47RunnerTest.class, - MavenSurefireJUnit48RunnerTest.class, - TestMethodTest.class -} ) -@RunWith( Suite.class ) -public class JUnit47SuiteTest +public class JUnit47SuiteTest extends TestCase { public static Test suite() { - return new JUnit4TestAdapter( JUnit47SuiteTest.class ); + TestSuite suite = new TestSuite(); + suite.addTestSuite( ConcurrentRunListenerTest.class ); + suite.addTestSuite( ConfigurableParallelComputerTest.class ); + suite.addTestSuite( JUnitCoreRunListenerTest.class ); + suite.addTestSuite( MavenSurefireJUnit47RunnerTest.class ); + suite.addTestSuite( MavenSurefireJUnit48RunnerTest.class ); + suite.addTestSuite( TestMethodTest.class ); + suite.addTest( new JUnit4TestAdapter( Surefire746Test.class ) ); + suite.addTest( new JUnit4TestAdapter( Surefire813IncorrectResultTest.class ) ); + suite.addTest( new JUnit4TestAdapter( ParallelComputerUtilTest.class ) ); + suite.addTest( new JUnit4TestAdapter( ParallelComputerBuilderTest.class ) ); + suite.addTest( new JUnit4TestAdapter( SchedulingStrategiesTest.class ) ); + suite.addTest( new JUnit4TestAdapter( OptimizedParallelComputerTest.class ) ); + suite.addTest( new JUnit4TestAdapter( JUnit4Reflector481Test.class ) ); + suite.addTest( new JUnit4TestAdapter( JUnitCoreParametersTest.class ) ); + return suite; } } diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java index 896af3efc0..abf74befa4 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnit4Reflector481Test.java @@ -21,6 +21,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; + import org.apache.maven.surefire.common.junit4.JUnit4Reflector; import org.apache.maven.surefire.util.ReflectionUtils; @@ -28,7 +29,10 @@ import org.junit.Test; import org.junit.runner.Description; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; /** * Reflector Test with junit 4.8.1 @@ -42,33 +46,33 @@ public class JUnit4Reflector481Test @Test public void testGetAnnotatedIgnore() { - final Method testSomething2 = - ReflectionUtils.getMethod( IgnoreWithDescription.class, "testSomething2", EMPTY_CLASS_ARRAY ); + final Method testSomething2 = ReflectionUtils.getMethod( IgnoreWithDescription.class, "testSomething2", + EMPTY_CLASS_ARRAY ); final Annotation[] annotations = testSomething2.getAnnotations(); - Description desc = - Description.createTestDescription( IgnoreWithDescription.class, "testSomething2", annotations ); + Description desc = Description.createTestDescription( IgnoreWithDescription.class, "testSomething2", + annotations ); Ignore annotatedIgnore = JUnit4Reflector.getAnnotatedIgnore( desc ); assertNotNull( annotatedIgnore ); assertEquals( - "testSomething2" + "(org.apache.maven.surefire.junitcore.JUnit4Reflector481Test$IgnoreWithDescription)", - desc.getDisplayName() ); - assertEquals( "testSomething2" - + "(org.apache.maven.surefire.junitcore.JUnit4Reflector481Test$IgnoreWithDescription)", - desc.toString() ); + "testSomething2" + "(org.apache.maven.surefire.junitcore.JUnit4Reflector481Test$IgnoreWithDescription)", + desc.getDisplayName() ); + assertEquals( + "testSomething2" + "(org.apache.maven.surefire.junitcore.JUnit4Reflector481Test$IgnoreWithDescription)", + desc.toString() ); assertEquals( "org.apache.maven.surefire.junitcore.JUnit4Reflector481Test$IgnoreWithDescription", - desc.getClassName() ); + desc.getClassName() ); assertEquals( "testSomething2", desc.getMethodName() ); assertEquals( 0, desc.getChildren().size() ); assertEquals( 2, desc.getAnnotations().size() ); assertSame( annotatedIgnore, desc.getAnnotation( Ignore.class ) ); - assertEquals( reason, annotatedIgnore.value() ); + assertEquals( REASON, annotatedIgnore.value() ); } @Test public void testGetAnnotatedIgnoreWithoutClass() { - final Method testSomething2 = - ReflectionUtils.getMethod( IgnoreWithDescription.class, "testSomething2", EMPTY_CLASS_ARRAY ); + final Method testSomething2 = ReflectionUtils.getMethod( IgnoreWithDescription.class, "testSomething2", + EMPTY_CLASS_ARRAY ); final Annotation[] annotations = testSomething2.getAnnotations(); Description desc = Description.createSuiteDescription( "testSomething2", annotations ); Ignore annotatedIgnore = JUnit4Reflector.getAnnotatedIgnore( desc ); @@ -80,16 +84,19 @@ public void testGetAnnotatedIgnoreWithoutClass() assertEquals( 0, desc.getChildren().size() ); assertEquals( 2, desc.getAnnotations().size() ); assertSame( annotatedIgnore, desc.getAnnotation( Ignore.class ) ); - assertEquals( reason, annotatedIgnore.value() ); + assertEquals( REASON, annotatedIgnore.value() ); } - private static final String reason = "Ignorance is bliss"; + private static final String REASON = "Ignorance is bliss"; + /** + * + */ public static class IgnoreWithDescription { @Test - @Ignore( reason ) + @Ignore( REASON ) public void testSomething2() { } diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java index 3734afe64a..0ca33b98f6 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreParametersTest.java @@ -24,12 +24,15 @@ import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.hamcrest.core.Is.is; -/* +/** * @author Kristian Rosenvold, kristian.rosenvold@gmail com */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class JUnitCoreParametersTest { @Test @@ -134,38 +137,38 @@ private Map newDefaultProperties() private Map newPropertiesClasses() { Map props = new HashMap<>(); - props.put(JUnitCoreParameters.PARALLEL_KEY, "classes"); - props.put(JUnitCoreParameters.PERCORETHREADCOUNT_KEY, "false"); - props.put(JUnitCoreParameters.THREADCOUNT_KEY, "2"); - props.put(JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY, "false"); + props.put( JUnitCoreParameters.PARALLEL_KEY, "classes" ); + props.put( JUnitCoreParameters.PERCORETHREADCOUNT_KEY, "false" ); + props.put( JUnitCoreParameters.THREADCOUNT_KEY, "2" ); + props.put( JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY, "false" ); return props; } private Map newPropertiesMethods() { Map props = new HashMap<>(); - props.put(JUnitCoreParameters.PARALLEL_KEY, "methods"); - props.put(JUnitCoreParameters.PERCORETHREADCOUNT_KEY, "false"); - props.put(JUnitCoreParameters.THREADCOUNT_KEY, "2"); - props.put(JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY, "true"); + props.put( JUnitCoreParameters.PARALLEL_KEY, "methods" ); + props.put( JUnitCoreParameters.PERCORETHREADCOUNT_KEY, "false" ); + props.put( JUnitCoreParameters.THREADCOUNT_KEY, "2" ); + props.put( JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY, "true" ); return props; } private Map newPropertiesBoth() { Map props = new HashMap<>(); - props.put(JUnitCoreParameters.PARALLEL_KEY, "both"); - props.put(JUnitCoreParameters.PERCORETHREADCOUNT_KEY, "true"); - props.put(JUnitCoreParameters.THREADCOUNT_KEY, "7"); - props.put(JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY, "false"); + props.put( JUnitCoreParameters.PARALLEL_KEY, "both" ); + props.put( JUnitCoreParameters.PERCORETHREADCOUNT_KEY, "true" ); + props.put( JUnitCoreParameters.THREADCOUNT_KEY, "7" ); + props.put( JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY, "false" ); return props; } private Map newPropertiesTimeouts( double timeout, double forcedTimeout ) { Map props = new HashMap<>(); - props.put(JUnitCoreParameters.PARALLEL_TIMEOUT_KEY, Double.toString(timeout)); - props.put(JUnitCoreParameters.PARALLEL_TIMEOUTFORCED_KEY, Double.toString(forcedTimeout)); + props.put( JUnitCoreParameters.PARALLEL_TIMEOUT_KEY, Double.toString( timeout ) ); + props.put( JUnitCoreParameters.PARALLEL_TIMEOUTFORCED_KEY, Double.toString( forcedTimeout ) ); return props; } diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListenerTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListenerTest.java index b467f639c4..1c38794c22 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListenerTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreRunListenerTest.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; + import org.apache.maven.surefire.junit4.MockReporter; import junit.framework.TestCase; @@ -34,19 +35,20 @@ import org.junit.runner.notification.RunListener; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.empty; /** * @author Kristian Rosenvold */ -public class JUnitCoreRunListenerTest - extends TestCase +public class JUnitCoreRunListenerTest extends TestCase { public void testTestRunStarted() - throws Exception { - RunListener jUnit4TestSetReporter = - new JUnitCoreRunListener( new MockReporter(), new HashMap() ); + RunListener jUnit4TestSetReporter = new JUnitCoreRunListener( new MockReporter(), + new HashMap() ); JUnitCore core = new JUnitCore(); core.addListener( jUnit4TestSetReporter ); Result result = core.run( new Computer(), STest1.class, STest2.class ); @@ -55,10 +57,9 @@ public void testTestRunStarted() } public void testFailedAssumption() - throws Exception { - RunListener jUnit4TestSetReporter = - new JUnitCoreRunListener( new MockReporter(), new HashMap() ); + RunListener jUnit4TestSetReporter = new JUnitCoreRunListener( new MockReporter(), + new HashMap() ); JUnitCore core = new JUnitCore(); core.addListener( jUnit4TestSetReporter ); Result result = core.run( new Computer(), TestWithAssumptionFailure.class ); @@ -66,16 +67,15 @@ public void testFailedAssumption() assertEquals( 1, result.getRunCount() ); } - public void testStateForClassesWithNoChildren() - throws Exception + public void testStateForClassesWithNoChildren() throws Exception { - Description testDescription = - Description.createSuiteDescription( "testMethod(cannot.be.loaded.by.junit.Test)" ); - Description st1 = Description.createSuiteDescription( STest1.class); -// st1.addChild( Description.createSuiteDescription( STest1.class ) ); + Description testDescription = Description.createSuiteDescription( + "testMethod(cannot.be.loaded.by.junit.Test)" ); + Description st1 = Description.createSuiteDescription( STest1.class ); + // st1.addChild( Description.createSuiteDescription( STest1.class ) ); testDescription.addChild( st1 ); - Description st2 = Description.createSuiteDescription( STest2.class); - // st2.addChild( Description.createSuiteDescription( STest2.class ) ); + Description st2 = Description.createSuiteDescription( STest2.class ); + // st2.addChild( Description.createSuiteDescription( STest2.class ) ); testDescription.addChild( st2 ); Map classMethodCounts = new HashMap<>(); @@ -83,15 +83,14 @@ public void testStateForClassesWithNoChildren() listener.testRunStarted( testDescription ); assertEquals( 2, classMethodCounts.size() ); Iterator iterator = classMethodCounts.values().iterator(); - assertFalse(iterator.next().equals( iterator.next() )); + assertFalse( iterator.next().equals( iterator.next() ) ); } - public void testTestClassNotLoadableFromJUnitClassLoader() - throws Exception + public void testTestClassNotLoadableFromJUnitClassLoader() throws Exception { // can't use Description.createTestDescription() methods as these require a loaded Class - Description testDescription = - Description.createSuiteDescription( "testMethod(cannot.be.loaded.by.junit.Test)" ); + Description testDescription = Description.createSuiteDescription( + "testMethod(cannot.be.loaded.by.junit.Test)" ); assertEquals( "testMethod", testDescription.getMethodName() ); assertEquals( "cannot.be.loaded.by.junit.Test", testDescription.getClassName() ); // assert that the test class is not visible by the JUnit classloader @@ -142,6 +141,9 @@ public void testEmptySuiteTestRunStarted() throws Exception assertThat( classMethodCounts.keySet(), empty() ); } + /** + * + */ public static class STest1 { @Test @@ -150,6 +152,9 @@ public void testSomething() } } + /** + * + */ public static class STest2 { @Test @@ -158,6 +163,9 @@ public void testSomething2() } } + /** + * + */ public static class TestWithAssumptionFailure { @Test diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java index 915b64ad7d..583792f616 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/JUnitCoreTester.java @@ -20,6 +20,9 @@ */ import org.apache.maven.plugin.surefire.StartupReportConfiguration; +import org.apache.maven.plugin.surefire.extensions.SurefireConsoleOutputReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessReporter; +import org.apache.maven.plugin.surefire.extensions.SurefireStatelessTestsetInfoReporter; import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger; import org.apache.maven.plugin.surefire.report.DefaultReporterFactory; import org.apache.maven.surefire.report.ConsoleOutputReceiver; @@ -104,7 +107,8 @@ private static StartupReportConfiguration defaultStartupReportConfiguration() { File target = new File( "./target" ); File statisticsFile = new File( target, "TESTHASHxXML" ); - return new StartupReportConfiguration( true, true, "PLAIN", false, true, target, false, null, statisticsFile, - false, 0, null, null, false ); + return new StartupReportConfiguration( true, true, "PLAIN", false, target, false, null, statisticsFile, + false, 0, null, null, false, new SurefireStatelessReporter(), new SurefireConsoleOutputReporter(), + new SurefireStatelessTestsetInfoReporter() ); } } diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTest.java index 3e139e1fc2..14dab812d1 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit47RunnerTest.java @@ -1,3 +1,24 @@ +package org.apache.maven.surefire.junitcore; + +/* + * 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. + */ + /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat Middleware LLC, and individual contributors @@ -14,7 +35,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.maven.surefire.junitcore; import junit.framework.Assert; import junit.framework.TestCase; diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit48RunnerTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit48RunnerTest.java index 1faa78246f..c9cc407bbe 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit48RunnerTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/MavenSurefireJUnit48RunnerTest.java @@ -1,3 +1,24 @@ +package org.apache.maven.surefire.junitcore; + +/* + * 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. + */ + /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat Middleware LLC, and individual contributors @@ -14,7 +35,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.maven.surefire.junitcore; import junit.framework.Assert; import junit.framework.TestCase; diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java index aded93f191..8859c195fb 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire746Test.java @@ -1,5 +1,24 @@ package org.apache.maven.surefire.junitcore; +/* + * 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. + */ + /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat Middleware LLC, and individual contributors @@ -18,7 +37,11 @@ */ import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.maven.surefire.booter.BaseProviderFactory; @@ -83,8 +106,8 @@ public class Surefire746Test public final ExpectedException exception = ExpectedException.none(); @Test - public void surefireIsConfused_ByMultipleIgnore_OnClassLevel() - throws Exception + @SuppressWarnings( "checkstyle:methodname" ) + public void surefireIsConfused_ByMultipleIgnore_OnClassLevel() throws Exception { ReporterFactory reporterFactory = JUnitCoreTester.defaultNoXml(); BaseProviderFactory providerParameters = new BaseProviderFactory( reporterFactory, true ); @@ -97,16 +120,14 @@ public void surefireIsConfused_ByMultipleIgnore_OnClassLevel() final Map testSetMap = new ConcurrentHashMap<>(); - RunListener listener = - ConcurrentRunListener.createInstance( testSetMap, reporterFactory, false, false, - new DefaultDirectConsoleReporter( System.out ) ); + RunListener listener = ConcurrentRunListener.createInstance( testSetMap, reporterFactory, false, false, + new DefaultDirectConsoleReporter( System.out ) ); TestsToRun testsToRun = new TestsToRun( Collections.>singleton( TestClassTest.class ) ); org.junit.runner.notification.RunListener jUnit4RunListener = new JUnitCoreRunListener( listener, testSetMap ); - List customRunListeners = - new ArrayList<>(); + List customRunListeners = new ArrayList<>(); customRunListeners.add( 0, jUnit4RunListener ); try @@ -116,31 +137,34 @@ public void surefireIsConfused_ByMultipleIgnore_OnClassLevel() exception.expect( TestSetFailedException.class ); JUnit4RunListener dummy = new JUnit4RunListener( new MockReporter() ); new JUnitCoreWrapper( new Notifier( dummy, 0 ), jUnitCoreParameters, - new DefaultDirectConsoleReporter( System.out ) ) - .execute( testsToRun, customRunListeners, null ); + new DefaultDirectConsoleReporter( System.out ) ).execute( testsToRun, customRunListeners, null ); } finally { RunResult result = reporterFactory.close(); - assertEquals( "JUnit should report correctly number of test ran(Finished)", 1, result.getCompletedCount() ); + assertEquals( "JUnit should report correctly number of test ran(Finished)", 1, + result.getCompletedCount() ); } } + /** + * + */ @RunWith( TestCaseRunner.class ) public static class TestClassTest { @Test - public void shouldNeverBeCalled() - throws Exception + public void shouldNeverBeCalled() throws Exception { } } - public static class TestCaseRunner - extends BlockJUnit4ClassRunner + /** + * + */ + public static class TestCaseRunner extends BlockJUnit4ClassRunner { - public TestCaseRunner( Class klass ) - throws InitializationError + public TestCaseRunner( Class klass ) throws InitializationError { super( klass ); } @@ -154,15 +178,13 @@ public void run( RunNotifier notifier ) } - private static class TestRunListener - extends org.junit.runner.notification.RunListener + private static class TestRunListener extends org.junit.runner.notification.RunListener { @Override - public void testFinished( Description description ) - throws Exception + public void testFinished( Description description ) throws Exception { throw new RuntimeException( - "This Exception will cause Surefire to receive an internal JUnit Description and fail." ); + "This Exception will cause Surefire to receive an internal JUnit Description and fail." ); } } } \ No newline at end of file diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire813IncorrectResultTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire813IncorrectResultTest.java index f4ad93ce0b..293b2876c6 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire813IncorrectResultTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/Surefire813IncorrectResultTest.java @@ -45,6 +45,9 @@ public void dcount() assertEquals( 0, run.getFailureCount() ); } + /** + * + */ public static class Test6 { private final CountDownLatch latch = new CountDownLatch( 1 ); @@ -64,13 +67,13 @@ public void tearDown() latch.await(); } - private static final String s = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + private static final String STR = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; public void synchPrint() { for ( int i = 0; i < 1000; ++i ) // Increase this number if it does no fail { - System.out.println( i + ":" + s ); + System.out.println( i + ":" + STR ); } } @@ -80,7 +83,7 @@ private class MyThread @Override public void run() { - System.out.println( s ); + System.out.println( STR ); latch.countDown(); synchPrint(); } diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/TestMethodTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/TestMethodTest.java index cb503585f4..3ec149b309 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/TestMethodTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/TestMethodTest.java @@ -30,13 +30,16 @@ public class TestMethodTest extends TestCase { + + public static final int BIG_UPTIME = 100_000; + public void testTestFailure() { - ReportEntry reportEntry = new SimpleReportEntry( "a", "b" ); + ReportEntry reportEntry = new SimpleReportEntry( "a", null, "b", null ); TestMethod testMethod = new TestMethod( reportEntry, new TestSet( TestMethodTest.class.getName() ) ); testMethod.testFailure( reportEntry ); final int elapsed = testMethod.getElapsed(); assertTrue( elapsed >= 0 ); - assertTrue( elapsed < 100000 ); + assertTrue( elapsed < BIG_UPTIME ); } } diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/OptimizedParallelComputerTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/OptimizedParallelComputerTest.java index 9be816f8df..ad362b5839 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/OptimizedParallelComputerTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/OptimizedParallelComputerTest.java @@ -33,20 +33,28 @@ import java.util.HashMap; import java.util.Map; -import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.*; -import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.*; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNT_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTSUITES_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTCLASSES_KEY; +import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.resolveConcurrency; +import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.overrideAvailableProcessors; +import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.setDefaultAvailableProcessors; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; /** - * Testing an algorithm in {@link ParallelComputerUtil} which configures - * optimized thread resources in ParallelComputer by given {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}. + * Testing an algorithm in {@link ParallelComputerUtil} which configures optimized thread resources in ParallelComputer + * by given {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}. * * @author Tibor Digana (tibor17) * @see ParallelComputerUtil * @since 2.17 */ @RunWith( Theories.class ) +@SuppressWarnings( "checkstyle:magicnumber" ) public final class OptimizedParallelComputerTest { @DataPoint @@ -71,13 +79,12 @@ public static void afterClass() } @Theory - public void threadCountSuites( int cpu ) - throws TestSetFailedException + public void threadCountSuites( int cpu ) throws TestSetFailedException { overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suites"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "suites" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 5, 10, 20 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -91,13 +98,12 @@ public void threadCountSuites( int cpu ) } @Theory - public void threadCountClasses( int cpu ) - throws TestSetFailedException + public void threadCountClasses( int cpu ) throws TestSetFailedException { overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classes"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "classes" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 1, 5, 10 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -111,13 +117,12 @@ public void threadCountClasses( int cpu ) } @Theory - public void threadCountMethods( int cpu ) - throws TestSetFailedException + public void threadCountMethods( int cpu ) throws TestSetFailedException { overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 1, 2, 5 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -131,13 +136,12 @@ public void threadCountMethods( int cpu ) } @Theory - public void threadCountBoth( int cpu ) - throws TestSetFailedException + public void threadCountBoth( int cpu ) throws TestSetFailedException { overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "both"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "both" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 1, 2, 5 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -151,13 +155,12 @@ public void threadCountBoth( int cpu ) } @Theory - public void threadCountClassesAndMethods( int cpu ) - throws TestSetFailedException + public void threadCountClassesAndMethods( int cpu ) throws TestSetFailedException { overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classesAndMethods"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "classesAndMethods" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 1, 2, 5 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -171,13 +174,12 @@ public void threadCountClassesAndMethods( int cpu ) } @Theory - public void threadCountSuitesAndMethods( int cpu ) - throws TestSetFailedException + public void threadCountSuitesAndMethods( int cpu ) throws TestSetFailedException { overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndMethods"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "suitesAndMethods" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 2, 3, 5 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -191,13 +193,12 @@ public void threadCountSuitesAndMethods( int cpu ) } @Theory - public void threadCountSuitesAndClasses( int cpu ) - throws TestSetFailedException + public void threadCountSuitesAndClasses( int cpu ) throws TestSetFailedException { overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndClasses"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "suitesAndClasses" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 2, 5, 20 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -211,13 +212,12 @@ public void threadCountSuitesAndClasses( int cpu ) } @Theory - public void threadCountAll( int cpu ) - throws TestSetFailedException + public void threadCountAll( int cpu ) throws TestSetFailedException { overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "all"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "all" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 2, 5, 20 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -231,15 +231,14 @@ public void threadCountAll( int cpu ) } @Theory - public void reusableThreadCountSuitesAndClasses( int cpu ) - throws TestSetFailedException + public void reusableThreadCountSuitesAndClasses( int cpu ) throws TestSetFailedException { // 4 * cpu to 5 * cpu threads to run test classes overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndClasses"); - properties.put(THREADCOUNT_KEY, "6"); - properties.put(THREADCOUNTSUITES_KEY, "2"); + properties.put( PARALLEL_KEY, "suitesAndClasses" ); + properties.put( THREADCOUNT_KEY, "6" ); + properties.put( THREADCOUNTSUITES_KEY, "2" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 3, 5, 20 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -253,15 +252,14 @@ public void reusableThreadCountSuitesAndClasses( int cpu ) } @Theory - public void reusableThreadCountSuitesAndMethods( int cpu ) - throws TestSetFailedException + public void reusableThreadCountSuitesAndMethods( int cpu ) throws TestSetFailedException { // 4 * cpu to 5 * cpu threads to run test methods overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndMethods"); - properties.put(THREADCOUNT_KEY, "6"); - properties.put(THREADCOUNTSUITES_KEY, "2"); + properties.put( PARALLEL_KEY, "suitesAndMethods" ); + properties.put( THREADCOUNT_KEY, "6" ); + properties.put( THREADCOUNTSUITES_KEY, "2" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 3, 5, 20 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -275,15 +273,14 @@ public void reusableThreadCountSuitesAndMethods( int cpu ) } @Theory - public void reusableThreadCountClassesAndMethods( int cpu ) - throws TestSetFailedException + public void reusableThreadCountClassesAndMethods( int cpu ) throws TestSetFailedException { // 4 * cpu to 5 * cpu threads to run test methods overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classesAndMethods"); - properties.put(THREADCOUNT_KEY, "6"); - properties.put(THREADCOUNTCLASSES_KEY, "2"); + properties.put( PARALLEL_KEY, "classesAndMethods" ); + properties.put( THREADCOUNT_KEY, "6" ); + properties.put( THREADCOUNTCLASSES_KEY, "2" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); RunnerCounter counter = new RunnerCounter( 3, 5, 20 ); Concurrency concurrency = resolveConcurrency( params, counter ); @@ -297,8 +294,7 @@ public void reusableThreadCountClassesAndMethods( int cpu ) } @Theory - public void reusableThreadCountAll( int cpu ) - throws TestSetFailedException + public void reusableThreadCountAll( int cpu ) throws TestSetFailedException { // 8 * cpu to 13 * cpu threads to run test methods overrideAvailableProcessors( cpu ); diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java index d87d63a3ef..3e752e3b58 100755 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerBuilderTest.java @@ -51,33 +51,40 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.apache.maven.surefire.junitcore.pc.RangeMatcher.between; -import static org.junit.Assert.*; +import static org.junit.Assert.fail; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; /** * @author Tibor Digana (tibor17) * @since 2.16 */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class ParallelComputerBuilderTest { private static final int DELAY_MULTIPLIER = 7; - private static final Object class1Lock = new Object(); + private static final Object CLASS1BLOCK = new Object(); private static volatile boolean beforeShutdown; private static volatile Runnable shutdownTask; - private static final ConsoleStream logger = new DefaultDirectConsoleReporter( System.out ); + private static final ConsoleStream LOGGER = new DefaultDirectConsoleReporter( System.out ); private static void testKeepBeforeAfter( ParallelComputerBuilder builder, Class... classes ) { JUnitCore core = new JUnitCore(); for ( int round = 0; round < 5; round++ ) { - NothingDoingTest1.methods.clear(); + NothingDoingTest1.METHODS.clear(); Result result = core.run( builder.buildComputer(), classes ); assertTrue( result.wasSuccessful() ); - Iterator methods = NothingDoingTest1.methods.iterator(); + Iterator methods = NothingDoingTest1.METHODS.iterator(); for ( Class clazz : classes ) { String a = clazz.getName() + "#a()"; @@ -113,8 +120,8 @@ public void beforeTest() @Test public void testsWithoutChildrenShouldAlsoBeRun() { - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); - ParallelComputerBuilder.PC computer = ( ParallelComputerBuilder.PC ) parallelComputerBuilder.buildComputer(); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); + ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer(); Result result = new JUnitCore().run( computer, TestWithoutPrecalculatedChildren.class ); assertThat( result.getRunCount(), is( 1 ) ); } @@ -122,7 +129,7 @@ public void testsWithoutChildrenShouldAlsoBeRun() @Test public void parallelMethodsReuseOneOrTwoThreads() { - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); parallelComputerBuilder.useOnePool( 4 ); // One thread because one suite: TestSuite, however the capacity is 5. @@ -168,7 +175,7 @@ else if ( Class1.maxConcurrentMethods == 2 ) @Test public void suiteAndClassInOnePool() { - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); parallelComputerBuilder.useOnePool( 5 ); parallelComputerBuilder.parallelSuites( 5 ); parallelComputerBuilder.parallelClasses( 5 ); @@ -190,18 +197,16 @@ public void suiteAndClassInOnePool() assertThat( computer.getPoolCapacity(), is( 5 ) ); assertTrue( result.wasSuccessful() ); assertThat( Class1.maxConcurrentMethods, is( 2 ) ); - assertThat( timeSpent, anyOf( - between( 1500 * DELAY_MULTIPLIER - 50, 1750 * DELAY_MULTIPLIER ), + assertThat( timeSpent, anyOf( between( 1500 * DELAY_MULTIPLIER - 50, 1750 * DELAY_MULTIPLIER ), between( 2000 * DELAY_MULTIPLIER - 50, 2250 * DELAY_MULTIPLIER ), - between( 2500 * DELAY_MULTIPLIER - 50, 2750 * DELAY_MULTIPLIER ) - ) ); + between( 2500 * DELAY_MULTIPLIER - 50, 2750 * DELAY_MULTIPLIER ) ) ); } @Test public void onePoolWithUnlimitedParallelMethods() { // see ParallelComputerBuilder Javadoc - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); parallelComputerBuilder.useOnePool( 8 ); parallelComputerBuilder.parallelSuites( 2 ); parallelComputerBuilder.parallelClasses( 4 ); @@ -229,7 +234,7 @@ public void onePoolWithUnlimitedParallelMethods() @Test public void underflowParallelism() { - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); parallelComputerBuilder.useOnePool( 3 ); // One thread because one suite: TestSuite. @@ -264,7 +269,7 @@ public void underflowParallelism() @Test public void separatePoolsWithSuite() { - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); parallelComputerBuilder.parallelSuites( 5 ); parallelComputerBuilder.parallelClasses( 5 ); parallelComputerBuilder.parallelMethods( 3 ); @@ -291,7 +296,7 @@ public void separatePoolsWithSuite() @Test public void separatePoolsWithSuiteAndClass() { - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); parallelComputerBuilder.parallelSuites( 5 ); parallelComputerBuilder.parallelClasses( 5 ); parallelComputerBuilder.parallelMethods( 3 ); @@ -321,7 +326,7 @@ public void separatePoolsWithSuiteAndClass() @Test public void separatePoolsWithSuiteAndSequentialClasses() { - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); parallelComputerBuilder.parallelSuites( 5 ); parallelComputerBuilder.parallelClasses( 1 ); parallelComputerBuilder.parallelMethods( 3 ); @@ -372,7 +377,7 @@ public void shutdownWithInterrupt() public void nothingParallel() { JUnitCore core = new JUnitCore(); - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ); assertFalse( builder.isOptimized() ); Result result = core.run( builder.buildComputer(), NothingDoingTest1.class, NothingDoingTest2.class ); @@ -396,7 +401,7 @@ public void nothingParallel() result = core.run( builder.buildComputer(), NothingDoingTest1.class, NothingDoingSuite.class ); assertTrue( result.wasSuccessful() ); - Class[] classes = { NothingDoingTest1.class, NothingDoingSuite.class }; + Class[] classes = {NothingDoingTest1.class, NothingDoingSuite.class}; builder.useOnePool( 2 ).parallelSuites( 1 ).parallelClasses( 1 ); assertFalse( builder.isOptimized() ); @@ -408,8 +413,8 @@ public void nothingParallel() result = core.run( builder.buildComputer(), classes ); assertTrue( result.wasSuccessful() ); - classes = new Class[]{ NothingDoingSuite.class, NothingDoingSuite.class, NothingDoingTest1.class, - NothingDoingTest2.class, NothingDoingTest3.class }; + classes = new Class[] { NothingDoingSuite.class, NothingDoingSuite.class, NothingDoingTest1.class, + NothingDoingTest2.class, NothingDoingTest3.class }; builder.useOnePool( 2 ).parallelSuites( 1 ).parallelClasses( 1 ); assertFalse( builder.isOptimized() ); @@ -425,7 +430,7 @@ public void nothingParallel() @Test public void keepBeforeAfterOneClass() { - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ); builder.parallelMethods(); assertFalse( builder.isOptimized() ); testKeepBeforeAfter( builder, NothingDoingTest1.class ); @@ -434,7 +439,7 @@ public void keepBeforeAfterOneClass() @Test public void keepBeforeAfterTwoClasses() { - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ); builder.useOnePool( 5 ).parallelClasses( 1 ).parallelMethods( 2 ); assertFalse( builder.isOptimized() ); testKeepBeforeAfter( builder, NothingDoingTest1.class, NothingDoingTest2.class ); @@ -443,15 +448,15 @@ public void keepBeforeAfterTwoClasses() @Test public void keepBeforeAfterTwoParallelClasses() { - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ); builder.useOnePool( 8 ).parallelClasses( 2 ).parallelMethods( 2 ); assertFalse( builder.isOptimized() ); JUnitCore core = new JUnitCore(); - NothingDoingTest1.methods.clear(); - Class[] classes = { NothingDoingTest1.class, NothingDoingTest2.class, NothingDoingTest3.class }; + NothingDoingTest1.METHODS.clear(); + Class[] classes = {NothingDoingTest1.class, NothingDoingTest2.class, NothingDoingTest3.class}; Result result = core.run( builder.buildComputer(), classes ); assertTrue( result.wasSuccessful() ); - ArrayList methods = new ArrayList<>( NothingDoingTest1.methods ); + ArrayList methods = new ArrayList<>( NothingDoingTest1.METHODS ); assertThat( methods.size(), is( 12 ) ); assertThat( methods.subList( 9, 12 ), is( not( Arrays.asList( "deinit", "deinit", "deinit" ) ) ) ); } @@ -459,8 +464,8 @@ public void keepBeforeAfterTwoParallelClasses() @Test public void notThreadSafeTest() { - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ) - .useOnePool( 6 ).optimize( true ).parallelClasses( 3 ).parallelMethods( 3 ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ).useOnePool( 6 ).optimize( + true ).parallelClasses( 3 ).parallelMethods( 3 ); ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer(); Result result = new JUnitCore().run( computer, NotThreadSafeTest1.class, NotThreadSafeTest2.class ); assertTrue( result.wasSuccessful() ); @@ -480,8 +485,8 @@ public void notThreadSafeTest() @Test public void mixedThreadSafety() { - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ) - .useOnePool( 6 ).optimize( true ).parallelClasses( 3 ).parallelMethods( 3 ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ).useOnePool( 6 ).optimize( + true ).parallelClasses( 3 ).parallelMethods( 3 ); ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer(); Result result = new JUnitCore().run( computer, NotThreadSafeTest1.class, NormalTest1.class ); assertTrue( result.wasSuccessful() ); @@ -502,8 +507,7 @@ public void mixedThreadSafety() @Test public void notThreadSafeTestsInSuite() { - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ) - .useOnePool( 5 ).parallelMethods( 3 ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ).useOnePool( 5 ).parallelMethods( 3 ); assertFalse( builder.isOptimized() ); ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer(); Result result = new JUnitCore().run( computer, NotThreadSafeTestSuite.class ); @@ -525,8 +529,8 @@ public void notThreadSafeTestsInSuite() @Test public void mixedThreadSafetyInSuite() { - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ) - .useOnePool( 10 ).optimize( true ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ).useOnePool( 10 ).optimize( + true ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 ); ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer(); Result result = new JUnitCore().run( computer, MixedSuite.class ); assertTrue( result.wasSuccessful() ); @@ -547,8 +551,8 @@ public void mixedThreadSafetyInSuite() @Test public void inheritanceWithNotThreadSafe() { - ParallelComputerBuilder builder = new ParallelComputerBuilder( logger ) - .useOnePool( 10 ).optimize( true ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 ); + ParallelComputerBuilder builder = new ParallelComputerBuilder( LOGGER ).useOnePool( 10 ).optimize( + true ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 ); ParallelComputerBuilder.PC computer = (ParallelComputerBuilder.PC) builder.buildComputer(); Result result = new JUnitCore().run( computer, OverMixedSuite.class ); assertTrue( result.wasSuccessful() ); @@ -567,8 +571,7 @@ public void inheritanceWithNotThreadSafe() } @Test - public void beforeAfterThreadChanges() - throws InterruptedException + public void beforeAfterThreadChanges() throws InterruptedException { // try to GC dead Thread objects from previous tests for ( int i = 0; i < 5; i++ ) @@ -577,7 +580,7 @@ public void beforeAfterThreadChanges() TimeUnit.MILLISECONDS.sleep( 500L ); } Collection expectedThreads = jvmThreads(); - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ); parallelComputerBuilder.parallelMethods( 3 ); ParallelComputer computer = parallelComputerBuilder.buildComputer(); Result result = new JUnitCore().run( computer, TestWithBeforeAfter.class ); @@ -613,16 +616,13 @@ private static class ShutdownTest { Result run( final boolean useInterrupt ) { - ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( logger ) - .useOnePool( 8 ) - .parallelSuites( 2 ) - .parallelClasses( 3 ) - .parallelMethods( 3 ); + ParallelComputerBuilder parallelComputerBuilder = new ParallelComputerBuilder( LOGGER ).useOnePool( + 8 ).parallelSuites( 2 ).parallelClasses( 3 ).parallelMethods( 3 ); assertFalse( parallelComputerBuilder.isOptimized() ); final ParallelComputerBuilder.PC computer = - (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer(); + (ParallelComputerBuilder.PC) parallelComputerBuilder.buildComputer(); shutdownTask = new Runnable() { @Override @@ -636,6 +636,9 @@ public void run() } } + /** + * + */ public static class Class1 { static volatile int concurrentMethods = 0; @@ -643,20 +646,18 @@ public static class Class1 static volatile int maxConcurrentMethods = 0; @Test - public void test1() - throws InterruptedException + public void test1() throws InterruptedException { - synchronized ( class1Lock ) + synchronized ( CLASS1BLOCK ) { ++concurrentMethods; - class1Lock.wait( DELAY_MULTIPLIER * 500L ); + CLASS1BLOCK.wait( DELAY_MULTIPLIER * 500L ); maxConcurrentMethods = Math.max( maxConcurrentMethods, concurrentMethods-- ); } } @Test - public void test2() - throws InterruptedException + public void test2() throws InterruptedException { test1(); Runnable shutdownTask = ParallelComputerBuilderTest.shutdownTask; @@ -668,71 +669,89 @@ public void test2() } } - public static class Class2 - extends Class1 + /** + * + */ + public static class Class2 extends Class1 { } - public static class Class3 - extends Class1 + /** + * + */ + public static class Class3 extends Class1 { } + /** + * + */ public static class NothingDoingTest1 { - static final Collection methods = new ConcurrentLinkedQueue<>(); + private static final Collection METHODS = new ConcurrentLinkedQueue<>(); @BeforeClass public static void init() { - methods.add( "init" ); + METHODS.add( "init" ); } @AfterClass public static void deinit() { - methods.add( "deinit" ); + METHODS.add( "deinit" ); } @Test - public void a() - throws InterruptedException + public void a() throws InterruptedException { Thread.sleep( 5 ); - methods.add( getClass().getName() + "#a()" ); + METHODS.add( getClass().getName() + "#a()" ); } @Test - public void b() - throws InterruptedException + public void b() throws InterruptedException { Thread.sleep( 5 ); - methods.add( getClass().getName() + "#b()" ); + METHODS.add( getClass().getName() + "#b()" ); } } - public static class NothingDoingTest2 - extends NothingDoingTest1 + /** + * + */ + public static class NothingDoingTest2 extends NothingDoingTest1 { } - public static class NothingDoingTest3 - extends NothingDoingTest1 + /** + * + */ + public static class NothingDoingTest3 extends NothingDoingTest1 { } + /** + * + */ @RunWith( Suite.class ) - @Suite.SuiteClasses( { NothingDoingTest1.class, NothingDoingTest2.class } ) + @Suite.SuiteClasses( {NothingDoingTest1.class, NothingDoingTest2.class} ) public static class NothingDoingSuite { } + /** + * + */ @RunWith( Suite.class ) - @Suite.SuiteClasses( { Class2.class, Class1.class } ) + @Suite.SuiteClasses( {Class2.class, Class1.class} ) public static class TestSuite { } + /** + * + */ public static class Test2 { @Test @@ -742,11 +761,18 @@ public void test() } } + /** + * + */ @RunWith( ReportOneTestAtRuntimeRunner.class ) - public static class TestWithoutPrecalculatedChildren {} + public static class TestWithoutPrecalculatedChildren + { + } - public static class ReportOneTestAtRuntimeRunner - extends ParentRunner + /** + * + */ + public static class ReportOneTestAtRuntimeRunner extends ParentRunner { private final Class testClass; private final Description suiteDescription; @@ -759,7 +785,7 @@ public ReportOneTestAtRuntimeRunner( Class testClass ) throws InitializationE this.testClass = testClass; suiteDescription = Description.createSuiteDescription( testClass ); myTestMethodDescr = Description.createTestDescription( testClass, "my_test" ); -// suiteDescription.addChild(myTestMethodDescr); // let it be not known at start time + // suiteDescription.addChild(myTestMethodDescr); // let it be not known at start time } protected List getChildren() @@ -789,6 +815,9 @@ public void run( RunNotifier notifier ) } } + /** + * + */ @NotThreadSafe public static class NotThreadSafeTest1 { @@ -814,6 +843,9 @@ public void test() } } + /** + * + */ @NotThreadSafe public static class NotThreadSafeTest2 { @@ -839,6 +871,9 @@ public void test() } } + /** + * + */ @NotThreadSafe public static class NotThreadSafeTest3 { @@ -852,8 +887,11 @@ public void test() } } + /** + * + */ @RunWith( Suite.class ) - @Suite.SuiteClasses( { NormalTest1.class, NormalTest2.class } ) + @Suite.SuiteClasses( {NormalTest1.class, NormalTest2.class} ) @NotThreadSafe public static class NotThreadSafeTestSuite { @@ -870,6 +908,9 @@ public static void afterSuite() } } + /** + * + */ public static class NormalTest1 { static volatile Thread t; @@ -881,6 +922,9 @@ public void test() } } + /** + * + */ public static class NormalTest2 { static volatile Thread t; @@ -892,8 +936,11 @@ public void test() } } + /** + * + */ @RunWith( Suite.class ) - @Suite.SuiteClasses( { NotThreadSafeTest1.class, NormalTest1.class } ) + @Suite.SuiteClasses( {NotThreadSafeTest1.class, NormalTest1.class} ) public static class MixedSuite { @BeforeClass @@ -909,8 +956,11 @@ public static void afterSuite() } } + /** + * + */ @RunWith( Suite.class ) - @Suite.SuiteClasses( { NotThreadSafeTest3.class, NormalTest1.class } ) + @Suite.SuiteClasses( {NotThreadSafeTest3.class, NormalTest1.class} ) @NotThreadSafe public static class OverMixedSuite { @@ -927,11 +977,13 @@ public static void afterSuite() } } + /** + * + */ public static class TestWithBeforeAfter { @BeforeClass - public static void beforeClass() - throws InterruptedException + public static void beforeClass() throws InterruptedException { System.out.println( new Date() + " BEG: beforeClass" ); sleepSeconds( 1 ); @@ -939,8 +991,7 @@ public static void beforeClass() } @Before - public void before() - throws InterruptedException + public void before() throws InterruptedException { System.out.println( new Date() + " BEG: before" ); sleepSeconds( 1 ); @@ -948,8 +999,7 @@ public void before() } @Test - public void test() - throws InterruptedException + public void test() throws InterruptedException { System.out.println( new Date() + " BEG: test" ); sleepSeconds( 1 ); @@ -957,8 +1007,7 @@ public void test() } @After - public void after() - throws InterruptedException + public void after() throws InterruptedException { System.out.println( new Date() + " BEG: after" ); sleepSeconds( 1 ); @@ -966,8 +1015,7 @@ public void after() } @AfterClass - public static void afterClass() - throws InterruptedException + public static void afterClass() throws InterruptedException { System.out.println( new Date() + " BEG: afterClass" ); sleepSeconds( 1 ); @@ -980,8 +1028,7 @@ private static long systemMillis() return TimeUnit.NANOSECONDS.toMillis( System.nanoTime() ); } - private static void sleepSeconds( int seconds ) - throws InterruptedException + private static void sleepSeconds( int seconds ) throws InterruptedException { TimeUnit.SECONDS.sleep( seconds ); } diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java index b9f862cd1a..9fea9cbd53 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/ParallelComputerUtilTest.java @@ -41,23 +41,34 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.*; -import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.*; +import static org.apache.maven.surefire.junitcore.pc.ParallelComputerUtil.resolveConcurrency; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNT_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTSUITES_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTCLASSES_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.THREADCOUNTMETHODS_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_TIMEOUT_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.PARALLEL_TIMEOUTFORCED_KEY; +import static org.apache.maven.surefire.junitcore.JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; /** - * Testing an algorithm in {@link ParallelComputerUtil} which configures - * allocated thread resources in ParallelComputer by given {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}. + * Testing an algorithm in {@link ParallelComputerUtil} which configures allocated thread resources in ParallelComputer + * by given {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}. * * @author Tibor Digana (tibor17) * @see ParallelComputerUtil * @since 2.16 */ @RunWith( Theories.class ) +@SuppressWarnings( "checkstyle:magicnumber" ) public final class ParallelComputerUtilTest { - private final ConsoleStream logger = new DefaultDirectConsoleReporter( System.out ); + private static final ConsoleStream LOGGER = new DefaultDirectConsoleReporter( System.out ); @DataPoint public static final int CPU_1 = 1; @@ -81,8 +92,7 @@ public static void afterClass() } @Before - public void beforeTest() - throws InterruptedException + public void beforeTest() throws InterruptedException { System.gc(); Thread.sleep( 50L ); @@ -95,8 +105,7 @@ private static Map parallel( String parallel ) } @Test - public void unknownParallel() - throws TestSetFailedException + public void unknownParallel() throws TestSetFailedException { Map properties = new HashMap<>(); exception.expect( TestSetFailedException.class ); @@ -104,8 +113,7 @@ public void unknownParallel() } @Test - public void unknownThreadCountSuites() - throws TestSetFailedException + public void unknownThreadCountSuites() throws TestSetFailedException { JUnitCoreParameters params = new JUnitCoreParameters( parallel( "suites" ) ); assertTrue( params.isParallelSuites() ); @@ -116,8 +124,7 @@ public void unknownThreadCountSuites() } @Test - public void unknownThreadCountClasses() - throws TestSetFailedException + public void unknownThreadCountClasses() throws TestSetFailedException { JUnitCoreParameters params = new JUnitCoreParameters( parallel( "classes" ) ); assertFalse( params.isParallelSuites() ); @@ -128,8 +135,7 @@ public void unknownThreadCountClasses() } @Test - public void unknownThreadCountMethods() - throws TestSetFailedException + public void unknownThreadCountMethods() throws TestSetFailedException { JUnitCoreParameters params = new JUnitCoreParameters( parallel( "methods" ) ); assertFalse( params.isParallelSuites() ); @@ -140,8 +146,7 @@ public void unknownThreadCountMethods() } @Test - public void unknownThreadCountBoth() - throws TestSetFailedException + public void unknownThreadCountBoth() throws TestSetFailedException { JUnitCoreParameters params = new JUnitCoreParameters( parallel( "both" ) ); assertFalse( params.isParallelSuites() ); @@ -152,8 +157,7 @@ public void unknownThreadCountBoth() } @Test - public void unknownThreadCountAll() - throws TestSetFailedException + public void unknownThreadCountAll() throws TestSetFailedException { JUnitCoreParameters params = new JUnitCoreParameters( parallel( "all" ) ); assertTrue( params.isParallelSuites() ); @@ -164,8 +168,7 @@ public void unknownThreadCountAll() } @Test - public void unknownThreadCountSuitesAndClasses() - throws TestSetFailedException + public void unknownThreadCountSuitesAndClasses() throws TestSetFailedException { JUnitCoreParameters params = new JUnitCoreParameters( parallel( "suitesAndClasses" ) ); assertTrue( params.isParallelSuites() ); @@ -176,8 +179,7 @@ public void unknownThreadCountSuitesAndClasses() } @Test - public void unknownThreadCountSuitesAndMethods() - throws TestSetFailedException + public void unknownThreadCountSuitesAndMethods() throws TestSetFailedException { JUnitCoreParameters params = new JUnitCoreParameters( parallel( "suitesAndMethods" ) ); assertTrue( params.isParallelSuites() ); @@ -188,8 +190,7 @@ public void unknownThreadCountSuitesAndMethods() } @Test - public void unknownThreadCountClassesAndMethods() - throws TestSetFailedException + public void unknownThreadCountClassesAndMethods() throws TestSetFailedException { JUnitCoreParameters params = new JUnitCoreParameters( parallel( "classesAndMethods" ) ); assertFalse( params.isParallelSuites() ); @@ -200,13 +201,12 @@ public void unknownThreadCountClassesAndMethods() } @Theory - public void useUnlimitedThreadsSuites( int cpu ) - throws TestSetFailedException + public void useUnlimitedThreadsSuites( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suites"); - properties.put(USEUNLIMITEDTHREADS_KEY, "true"); + properties.put( PARALLEL_KEY, "suites" ); + properties.put( USEUNLIMITEDTHREADS_KEY, "true" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -217,7 +217,7 @@ public void useUnlimitedThreadsSuites( int cpu ) assertThat( concurrency.classes, is( 0 ) ); assertThat( concurrency.methods, is( 0 ) ); - properties.put(THREADCOUNTSUITES_KEY, "5"); + properties.put( THREADCOUNTSUITES_KEY, "5" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -230,13 +230,12 @@ public void useUnlimitedThreadsSuites( int cpu ) } @Theory - public void useUnlimitedThreadsClasses( int cpu ) - throws TestSetFailedException + public void useUnlimitedThreadsClasses( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classes"); - properties.put(USEUNLIMITEDTHREADS_KEY, "true"); + properties.put( PARALLEL_KEY, "classes" ); + properties.put( USEUNLIMITEDTHREADS_KEY, "true" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -247,7 +246,7 @@ public void useUnlimitedThreadsClasses( int cpu ) assertThat( concurrency.classes, is( Integer.MAX_VALUE ) ); assertThat( concurrency.methods, is( 0 ) ); - properties.put(THREADCOUNTCLASSES_KEY, "5"); + properties.put( THREADCOUNTCLASSES_KEY, "5" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -260,13 +259,12 @@ public void useUnlimitedThreadsClasses( int cpu ) } @Theory - public void unlimitedThreadsMethods( int cpu ) - throws TestSetFailedException + public void unlimitedThreadsMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(USEUNLIMITEDTHREADS_KEY, "true"); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( USEUNLIMITEDTHREADS_KEY, "true" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -277,7 +275,7 @@ public void unlimitedThreadsMethods( int cpu ) assertThat( concurrency.classes, is( 0 ) ); assertThat( concurrency.methods, is( Integer.MAX_VALUE ) ); - properties.put(THREADCOUNTMETHODS_KEY, "5"); + properties.put( THREADCOUNTMETHODS_KEY, "5" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -290,13 +288,12 @@ public void unlimitedThreadsMethods( int cpu ) } @Theory - public void unlimitedThreadsSuitesAndClasses( int cpu ) - throws TestSetFailedException + public void unlimitedThreadsSuitesAndClasses( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndClasses"); - properties.put(USEUNLIMITEDTHREADS_KEY, "true"); + properties.put( PARALLEL_KEY, "suitesAndClasses" ); + properties.put( USEUNLIMITEDTHREADS_KEY, "true" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -307,8 +304,8 @@ public void unlimitedThreadsSuitesAndClasses( int cpu ) assertThat( concurrency.classes, is( Integer.MAX_VALUE ) ); assertThat( concurrency.methods, is( 0 ) ); - properties.put(THREADCOUNTSUITES_KEY, "5"); - properties.put(THREADCOUNTCLASSES_KEY, "15"); + properties.put( THREADCOUNTSUITES_KEY, "5" ); + properties.put( THREADCOUNTCLASSES_KEY, "15" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -321,13 +318,12 @@ public void unlimitedThreadsSuitesAndClasses( int cpu ) } @Theory - public void unlimitedThreadsSuitesAndMethods( int cpu ) - throws TestSetFailedException + public void unlimitedThreadsSuitesAndMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndMethods"); - properties.put(USEUNLIMITEDTHREADS_KEY, "true"); + properties.put( PARALLEL_KEY, "suitesAndMethods" ); + properties.put( USEUNLIMITEDTHREADS_KEY, "true" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -338,8 +334,8 @@ public void unlimitedThreadsSuitesAndMethods( int cpu ) assertThat( concurrency.classes, is( 0 ) ); assertThat( concurrency.methods, is( Integer.MAX_VALUE ) ); - properties.put(THREADCOUNTSUITES_KEY, "5"); - properties.put(THREADCOUNTMETHODS_KEY, "15"); + properties.put( THREADCOUNTSUITES_KEY, "5" ); + properties.put( THREADCOUNTMETHODS_KEY, "15" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -352,13 +348,12 @@ public void unlimitedThreadsSuitesAndMethods( int cpu ) } @Theory - public void unlimitedThreadsClassesAndMethods( int cpu ) - throws TestSetFailedException + public void unlimitedThreadsClassesAndMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classesAndMethods"); - properties.put(USEUNLIMITEDTHREADS_KEY, "true"); + properties.put( PARALLEL_KEY, "classesAndMethods" ); + properties.put( USEUNLIMITEDTHREADS_KEY, "true" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -369,8 +364,8 @@ public void unlimitedThreadsClassesAndMethods( int cpu ) assertThat( concurrency.classes, is( Integer.MAX_VALUE ) ); assertThat( concurrency.methods, is( Integer.MAX_VALUE ) ); - properties.put(THREADCOUNTCLASSES_KEY, "5"); - properties.put(THREADCOUNTMETHODS_KEY, "15"); + properties.put( THREADCOUNTCLASSES_KEY, "5" ); + properties.put( THREADCOUNTMETHODS_KEY, "15" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -383,13 +378,12 @@ public void unlimitedThreadsClassesAndMethods( int cpu ) } @Theory - public void unlimitedThreadsAll( int cpu ) - throws TestSetFailedException + public void unlimitedThreadsAll( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "all"); - properties.put(USEUNLIMITEDTHREADS_KEY, "true"); + properties.put( PARALLEL_KEY, "all" ); + properties.put( USEUNLIMITEDTHREADS_KEY, "true" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -400,9 +394,9 @@ public void unlimitedThreadsAll( int cpu ) assertThat( concurrency.classes, is( Integer.MAX_VALUE ) ); assertThat( concurrency.methods, is( Integer.MAX_VALUE ) ); - properties.put(THREADCOUNTSUITES_KEY, "5"); - properties.put(THREADCOUNTCLASSES_KEY, "15"); - properties.put(THREADCOUNTMETHODS_KEY, "30"); + properties.put( THREADCOUNTSUITES_KEY, "5" ); + properties.put( THREADCOUNTCLASSES_KEY, "15" ); + properties.put( THREADCOUNTMETHODS_KEY, "30" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -415,13 +409,12 @@ public void unlimitedThreadsAll( int cpu ) } @Theory - public void threadCountSuites( int cpu ) - throws TestSetFailedException + public void threadCountSuites( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suites"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "suites" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -434,13 +427,12 @@ public void threadCountSuites( int cpu ) } @Theory - public void threadCountClasses( int cpu ) - throws TestSetFailedException + public void threadCountClasses( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classes"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "classes" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -453,13 +445,12 @@ public void threadCountClasses( int cpu ) } @Theory - public void threadCountMethods( int cpu ) - throws TestSetFailedException + public void threadCountMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -472,13 +463,12 @@ public void threadCountMethods( int cpu ) } @Theory - public void threadCountBoth( int cpu ) - throws TestSetFailedException + public void threadCountBoth( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "both"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "both" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -491,13 +481,12 @@ public void threadCountBoth( int cpu ) } @Theory - public void threadCountClassesAndMethods( int cpu ) - throws TestSetFailedException + public void threadCountClassesAndMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classesAndMethods"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "classesAndMethods" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -510,13 +499,12 @@ public void threadCountClassesAndMethods( int cpu ) } @Theory - public void threadCountSuitesAndMethods( int cpu ) - throws TestSetFailedException + public void threadCountSuitesAndMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndMethods"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "suitesAndMethods" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -529,13 +517,12 @@ public void threadCountSuitesAndMethods( int cpu ) } @Theory - public void threadCountSuitesAndClasses( int cpu ) - throws TestSetFailedException + public void threadCountSuitesAndClasses( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndClasses"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "suitesAndClasses" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -548,13 +535,12 @@ public void threadCountSuitesAndClasses( int cpu ) } @Theory - public void threadCountAll( int cpu ) - throws TestSetFailedException + public void threadCountAll( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "all"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "all" ); + properties.put( THREADCOUNT_KEY, "3" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -567,16 +553,15 @@ public void threadCountAll( int cpu ) } @Theory - public void everyThreadCountSuitesAndClasses( int cpu ) - throws TestSetFailedException + public void everyThreadCountSuitesAndClasses( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndClasses"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "suitesAndClasses" ); + properties.put( THREADCOUNT_KEY, "3" ); // % percentage ratio - properties.put(THREADCOUNTSUITES_KEY, "34"); - properties.put(THREADCOUNTCLASSES_KEY, "66"); + properties.put( THREADCOUNTSUITES_KEY, "34" ); + properties.put( THREADCOUNTCLASSES_KEY, "66" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -590,16 +575,15 @@ public void everyThreadCountSuitesAndClasses( int cpu ) } @Theory - public void everyThreadCountSuitesAndMethods( int cpu ) - throws TestSetFailedException + public void everyThreadCountSuitesAndMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndMethods"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "suitesAndMethods" ); + properties.put( THREADCOUNT_KEY, "3" ); // % percentage ratio - properties.put(THREADCOUNTSUITES_KEY, "34"); - properties.put(THREADCOUNTMETHODS_KEY, "66"); + properties.put( THREADCOUNTSUITES_KEY, "34" ); + properties.put( THREADCOUNTMETHODS_KEY, "66" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -613,16 +597,15 @@ public void everyThreadCountSuitesAndMethods( int cpu ) } @Theory - public void everyThreadCountClassesAndMethods( int cpu ) - throws TestSetFailedException + public void everyThreadCountClassesAndMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classesAndMethods"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "classesAndMethods" ); + properties.put( THREADCOUNT_KEY, "3" ); // % percentage ratio - properties.put(THREADCOUNTCLASSES_KEY, "34"); - properties.put(THREADCOUNTMETHODS_KEY, "66"); + properties.put( THREADCOUNTCLASSES_KEY, "34" ); + properties.put( THREADCOUNTMETHODS_KEY, "66" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -636,17 +619,16 @@ public void everyThreadCountClassesAndMethods( int cpu ) } @Theory - public void everyThreadCountAll( int cpu ) - throws TestSetFailedException + public void everyThreadCountAll( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "all"); - properties.put(THREADCOUNT_KEY, "3"); + properties.put( PARALLEL_KEY, "all" ); + properties.put( THREADCOUNT_KEY, "3" ); // % percentage ratio - properties.put(THREADCOUNTSUITES_KEY, "17"); - properties.put(THREADCOUNTCLASSES_KEY, "34"); - properties.put(THREADCOUNTMETHODS_KEY, "49"); + properties.put( THREADCOUNTSUITES_KEY, "17" ); + properties.put( THREADCOUNTCLASSES_KEY, "34" ); + properties.put( THREADCOUNTMETHODS_KEY, "49" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -661,15 +643,14 @@ public void everyThreadCountAll( int cpu ) } @Theory - public void reusableThreadCountSuitesAndClasses( int cpu ) - throws TestSetFailedException + public void reusableThreadCountSuitesAndClasses( int cpu ) throws TestSetFailedException { // 4 * cpu to 5 * cpu threads to run test classes ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndClasses"); - properties.put(THREADCOUNT_KEY, "6"); - properties.put(THREADCOUNTSUITES_KEY, "2"); + properties.put( PARALLEL_KEY, "suitesAndClasses" ); + properties.put( THREADCOUNT_KEY, "6" ); + properties.put( THREADCOUNTSUITES_KEY, "2" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -682,15 +663,14 @@ public void reusableThreadCountSuitesAndClasses( int cpu ) } @Theory - public void reusableThreadCountSuitesAndMethods( int cpu ) - throws TestSetFailedException + public void reusableThreadCountSuitesAndMethods( int cpu ) throws TestSetFailedException { // 4 * cpu to 5 * cpu threads to run test methods ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndMethods"); - properties.put(THREADCOUNT_KEY, "6"); - properties.put(THREADCOUNTSUITES_KEY, "2"); + properties.put( PARALLEL_KEY, "suitesAndMethods" ); + properties.put( THREADCOUNT_KEY, "6" ); + properties.put( THREADCOUNTSUITES_KEY, "2" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -703,15 +683,14 @@ public void reusableThreadCountSuitesAndMethods( int cpu ) } @Theory - public void reusableThreadCountClassesAndMethods( int cpu ) - throws TestSetFailedException + public void reusableThreadCountClassesAndMethods( int cpu ) throws TestSetFailedException { // 4 * cpu to 5 * cpu threads to run test methods ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classesAndMethods"); - properties.put(THREADCOUNT_KEY, "6"); - properties.put(THREADCOUNTCLASSES_KEY, "2"); + properties.put( PARALLEL_KEY, "classesAndMethods" ); + properties.put( THREADCOUNT_KEY, "6" ); + properties.put( THREADCOUNTCLASSES_KEY, "2" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -724,16 +703,15 @@ public void reusableThreadCountClassesAndMethods( int cpu ) } @Theory - public void reusableThreadCountAll( int cpu ) - throws TestSetFailedException + public void reusableThreadCountAll( int cpu ) throws TestSetFailedException { // 8 * cpu to 13 * cpu threads to run test methods ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "all"); - properties.put(THREADCOUNT_KEY, "14"); - properties.put(THREADCOUNTSUITES_KEY, "2"); - properties.put(THREADCOUNTCLASSES_KEY, "4"); + properties.put( PARALLEL_KEY, "all" ); + properties.put( THREADCOUNT_KEY, "14" ); + properties.put( THREADCOUNTSUITES_KEY, "2" ); + properties.put( THREADCOUNTCLASSES_KEY, "4" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -746,13 +724,12 @@ public void reusableThreadCountAll( int cpu ) } @Theory - public void suites( int cpu ) - throws TestSetFailedException + public void suites( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suites"); - properties.put(THREADCOUNTSUITES_KEY, "5"); + properties.put( PARALLEL_KEY, "suites" ); + properties.put( THREADCOUNTSUITES_KEY, "5" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -765,13 +742,12 @@ public void suites( int cpu ) } @Theory - public void classes( int cpu ) - throws TestSetFailedException + public void classes( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classes"); - properties.put(THREADCOUNTCLASSES_KEY, "5"); + properties.put( PARALLEL_KEY, "classes" ); + properties.put( THREADCOUNTCLASSES_KEY, "5" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -784,13 +760,12 @@ public void classes( int cpu ) } @Theory - public void methods( int cpu ) - throws TestSetFailedException + public void methods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(THREADCOUNTMETHODS_KEY, "5"); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( THREADCOUNTMETHODS_KEY, "5" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -803,15 +778,14 @@ public void methods( int cpu ) } @Theory - public void suitesAndClasses( int cpu ) - throws TestSetFailedException + public void suitesAndClasses( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndClasses"); - properties.put(THREADCOUNTSUITES_KEY, "5"); - properties.put(THREADCOUNTCLASSES_KEY, "15"); + properties.put( PARALLEL_KEY, "suitesAndClasses" ); + properties.put( THREADCOUNTSUITES_KEY, "5" ); + properties.put( THREADCOUNTCLASSES_KEY, "15" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -825,8 +799,8 @@ public void suitesAndClasses( int cpu ) // Warning: this case works but is not enabled in AbstractSurefireMojo // Instead use the 'useUnlimitedThreads' parameter. properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndClasses"); - properties.put(THREADCOUNTSUITES_KEY, "5"); + properties.put( PARALLEL_KEY, "suitesAndClasses" ); + properties.put( THREADCOUNTSUITES_KEY, "5" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -839,15 +813,14 @@ public void suitesAndClasses( int cpu ) } @Theory - public void suitesAndMethods( int cpu ) - throws TestSetFailedException + public void suitesAndMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndMethods"); - properties.put(THREADCOUNTSUITES_KEY, "5"); - properties.put(THREADCOUNTMETHODS_KEY, "15"); + properties.put( PARALLEL_KEY, "suitesAndMethods" ); + properties.put( THREADCOUNTSUITES_KEY, "5" ); + properties.put( THREADCOUNTMETHODS_KEY, "15" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -861,8 +834,8 @@ public void suitesAndMethods( int cpu ) // Warning: this case works but is not enabled in AbstractSurefireMojo // Instead use the 'useUnlimitedThreads' parameter. properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "suitesAndMethods"); - properties.put(THREADCOUNTSUITES_KEY, "5"); + properties.put( PARALLEL_KEY, "suitesAndMethods" ); + properties.put( THREADCOUNTSUITES_KEY, "5" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -875,15 +848,14 @@ public void suitesAndMethods( int cpu ) } @Theory - public void classesAndMethods( int cpu ) - throws TestSetFailedException + public void classesAndMethods( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classesAndMethods"); - properties.put(THREADCOUNTCLASSES_KEY, "5"); - properties.put(THREADCOUNTMETHODS_KEY, "15"); + properties.put( PARALLEL_KEY, "classesAndMethods" ); + properties.put( THREADCOUNTCLASSES_KEY, "5" ); + properties.put( THREADCOUNTMETHODS_KEY, "15" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -897,8 +869,8 @@ public void classesAndMethods( int cpu ) // Warning: this case works but is not enabled in AbstractSurefireMojo // Instead use the 'useUnlimitedThreads' parameter. properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "classesAndMethods"); - properties.put(THREADCOUNTCLASSES_KEY, "5"); + properties.put( PARALLEL_KEY, "classesAndMethods" ); + properties.put( THREADCOUNTCLASSES_KEY, "5" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertFalse( params.isParallelSuites() ); @@ -911,16 +883,15 @@ public void classesAndMethods( int cpu ) } @Theory - public void all( int cpu ) - throws TestSetFailedException + public void all( int cpu ) throws TestSetFailedException { ParallelComputerUtil.overrideAvailableProcessors( cpu ); Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "all"); - properties.put(THREADCOUNTSUITES_KEY, "5"); - properties.put(THREADCOUNTCLASSES_KEY, "15"); - properties.put(THREADCOUNTMETHODS_KEY, "30"); + properties.put( PARALLEL_KEY, "all" ); + properties.put( THREADCOUNTSUITES_KEY, "5" ); + properties.put( THREADCOUNTCLASSES_KEY, "15" ); + properties.put( THREADCOUNTMETHODS_KEY, "30" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); Concurrency concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -934,9 +905,9 @@ public void all( int cpu ) // Warning: these cases work but they are not enabled in AbstractSurefireMojo // Instead use the 'useUnlimitedThreads' parameter. properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "all"); - properties.put(THREADCOUNTSUITES_KEY, "5"); - properties.put(THREADCOUNTCLASSES_KEY, "15"); + properties.put( PARALLEL_KEY, "all" ); + properties.put( THREADCOUNTSUITES_KEY, "5" ); + properties.put( THREADCOUNTCLASSES_KEY, "15" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -948,8 +919,8 @@ public void all( int cpu ) assertThat( concurrency.methods, is( Integer.MAX_VALUE ) ); properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "all"); - properties.put(THREADCOUNTCLASSES_KEY, "15"); + properties.put( PARALLEL_KEY, "all" ); + properties.put( THREADCOUNTCLASSES_KEY, "15" ); params = new JUnitCoreParameters( properties ); concurrency = resolveConcurrency( params, null ); assertTrue( params.isParallelSuites() ); @@ -965,10 +936,10 @@ public void all( int cpu ) public void withoutShutdown() { Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(THREADCOUNTMETHODS_KEY, "2"); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( THREADCOUNTMETHODS_KEY, "2" ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); - ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params ); + ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( LOGGER, params ); ParallelComputer pc = pcBuilder.buildComputer(); final JUnitCore core = new JUnitCore(); final long t1 = systemMillis(); @@ -986,17 +957,16 @@ public void withoutShutdown() } @Test - public void shutdown() - throws TestSetFailedException + public void shutdown() throws TestSetFailedException { // The JUnitCore returns after 2.5s. // The test-methods in TestClass are NOT interrupted, and return normally after 5s. Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(THREADCOUNTMETHODS_KEY, "2"); - properties.put(PARALLEL_TIMEOUT_KEY, Double.toString( 2.5d )); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( THREADCOUNTMETHODS_KEY, "2" ); + properties.put( PARALLEL_TIMEOUT_KEY, Double.toString( 2.5d ) ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); - ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params ); + ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( LOGGER, params ); ParallelComputer pc = pcBuilder.buildComputer(); final JUnitCore core = new JUnitCore(); final long t1 = systemMillis(); @@ -1007,22 +977,21 @@ public void shutdown() assertEquals( 5000L, timeSpent, deltaTime ); String description = pc.describeElapsedTimeout(); - assertTrue( description.contains( "The test run has finished abruptly after timeout of 2.5 seconds.") ); - assertTrue( description.contains( "These tests were executed in prior to the shutdown operation:\n" - + TestClass.class.getName() ) ); + assertTrue( description.contains( "The test run has finished abruptly after timeout of 2.5 seconds." ) ); + assertTrue( description.contains( + "These tests were executed in prior to the shutdown operation:\n" + TestClass.class.getName() ) ); } @Test - public void forcedShutdown() - throws TestSetFailedException + public void forcedShutdown() throws TestSetFailedException { // The JUnitCore returns after 2.5s, and the test-methods in TestClass are interrupted. Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(THREADCOUNTMETHODS_KEY, "2"); - properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString( 2.5d )); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( THREADCOUNTMETHODS_KEY, "2" ); + properties.put( PARALLEL_TIMEOUTFORCED_KEY, Double.toString( 2.5d ) ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); - ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params ); + ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( LOGGER, params ); ParallelComputer pc = pcBuilder.buildComputer(); final JUnitCore core = new JUnitCore(); final long t1 = systemMillis(); @@ -1033,25 +1002,24 @@ public void forcedShutdown() assertEquals( 2500L, timeSpent, deltaTime ); String description = pc.describeElapsedTimeout(); - assertTrue( description.contains( "The test run has finished abruptly after timeout of 2.5 seconds.") ); - assertTrue( description.contains( "These tests were executed in prior to the shutdown operation:\n" - + TestClass.class.getName() ) ); + assertTrue( description.contains( "The test run has finished abruptly after timeout of 2.5 seconds." ) ); + assertTrue( description.contains( + "These tests were executed in prior to the shutdown operation:\n" + TestClass.class.getName() ) ); } @Test - public void timeoutAndForcedShutdown() - throws TestSetFailedException + public void timeoutAndForcedShutdown() throws TestSetFailedException { // The JUnitCore returns after 3.5s and the test-methods in TestClass are timed out after 2.5s. // No new test methods are scheduled for execution after 2.5s. // Interruption of test methods after 3.5s. Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(THREADCOUNTMETHODS_KEY, "2"); - properties.put(PARALLEL_TIMEOUT_KEY, Double.toString( 2.5d )); - properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString( 3.5d )); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( THREADCOUNTMETHODS_KEY, "2" ); + properties.put( PARALLEL_TIMEOUT_KEY, Double.toString( 2.5d ) ); + properties.put( PARALLEL_TIMEOUTFORCED_KEY, Double.toString( 3.5d ) ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); - ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params ); + ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( LOGGER, params ); ParallelComputer pc = pcBuilder.buildComputer(); final JUnitCore core = new JUnitCore(); final long t1 = systemMillis(); @@ -1062,23 +1030,22 @@ public void timeoutAndForcedShutdown() assertEquals( 3500L, timeSpent, deltaTime ); String description = pc.describeElapsedTimeout(); - assertTrue( description.contains( "The test run has finished abruptly after timeout of 2.5 seconds.") ); - assertTrue( description.contains( "These tests were executed in prior to the shutdown operation:\n" - + TestClass.class.getName() ) ); + assertTrue( description.contains( "The test run has finished abruptly after timeout of 2.5 seconds." ) ); + assertTrue( description.contains( + "These tests were executed in prior to the shutdown operation:\n" + TestClass.class.getName() ) ); } @Test - public void forcedTimeoutAndShutdown() - throws Exception + public void forcedTimeoutAndShutdown() throws Exception { // The JUnitCore returns after 3.5s and the test-methods in TestClass are interrupted after 3.5s. Map properties = new HashMap<>(); - properties.put(PARALLEL_KEY, "methods"); - properties.put(THREADCOUNTMETHODS_KEY, "2"); - properties.put(PARALLEL_TIMEOUTFORCED_KEY, Double.toString( 3.5d ) ); - properties.put(PARALLEL_TIMEOUT_KEY, Double.toString( 4.0d ) ); + properties.put( PARALLEL_KEY, "methods" ); + properties.put( THREADCOUNTMETHODS_KEY, "2" ); + properties.put( PARALLEL_TIMEOUTFORCED_KEY, Double.toString( 3.5d ) ); + properties.put( PARALLEL_TIMEOUT_KEY, Double.toString( 4.0d ) ); JUnitCoreParameters params = new JUnitCoreParameters( properties ); - ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( logger, params ); + ParallelComputerBuilder pcBuilder = new ParallelComputerBuilder( LOGGER, params ); ParallelComputer pc = pcBuilder.buildComputer(); final JUnitCore core = new JUnitCore(); final long t1 = systemMillis(); @@ -1089,16 +1056,18 @@ public void forcedTimeoutAndShutdown() assertEquals( 3500L, timeSpent, deltaTime ); String description = pc.describeElapsedTimeout(); - assertTrue( description.contains( "The test run has finished abruptly after timeout of 3.5 seconds.") ); - assertTrue( description.contains( "These tests were executed in prior to the shutdown operation:\n" - + TestClass.class.getName() ) ); + assertTrue( description.contains( "The test run has finished abruptly after timeout of 3.5 seconds." ) ); + assertTrue( description.contains( + "These tests were executed in prior to the shutdown operation:\n" + TestClass.class.getName() ) ); } + /** + * + */ public static class TestClass { @Test - public void a() - throws InterruptedException + public void a() throws InterruptedException { long t1 = systemMillis(); try @@ -1112,8 +1081,7 @@ public void a() } @Test - public void b() - throws InterruptedException + public void b() throws InterruptedException { long t1 = systemMillis(); try @@ -1127,8 +1095,7 @@ public void b() } @Test - public void c() - throws InterruptedException + public void c() throws InterruptedException { long t1 = systemMillis(); try diff --git a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java index 0f1ac1ad58..3aeab72dc8 100644 --- a/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java +++ b/surefire-providers/surefire-junit47/src/test/java/org/apache/maven/surefire/junitcore/pc/SchedulingStrategiesTest.java @@ -93,7 +93,7 @@ public void nonSharedPoolStrategy() assertTrue( task2.result ); } - @Test(expected = NullPointerException.class) + @Test( expected = NullPointerException.class ) public void sharedPoolStrategyNullPool() { SchedulingStrategies.createParallelSharedStrategy( logger, null ); diff --git a/surefire-providers/surefire-testng-utils/pom.xml b/surefire-providers/surefire-testng-utils/pom.xml index 9daca2e7e6..6bd657fb46 100644 --- a/surefire-providers/surefire-testng-utils/pom.xml +++ b/surefire-providers/surefire-testng-utils/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 surefire-testng-utils @@ -54,13 +54,31 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/GroupMatcherMethodSelector.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/GroupMatcherMethodSelector.java index e540569b02..3ba0ec1df2 100644 --- a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/GroupMatcherMethodSelector.java +++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/GroupMatcherMethodSelector.java @@ -19,19 +19,19 @@ * under the License. */ -import java.util.HashMap; -import java.util.List; -import java.util.Map; import org.apache.maven.surefire.group.match.AndGroupMatcher; import org.apache.maven.surefire.group.match.GroupMatcher; import org.apache.maven.surefire.group.match.InverseGroupMatcher; import org.apache.maven.surefire.group.parse.GroupMatcherParser; import org.apache.maven.surefire.group.parse.ParseException; - import org.testng.IMethodSelector; import org.testng.IMethodSelectorContext; import org.testng.ITestNGMethod; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Method selector delegating to {@link GroupMatcher} to decide if a method is included or not. * diff --git a/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/BaseClassSample.java b/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/BaseClassSample.java index f8b748e909..01487a05f5 100644 --- a/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/BaseClassSample.java +++ b/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/BaseClassSample.java @@ -19,6 +19,9 @@ * under the License. */ +/** + * + */ public abstract class BaseClassSample { public void baseClassMethodToBeIncluded() diff --git a/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/ChildClassSample.java b/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/ChildClassSample.java index dde19941ec..28d40c54ee 100644 --- a/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/ChildClassSample.java +++ b/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/ChildClassSample.java @@ -19,6 +19,9 @@ * under the License. */ +/** + * + */ public class ChildClassSample extends BaseClassSample { diff --git a/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/MethodSelectorTest.java b/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/MethodSelectorTest.java index 676ee05b1a..003e9f6969 100644 --- a/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/MethodSelectorTest.java +++ b/surefire-providers/surefire-testng-utils/src/test/java/testng/utils/MethodSelectorTest.java @@ -30,6 +30,9 @@ import java.lang.reflect.Method; +/** + * + */ public class MethodSelectorTest extends TestCase { diff --git a/surefire-providers/surefire-testng/pom.xml b/surefire-providers/surefire-testng/pom.xml index 49e75b6ea8..1ce2888498 100644 --- a/surefire-providers/surefire-testng/pom.xml +++ b/surefire-providers/surefire-testng/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire-providers - 3.0.0-M3 + 3.0.0-M4 surefire-testng @@ -59,13 +59,31 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin + + ${jvm.args.tests} ${jacoco.agent} + org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java index 82b9b90424..f4cc1b9a1f 100644 --- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java +++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGDirectoryTestSuite.java @@ -167,8 +167,8 @@ private static Class lookupClass( String className ) private void executeMulti( TestsToRun testsToRun, RunListener reporterManager ) throws TestSetFailedException { - List> testNgTestClasses = new ArrayList>(); - List> junitTestClasses = new ArrayList>(); + List> testNgTestClasses = new ArrayList<>(); + List> junitTestClasses = new ArrayList<>(); for ( Class testToRun : testsToRun ) { if ( isJUnitTest( testToRun ) ) diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGReporter.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGReporter.java index 19cd22d394..83c9d2b1b9 100644 --- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGReporter.java +++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGReporter.java @@ -25,6 +25,7 @@ import org.apache.maven.surefire.report.RunListener; import org.apache.maven.surefire.report.SimpleReportEntry; +import org.testng.IClass; import org.testng.ISuite; import org.testng.ISuiteListener; import org.testng.ITestContext; @@ -64,54 +65,46 @@ public TestNGReporter( RunListener reportManager ) @Override public void onTestStart( ITestResult result ) { - String group = groupString( result.getMethod().getGroups(), result.getTestClass().getName() ); - String userFriendlyTestName = getUserFriendlyTestName( result ); - reporter.testStarting( new CategorizedReportEntry( getSource( result ), userFriendlyTestName, group ) ); - } - - private String getSource( ITestResult result ) - { - return result.getTestClass().getName(); + String clazz = result.getTestClass().getName(); + String group = groupString( result.getMethod().getGroups(), clazz ); + reporter.testStarting( new CategorizedReportEntry( clazz, result.getName(), group ) ); } @Override public void onTestSuccess( ITestResult result ) { - ReportEntry report = new SimpleReportEntry( getSource( result ), getUserFriendlyTestName( result ) ); + ReportEntry report = new SimpleReportEntry( result.getTestClass().getName(), null, result.getName(), null ); reporter.testSucceeded( report ); } @Override public void onTestFailure( ITestResult result ) { - ReportEntry report = withException( getSource( result ), getUserFriendlyTestName( result ), - new PojoStackTraceWriter( result.getTestClass().getRealClass().getName(), + IClass clazz = result.getTestClass(); + ReportEntry report = withException( clazz.getName(), null, result.getName(), null, + new PojoStackTraceWriter( clazz.getRealClass().getName(), result.getMethod().getMethodName(), result.getThrowable() ) ); reporter.testFailed( report ); } - private static String getUserFriendlyTestName( ITestResult result ) - { - // This is consistent with the JUnit output - return result.getName() + "(" + result.getTestClass().getName() + ")"; - } - @Override public void onTestSkipped( ITestResult result ) { + //noinspection ThrowableResultOfMethodCallIgnored Throwable t = result.getThrowable(); String reason = t == null ? null : t.getMessage(); - ReportEntry report = ignored( getSource( result ), getUserFriendlyTestName( result ), reason ); + ReportEntry report = ignored( result.getTestClass().getName(), null, result.getName(), null, reason ); reporter.testSkipped( report ); } @Override public void onTestFailedButWithinSuccessPercentage( ITestResult result ) { - ReportEntry report = withException( getSource( result ), getUserFriendlyTestName( result ), - new PojoStackTraceWriter( result.getTestClass().getRealClass().getName(), + IClass clazz = result.getTestClass(); + ReportEntry report = withException( clazz.getName(), null, result.getName(), null, + new PojoStackTraceWriter( clazz.getRealClass().getName(), result.getMethod().getMethodName(), result.getThrowable() ) ); diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestSuite.java index ca40f7c764..27f46be175 100644 --- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestSuite.java +++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestSuite.java @@ -35,7 +35,7 @@ abstract class TestSuite { abstract Map getOptions(); - final String getSuiteName() + private String getSuiteName() { String result = getOptions().get( "suitename" ); return result == null ? "TestSuite" : result; @@ -43,7 +43,7 @@ final String getSuiteName() final void startTestSuite( RunListener reporterManager ) { - TestSetReportEntry report = new SimpleReportEntry( getClass().getName(), getSuiteName(), systemProps() ); + TestSetReportEntry report = new SimpleReportEntry( getSuiteName(), null, null, null ); try { @@ -57,7 +57,7 @@ final void startTestSuite( RunListener reporterManager ) final void finishTestSuite( RunListener reporterManager ) { - SimpleReportEntry report = new SimpleReportEntry( getClass().getName(), getSuiteName(), systemProps() ); + SimpleReportEntry report = new SimpleReportEntry( getSuiteName(), null, null, null, systemProps() ); reporterManager.testSetCompleted( report ); } } diff --git a/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG513ConfiguratorTest.java b/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG513ConfiguratorTest.java index bbbe40dd5c..15d976d729 100644 --- a/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG513ConfiguratorTest.java +++ b/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG513ConfiguratorTest.java @@ -29,6 +29,9 @@ import static org.apache.maven.surefire.testng.conf.TestNGMapConfiguratorTest.LISTENER_PROP; import static org.apache.maven.surefire.testng.conf.TestNGMapConfiguratorTest.SECOND_LISTENER; +/** + * + */ public class TestNG513ConfiguratorTest extends TestCase { diff --git a/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG5141ConfiguratorTest.java b/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG5141ConfiguratorTest.java index 54d1eb739f..763a4a1dc9 100644 --- a/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG5141ConfiguratorTest.java +++ b/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG5141ConfiguratorTest.java @@ -26,22 +26,24 @@ import java.util.List; import java.util.Map; -import static org.apache.maven.surefire.testng.conf.TestNGMapConfiguratorTest.*; +import static org.apache.maven.surefire.testng.conf.TestNGMapConfiguratorTest.FIRST_LISTENER; +import static org.apache.maven.surefire.testng.conf.TestNGMapConfiguratorTest.LISTENER_PROP; +import static org.apache.maven.surefire.testng.conf.TestNGMapConfiguratorTest.SECOND_LISTENER; -public class TestNG5141ConfiguratorTest - extends TestCase +/** + * + */ +public class TestNG5141ConfiguratorTest extends TestCase { public void testListenersOnSeparateLines() - throws Exception { try { - String listenersOnSeveralLines = String.format("%s , %n %s", - FIRST_LISTENER, SECOND_LISTENER); - Map convertedOptions = getConvertedOptions(LISTENER_PROP, listenersOnSeveralLines); - List listeners = (List) convertedOptions.get(String.format("-%s", LISTENER_PROP)); - assertEquals(2, listeners.size()); + String listenersOnSeveralLines = String.format( "%s , %n %s", FIRST_LISTENER, SECOND_LISTENER ); + Map convertedOptions = getConvertedOptions( LISTENER_PROP, listenersOnSeveralLines ); + List listeners = (List) convertedOptions.get( String.format( "-%s", LISTENER_PROP ) ); + assertEquals( 2, listeners.size() ); fail(); } catch ( TestSetFailedException e ) @@ -51,14 +53,13 @@ public void testListenersOnSeparateLines() } public void testListenersOnTheSameLine() - throws Exception { - try { - String listenersOnSeveralLines = String.format("%s,%s", - FIRST_LISTENER, SECOND_LISTENER); - Map convertedOptions = getConvertedOptions(LISTENER_PROP, listenersOnSeveralLines); - List listeners = (List) convertedOptions.get(String.format("-%s", LISTENER_PROP)); - assertEquals(2, listeners.size()); + try + { + String listenersOnSeveralLines = String.format( "%s,%s", FIRST_LISTENER, SECOND_LISTENER ); + Map convertedOptions = getConvertedOptions( LISTENER_PROP, listenersOnSeveralLines ); + List listeners = (List) convertedOptions.get( String.format( "-%s", LISTENER_PROP ) ); + assertEquals( 2, listeners.size() ); fail(); } catch ( TestSetFailedException e ) @@ -67,8 +68,7 @@ public void testListenersOnTheSameLine() } } - private Map getConvertedOptions( String key, String value ) - throws TestSetFailedException + private Map getConvertedOptions( String key, String value ) throws TestSetFailedException { TestNGMapConfigurator testNGMapConfigurator = new TestNG5141Configurator(); Map raw = new HashMap<>(); diff --git a/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG5143ConfiguratorTest.java b/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG5143ConfiguratorTest.java index 34f46b1ddd..a6704be562 100644 --- a/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG5143ConfiguratorTest.java +++ b/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNG5143ConfiguratorTest.java @@ -29,40 +29,36 @@ import static org.apache.maven.surefire.testng.conf.TestNGMapConfiguratorTest.LISTENER_PROP; import static org.apache.maven.surefire.testng.conf.TestNGMapConfiguratorTest.SECOND_LISTENER; -public class TestNG5143ConfiguratorTest - extends TestCase +/** + * + */ +public class TestNG5143ConfiguratorTest extends TestCase { - public void testListenersOnSeparateLines() - throws Exception + public void testListenersOnSeparateLines() throws Exception { - String listenersOnSeveralLines = String.format( "%s , %n %s", - FIRST_LISTENER, SECOND_LISTENER); - Map convertedOptions = getConvertedOptions(LISTENER_PROP, listenersOnSeveralLines); - String listeners = (String) convertedOptions.get( String.format("-%s", LISTENER_PROP)); - assertEquals(FIRST_LISTENER + "," + SECOND_LISTENER, listeners); + String listenersOnSeveralLines = String.format( "%s , %n %s", FIRST_LISTENER, SECOND_LISTENER ); + Map convertedOptions = getConvertedOptions( LISTENER_PROP, listenersOnSeveralLines ); + String listeners = (String) convertedOptions.get( String.format( "-%s", LISTENER_PROP ) ); + assertEquals( FIRST_LISTENER + "," + SECOND_LISTENER, listeners ); } - public void testListenersOnTheSameLine() - throws Exception + public void testListenersOnTheSameLine() throws Exception { - String listenersOnSeveralLines = String.format( "%s,%s", - FIRST_LISTENER, SECOND_LISTENER); - Map convertedOptions = getConvertedOptions( LISTENER_PROP, listenersOnSeveralLines); - String listeners = (String) convertedOptions.get( String.format("-%s", LISTENER_PROP)); - assertEquals(FIRST_LISTENER + "," + SECOND_LISTENER, listeners); + String listenersOnSeveralLines = String.format( "%s,%s", FIRST_LISTENER, SECOND_LISTENER ); + Map convertedOptions = getConvertedOptions( LISTENER_PROP, listenersOnSeveralLines ); + String listeners = (String) convertedOptions.get( String.format( "-%s", LISTENER_PROP ) ); + assertEquals( FIRST_LISTENER + "," + SECOND_LISTENER, listeners ); } - public void testReporter() - throws Exception + public void testReporter() throws Exception { Map convertedOptions = getConvertedOptions( "reporter", "classname" ); assertNull( "classname", convertedOptions.get( "-reporterslist" ) ); - String reporter = (String) convertedOptions.get("-reporter" ); + String reporter = (String) convertedOptions.get( "-reporter" ); assertEquals( "classname", reporter ); } - private Map getConvertedOptions( String key, String value ) - throws TestSetFailedException + private Map getConvertedOptions( String key, String value ) throws TestSetFailedException { TestNGMapConfigurator testNGMapConfigurator = new TestNG5143Configurator(); Map raw = new HashMap<>(); diff --git a/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNGMapConfiguratorTest.java b/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNGMapConfiguratorTest.java index 60a6b3751e..69cd8e5635 100755 --- a/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNGMapConfiguratorTest.java +++ b/surefire-providers/surefire-testng/src/test/java/org/apache/maven/surefire/testng/conf/TestNGMapConfiguratorTest.java @@ -31,51 +31,43 @@ /** * @author Kristian Rosenvold */ -public class TestNGMapConfiguratorTest - extends TestCase +public class TestNGMapConfiguratorTest extends TestCase { public static final String FIRST_LISTENER = "org.testng.TestListenerAdapter"; public static final String SECOND_LISTENER = "org.testng.reporters.ExitCodeListener"; public static final String LISTENER_PROP = "listener"; - public void testGetConvertedOptions() - throws Exception + public void testGetConvertedOptions() throws Exception { Map convertedOptions = getConvertedOptions( "mixed", "true" ); boolean bool = (Boolean) convertedOptions.get( "-mixed" ); assertTrue( bool ); } - public void testListenersOnSeparateLines() - throws Exception + public void testListenersOnSeparateLines() throws Exception { - String listenersOnSeveralLines = String.format( "%s , %n %s", - FIRST_LISTENER, SECOND_LISTENER); - Map convertedOptions = getConvertedOptions(LISTENER_PROP, listenersOnSeveralLines); - List listeners = (List) convertedOptions.get( String.format("-%s", LISTENER_PROP)); - assertEquals(2, listeners.size()); + String listenersOnSeveralLines = String.format( "%s , %n %s", FIRST_LISTENER, SECOND_LISTENER ); + Map convertedOptions = getConvertedOptions( LISTENER_PROP, listenersOnSeveralLines ); + List listeners = (List) convertedOptions.get( String.format( "-%s", LISTENER_PROP ) ); + assertEquals( 2, listeners.size() ); } - public void testListenersOnTheSameLine() - throws Exception + public void testListenersOnTheSameLine() throws Exception { - String listenersOnSeveralLines = String.format( "%s,%s", - FIRST_LISTENER, SECOND_LISTENER); - Map convertedOptions = getConvertedOptions( LISTENER_PROP, listenersOnSeveralLines); - List listeners = (List) convertedOptions.get( String.format("-%s", LISTENER_PROP)); - assertEquals(2, listeners.size()); + String listenersOnSeveralLines = String.format( "%s,%s", FIRST_LISTENER, SECOND_LISTENER ); + Map convertedOptions = getConvertedOptions( LISTENER_PROP, listenersOnSeveralLines ); + List listeners = (List) convertedOptions.get( String.format( "-%s", LISTENER_PROP ) ); + assertEquals( 2, listeners.size() ); } - public void testGroupByInstances() - throws Exception + public void testGroupByInstances() throws Exception { Map convertedOptions = getConvertedOptions( "group-by-instances", "true" ); boolean bool = (Boolean) convertedOptions.get( "-group-by-instances" ); assertTrue( bool ); } - public void testReporter() - throws Exception + public void testReporter() throws Exception { Map convertedOptions = getConvertedOptions( "reporter", "classname" ); List reporter = (List) convertedOptions.get( "-reporterslist" ); @@ -83,8 +75,7 @@ public void testReporter() assertEquals( "classname", reporterConfig.getClassName() ); } - private Map getConvertedOptions( String key, String value ) - throws TestSetFailedException + private Map getConvertedOptions( String key, String value ) throws TestSetFailedException { TestNGMapConfigurator testNGMapConfigurator = new TestNGMapConfigurator(); Map raw = new HashMap<>(); diff --git a/surefire-report-parser/pom.xml b/surefire-report-parser/pom.xml index 36cfbea07c..cb0de886bc 100644 --- a/surefire-report-parser/pom.xml +++ b/surefire-report-parser/pom.xml @@ -24,7 +24,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 surefire-report-parser @@ -32,10 +32,6 @@ Surefire Report Parser Parses report output files from surefire. - - 3.0 - - org.apache.maven.surefire @@ -53,16 +49,32 @@ + + org.jacoco + jacoco-maven-plugin + + + jacoco-agent + + prepare-agent + + + + + jacoco.agent + + maven-surefire-plugin org.apache.maven.surefire surefire-shadefire - 3.0.0-M2 + 3.0.0-M3 + ${jvm.args.tests} ${jacoco.agent} **/JUnit4SuiteTest.java @@ -85,8 +97,8 @@ - org.apache.maven.shared - org.apache.maven.surefire.shade.report.org.apache.maven.shared + org.apache.maven.shared.utils + org.apache.maven.surefire.shade.report.org.apache.maven.shared.utils diff --git a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java index da1b255855..f6e644ff74 100644 --- a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java +++ b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java @@ -33,11 +33,10 @@ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; import org.apache.maven.reporting.MavenReportException; -import org.apache.maven.shared.utils.StringUtils; import org.apache.maven.shared.utils.io.DirectoryScanner; import org.xml.sax.SAXException; -import static java.util.Collections.singletonList; +import static org.apache.maven.shared.utils.StringUtils.split; /** * @@ -57,7 +56,7 @@ public final class SurefireReportParser private final ConsoleLogger consoleLogger; - private List reportsDirectories; + private final List reportsDirectories; public SurefireReportParser( List reportsDirectories, Locale locale, ConsoleLogger consoleLogger ) { @@ -104,21 +103,6 @@ public List parseXMLReportFiles() return testSuites; } - protected String parseTestSuiteName( String lineString ) - { - return lineString.substring( lineString.lastIndexOf( "." ) + 1, lineString.length() ); - } - - protected String parseTestSuitePackageName( String lineString ) - { - return lineString.substring( lineString.indexOf( ":" ) + 2, lineString.lastIndexOf( "." ) ); - } - - protected String parseTestCaseName( String lineString ) - { - return lineString.substring( 0, lineString.indexOf( "(" ) ); - } - public Map getSummary( List suites ) { Map totalSummary = new HashMap<>(); @@ -164,11 +148,6 @@ public Map getSummary( List suites ) return totalSummary; } - public void setReportsDirectory( File reportsDirectory ) - { - reportsDirectories = singletonList( reportsDirectory ); - } - public NumberFormat getNumberFormat() { return numberFormat; @@ -238,9 +217,9 @@ private static String[] getIncludedFiles( File directory, String includes, Strin scanner.setBasedir( directory ); - scanner.setIncludes( StringUtils.split( includes, "," ) ); + scanner.setIncludes( split( includes, "," ) ); - scanner.setExcludes( StringUtils.split( excludes, "," ) ); + scanner.setExcludes( split( excludes, "," ) ); scanner.scan(); diff --git a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/JUnit4SuiteTest.java b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/JUnit4SuiteTest.java index 142ca9d7e3..8c143dd284 100644 --- a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/JUnit4SuiteTest.java +++ b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/JUnit4SuiteTest.java @@ -21,8 +21,8 @@ import junit.framework.JUnit4TestAdapter; import junit.framework.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; +import junit.framework.TestCase; +import junit.framework.TestSuite; /** * Adapt the JUnit4 tests which use only annotations to the JUnit3 test suite. @@ -30,17 +30,15 @@ * @author Tibor Digana (tibor17) * @since 2.21.0 */ -@Suite.SuiteClasses( { - ReportTestCaseTest.class, - ReportTestSuiteTest.class, - SurefireReportParserTest.class, - TestSuiteXmlParserTest.class -} ) -@RunWith( Suite.class ) -public class JUnit4SuiteTest +public class JUnit4SuiteTest extends TestCase { public static Test suite() { - return new JUnit4TestAdapter( JUnit4SuiteTest.class ); + TestSuite suite = new TestSuite(); + suite.addTestSuite( ReportTestCaseTest.class ); + suite.addTestSuite( ReportTestSuiteTest.class ); + suite.addTestSuite( SurefireReportParserTest.class ); + suite.addTest( new JUnit4TestAdapter( TestSuiteXmlParserTest.class ) ); + return suite; } } diff --git a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java index ce7f2f375c..6ca030ed36 100644 --- a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java +++ b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java @@ -24,6 +24,7 @@ /** * @author Jontri */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class ReportTestCaseTest extends TestCase { diff --git a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java index f454bc8c1e..8109da493e 100644 --- a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java +++ b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java @@ -27,6 +27,7 @@ /** * */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class ReportTestSuiteTest extends TestCase { diff --git a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java index 870cd92048..8bc9f1c3bc 100644 --- a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java +++ b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java @@ -29,35 +29,24 @@ import java.util.Map; import org.apache.maven.plugin.surefire.log.api.NullConsoleLogger; -import org.apache.maven.reporting.MavenReportException; import junit.framework.TestCase; +import static java.util.Collections.singletonList; import static java.util.Locale.ENGLISH; /** * */ +@SuppressWarnings( "checkstyle:magicnumber" ) public class SurefireReportParserTest extends TestCase { - private SurefireReportParser report; - - /** - * {@inheritDoc} - */ - @Override - protected void setUp() - throws Exception - { - super.setUp(); - report = new SurefireReportParser( null, ENGLISH, new NullConsoleLogger() ); - } - public void testParseXMLReportFiles() - throws MavenReportException, UnsupportedEncodingException + throws Exception { - report.setReportsDirectory( getTestDir() ); + SurefireReportParser report = + new SurefireReportParser( singletonList( getTestDir() ), ENGLISH, new NullConsoleLogger() ); List suites = report.parseXMLReportFiles(); @@ -79,21 +68,6 @@ private File getTestDir() return new File( URLDecoder.decode( resource.getPath(), "UTF-8" ) ).getAbsoluteFile(); } - public void testParseTestSuiteName() - { - assertEquals( "CircleTest", report.parseTestSuiteName( "Battery: com.shape.CircleTest" ) ); - } - - public void testParseTestSuitePackageName() - { - assertEquals( "com.shape", report.parseTestSuitePackageName( "Battery: com.shape.CircleTest" ) ); - } - - public void testParseTestCaseName() - { - assertEquals( "testCase", report.parseTestCaseName( "testCase(com.shape.CircleTest)" ) ); - } - public void testGetSummary() throws Exception { @@ -117,6 +91,8 @@ public void testGetSummary() suites.add( tSuite2 ); + SurefireReportParser report = new SurefireReportParser( null, ENGLISH, new NullConsoleLogger() ); + Map testMap = report.getSummary( suites ); assertEquals( 20, Integer.parseInt( testMap.get( "totalErrors" ) ) ); @@ -156,6 +132,8 @@ public void testGetSuitesGroupByPackage() suites.add( tSuite3 ); + SurefireReportParser report = new SurefireReportParser( null, ENGLISH, new NullConsoleLogger() ); + Map> groupMap = report.getSuitesGroupByPackage( suites ); assertEquals( 2, groupMap.size() ); @@ -170,6 +148,7 @@ public void testGetSuitesGroupByPackage() public void testComputePercentage() throws Exception { + SurefireReportParser report = new SurefireReportParser( null, ENGLISH, new NullConsoleLogger() ); NumberFormat numberFormat = report.getNumberFormat(); assertEquals( 70.00f, numberFormat.parse( report.computePercentage( 100, 20, 10, 0 ) ).floatValue(), 0 ); @@ -211,6 +190,8 @@ public void testGetFailureDetails() suites.add( tSuite2 ); + SurefireReportParser report = new SurefireReportParser( null, ENGLISH, new NullConsoleLogger() ); + List failures = report.getFailureDetails( suites ); assertEquals( 2, failures.size() ); diff --git a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java index d79fe64a61..9a7ada80df 100644 --- a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java +++ b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java @@ -32,17 +32,24 @@ import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertFalse; import static org.junit.Assume.assumeTrue; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; import static org.hamcrest.MatcherAssert.assertThat; /** * @author Kristian Rosenvold */ +@SuppressWarnings( { "checkstyle:magicnumber", "checkstyle:linelength" } ) public class TestSuiteXmlParserTest { - private static final String[] linePatterns = { "at org.apache.Test.", "at org.apache.Test$" }; + private static final String[] LINE_PATTERNS = {"at org.apache.Test.", "at org.apache.Test$"}; private final Collection loggedErrors = new ArrayList<>(); @@ -120,48 +127,41 @@ public void verifyErrorFreeLogger() } @Test - public void testParse() - throws Exception + public void testParse() throws Exception { TestSuiteXmlParser testSuiteXmlParser = new TestSuiteXmlParser( consoleLogger ); - String xml = "\n" + - "\n" - + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " junit.framework.AssertionFailedError: \n" - + - "\tat junit.framework.Assert.fail(Assert.java:47)\n" + - "\tat wellFormedXmlFailures.TestSurefire3.testU0000(TestSurefire3.java:40)\n" + - "\n" + - " \n" + - " \n" + - " junit.framework.AssertionFailedError: >\n" - + - "\tat junit.framework.Assert.fail(Assert.java:47)\n" + - "\tat wellFormedXmlFailures.TestSurefire3.testGreater(TestSurefire3.java:35)\n" + - "\n" + - " \n" + - " \n" + - " junit.framework.AssertionFailedError: \"\n" - + - "\tat junit.framework.Assert.fail(Assert.java:47)\n" + - "\tat wellFormedXmlFailures.TestSurefire3.testQuote(TestSurefire3.java:25)\n" + - "\n" + - " \n" + - ""; + String xml = "\n" + + "\n" + + " \n" + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " junit.framework.AssertionFailedError: \n" + + "\tat junit.framework.Assert.fail(Assert.java:47)\n" + + "\tat wellFormedXmlFailures.TestSurefire3.testU0000(TestSurefire3.java:40)\n" + + "\n" + + " \n" + + " \n" + + " junit.framework.AssertionFailedError: >\n" + + "\tat junit.framework.Assert.fail(Assert.java:47)\n" + + "\tat wellFormedXmlFailures.TestSurefire3.testGreater(TestSurefire3.java:35)\n" + + "\n" + + " \n" + + " \n" + + " junit.framework.AssertionFailedError: \"\n" + + "\tat junit.framework.Assert.fail(Assert.java:47)\n" + + "\tat wellFormedXmlFailures.TestSurefire3.testQuote(TestSurefire3.java:25)\n" + + "\n" + + " \n" + + ""; InputStream byteArrayIs = new ByteArrayInputStream( xml.getBytes() ); - List parse = testSuiteXmlParser.parse( new InputStreamReader(byteArrayIs, "UTF-8") ); + List parse = testSuiteXmlParser.parse( new InputStreamReader( byteArrayIs, UTF_8 ) ); assertThat( parse.size(), is( 1 ) ); ReportTestSuite report = parse.get( 0 ); assertThat( report.getFullClassName(), is( "wellFormedXmlFailures.TestSurefire3" ) ); @@ -179,9 +179,9 @@ public void testParse() assertThat( tests.get( 0 ).getFullClassName(), is( "wellFormedXmlFailures.TestSurefire3" ) ); assertThat( tests.get( 0 ).getName(), is( "testLower" ) ); assertThat( tests.get( 0 ).getFailureDetail(), - is( "junit.framework.AssertionFailedError: <\n" - + "\tat junit.framework.Assert.fail(Assert.java:47)\n" - + "\tat wellFormedXmlFailures.TestSurefire3.testLower(TestSurefire3.java:30)\n" ) ); + is( "junit.framework.AssertionFailedError: <\n" + + "\tat junit.framework.Assert.fail(Assert.java:47)\n" + + "\tat wellFormedXmlFailures.TestSurefire3.testLower(TestSurefire3.java:30)\n" ) ); assertThat( tests.get( 0 ).getClassName(), is( "TestSurefire3" ) ); assertThat( tests.get( 0 ).getTime(), is( 0.005f ) ); assertThat( tests.get( 0 ).getFailureErrorLine(), is( "30" ) ); @@ -193,9 +193,8 @@ public void testParse() assertThat( tests.get( 1 ).getFullClassName(), is( "wellFormedXmlFailures.TestSurefire3" ) ); assertThat( tests.get( 1 ).getName(), is( "testU0000" ) ); assertThat( tests.get( 1 ).getFailureDetail(), - is( "junit.framework.AssertionFailedError: \n" - + "\tat junit.framework.Assert.fail(Assert.java:47)\n" - + "\tat wellFormedXmlFailures.TestSurefire3.testU0000(TestSurefire3.java:40)\n" ) ); + is( "junit.framework.AssertionFailedError: \n" + "\tat junit.framework.Assert.fail(Assert.java:47)\n" + + "\tat wellFormedXmlFailures.TestSurefire3.testU0000(TestSurefire3.java:40)\n" ) ); assertThat( tests.get( 1 ).getClassName(), is( "TestSurefire3" ) ); assertThat( tests.get( 1 ).getTime(), is( 0f ) ); assertThat( tests.get( 1 ).getFailureErrorLine(), is( "40" ) ); @@ -207,9 +206,8 @@ public void testParse() assertThat( tests.get( 2 ).getFullClassName(), is( "wellFormedXmlFailures.TestSurefire3" ) ); assertThat( tests.get( 2 ).getName(), is( "testGreater" ) ); assertThat( tests.get( 2 ).getFailureDetail(), - is( "junit.framework.AssertionFailedError: >\n" - + "\tat junit.framework.Assert.fail(Assert.java:47)\n" - + "\tat wellFormedXmlFailures.TestSurefire3.testGreater(TestSurefire3.java:35)\n" ) ); + is( "junit.framework.AssertionFailedError: >\n" + "\tat junit.framework.Assert.fail(Assert.java:47)\n" + + "\tat wellFormedXmlFailures.TestSurefire3.testGreater(TestSurefire3.java:35)\n" ) ); assertThat( tests.get( 2 ).getClassName(), is( "TestSurefire3" ) ); assertThat( tests.get( 2 ).getTime(), is( 0f ) ); assertThat( tests.get( 2 ).getFailureErrorLine(), is( "35" ) ); @@ -221,9 +219,8 @@ public void testParse() assertThat( tests.get( 3 ).getFullClassName(), is( "wellFormedXmlFailures.TestSurefire3" ) ); assertThat( tests.get( 3 ).getName(), is( "testQuote" ) ); assertThat( tests.get( 3 ).getFailureDetail(), - is( "junit.framework.AssertionFailedError: \"\n" - + "\tat junit.framework.Assert.fail(Assert.java:47)\n" - + "\tat wellFormedXmlFailures.TestSurefire3.testQuote(TestSurefire3.java:25)\n" ) ); + is( "junit.framework.AssertionFailedError: \"\n" + "\tat junit.framework.Assert.fail(Assert.java:47)\n" + + "\tat wellFormedXmlFailures.TestSurefire3.testQuote(TestSurefire3.java:25)\n" ) ); assertThat( tests.get( 3 ).getClassName(), is( "TestSurefire3" ) ); assertThat( tests.get( 3 ).getTime(), is( 0f ) ); assertThat( tests.get( 3 ).getFailureErrorLine(), is( "25" ) ); @@ -234,13 +231,12 @@ public void testParse() } @Test - public void testParser() - throws Exception + public void testParser() throws Exception { TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger ); Collection oldResult = parser.parse( - "src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.FailingTest.xml" ); + "src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.FailingTest.xml" ); assertNotNull( oldResult ); @@ -250,8 +246,7 @@ public void testParser() } @Test - public void successfulSurefireTestReport() - throws Exception + public void successfulSurefireTestReport() throws Exception { TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger ); File surefireReport = new File( "src/test/resources/junit-pathWithÜmlaut/TEST-umlautTest.BasicTest.xml" ); @@ -283,8 +278,7 @@ public void successfulSurefireTestReport() } @Test - public void testParserHitsFailsafeSummary() - throws Exception + public void testParserHitsFailsafeSummary() throws Exception { TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger ); @@ -293,7 +287,7 @@ public void testParserHitsFailsafeSummary() assertFalse( parser.isValid() ); parser.parse( - "src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.FailingTest.xml" ); + "src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.FailingTest.xml" ); assertTrue( parser.isValid() ); } @@ -302,11 +296,10 @@ public void testParserHitsFailsafeSummary() public void lastIndexOfPatternOfOrdinalTest() { final StringBuilder stackTrace = new StringBuilder( - "\tat org.apache.Test.util(Test.java:60)\n" - + "\tat org.apache.Test.test(Test.java:30)\n" - + "\tat com.sun.Impl.xyz(Impl.java:258)\n" ); + "\tat org.apache.Test.util(Test.java:60)\n" + "\tat org.apache.Test.test(Test.java:30)\n" + + "\tat com.sun.Impl.xyz(Impl.java:258)\n" ); - int[] result = TestSuiteXmlParser.lastIndexOf( stackTrace, linePatterns ); + int[] result = TestSuiteXmlParser.lastIndexOf( stackTrace, LINE_PATTERNS ); assertThat( result[0], is( 40 ) ); assertThat( result[1], is( 0 ) ); String errorLine = TestSuiteXmlParser.parseErrorLine( stackTrace, "org.apache.Test" ); @@ -317,13 +310,12 @@ public void lastIndexOfPatternOfOrdinalTest() public void lastIndexOfPatternOfOrdinalTestWithCause() { final StringBuilder stackTrace = new StringBuilder( - "\tat org.apache.Test.util(Test.java:60)\n" - + "\tat org.apache.Test.test(Test.java:30)\n" - + "\tat com.sun.Impl.xyz(Impl.java:258)\n" - + "\tat Caused by: java.lang.IndexOutOfBoundsException\n" - + "\tat org.apache.Test.util(Test.java:70)\n" ); + "\tat org.apache.Test.util(Test.java:60)\n" + "\tat org.apache.Test.test(Test.java:30)\n" + + "\tat com.sun.Impl.xyz(Impl.java:258)\n" + + "\tat Caused by: java.lang.IndexOutOfBoundsException\n" + + "\tat org.apache.Test.util(Test.java:70)\n" ); - int[] result = TestSuiteXmlParser.lastIndexOf( stackTrace, linePatterns ); + int[] result = TestSuiteXmlParser.lastIndexOf( stackTrace, LINE_PATTERNS ); assertThat( result[0], is( 40 ) ); assertThat( result[1], is( 0 ) ); String errorLine = TestSuiteXmlParser.parseErrorLine( stackTrace, "org.apache.Test" ); @@ -334,11 +326,11 @@ public void lastIndexOfPatternOfOrdinalTestWithCause() public void lastIndexOfPatternOfEnclosedTest() { final StringBuilder source = new StringBuilder( - "\tat org.apache.Test.util(Test.java:60)\n" - + "\tat org.apache.Test$Nested.test(Test.java:30)\n" - + "\tat com.sun.Impl.xyz(Impl.java:258)\n" ); + "\tat org.apache.Test.util(Test.java:60)\n" + + "\tat org.apache.Test$Nested.test(Test.java:30)\n" + + "\tat com.sun.Impl.xyz(Impl.java:258)\n" ); - int[] result = TestSuiteXmlParser.lastIndexOf( source, linePatterns ); + int[] result = TestSuiteXmlParser.lastIndexOf( source, LINE_PATTERNS ); assertThat( result[0], is( 40 ) ); assertThat( result[1], is( 1 ) ); String errorLine = TestSuiteXmlParser.parseErrorLine( source, "org.apache.Test$Nested" ); @@ -349,13 +341,12 @@ public void lastIndexOfPatternOfEnclosedTest() public void lastIndexOfPatternOfEnclosedTestWithCause() { final StringBuilder source = new StringBuilder( - "\tat org.apache.Test.util(Test.java:60)\n" - + "\tat org.apache.Test$Nested.test(Test.java:30)\n" - + "\tat com.sun.Impl.xyz(Impl.java:258)\n" - + "\tat Caused by: java.lang.IndexOutOfBoundsException\n" - + "\tat org.apache.Test$Nested.util(Test.java:70)\n" ); + "\tat org.apache.Test.util(Test.java:60)\n" + "\tat org.apache.Test$Nested.test(Test.java:30)\n" + + "\tat com.sun.Impl.xyz(Impl.java:258)\n" + + "\tat Caused by: java.lang.IndexOutOfBoundsException\n" + + "\tat org.apache.Test$Nested.util(Test.java:70)\n" ); - int[] result = TestSuiteXmlParser.lastIndexOf( source, linePatterns ); + int[] result = TestSuiteXmlParser.lastIndexOf( source, LINE_PATTERNS ); assertThat( result[0], is( 40 ) ); assertThat( result[1], is( 1 ) ); String errorLine = TestSuiteXmlParser.parseErrorLine( source, "org.apache.Test$Nested" ); @@ -363,12 +354,11 @@ public void lastIndexOfPatternOfEnclosedTestWithCause() } @Test - public void shouldParserEverythingInOrdinalTest() - throws Exception + public void shouldParserEverythingInOrdinalTest() throws Exception { TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger ); - List tests = - parser.parse( "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest.xml" ); + List tests = parser.parse( + "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest.xml" ); assertTrue( parser.isValid() ); assertThat( tests.size(), is( 1 ) ); assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest" ) ); @@ -390,50 +380,48 @@ public void shouldParserEverythingInOrdinalTest() assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(), is( "this is different message" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(), - is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n" - + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" - + "\tat surefire.MyTest.test(MyTest.java:13)\n" - + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" - + "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n" - + "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" - + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n" - + "\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n" - + "\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n" - + "\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n" - + "\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n" - + "\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n" - + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n" - + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n" - + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n" - + "\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n" - + "\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n" - + "\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n" - + "\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n" - + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n" - + "\tCaused by: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.failure(MyTest.java:33)\n" - + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" - + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" - + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) ); + is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n" + + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" + + "\tat surefire.MyTest.test(MyTest.java:13)\n" + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n" + + "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" + + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n" + + "\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n" + + "\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n" + + "\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n" + + "\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n" + + "\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n" + + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n" + + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n" + + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n" + + "\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n" + + "\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n" + + "\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n" + + "\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n" + + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n" + + "\tCaused by: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.failure(MyTest.java:33)\n" + + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" + + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" + + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).hasError(), is( true ) ); } @Test - public void shouldParserEverythingInEnclosedTest() - throws Exception + public void shouldParserEverythingInEnclosedTest() throws Exception { TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger ); - List tests = - parser.parse( "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed.xml" ); + List tests = parser.parse( + "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed.xml" ); assertTrue( parser.isValid() ); assertThat( tests.size(), is( 1 ) ); assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest$A" ) ); @@ -446,8 +434,7 @@ public void shouldParserEverythingInEnclosedTest() assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) ); assertFalse( tests.get( 0 ).getTestCases().get( 0 ).isSuccessful() ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureErrorLine(), is( "45" ) ); - assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), - is( "java.lang.RuntimeException" ) ); + assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), is( "java.lang.RuntimeException" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), is( "surefire.MyTest$A" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( "MyTest$A" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( "t" ) ); @@ -455,62 +442,61 @@ public void shouldParserEverythingInEnclosedTest() assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0f ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(), - is( "java.lang.IndexOutOfBoundsException" ) ); + is( "java.lang.IndexOutOfBoundsException" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(), - is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n" - + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" - + "\tat surefire.MyTest.access$200(MyTest.java:9)\n" - + "\tat surefire.MyTest$A.t(MyTest.java:45)\n" - + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" - + "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n" - + "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" - + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n" - + "\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n" - + "\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n" - + "\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n" - + "\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n" - + "\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n" - + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n" - + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n" - + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n" - + "\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n" - + "\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n" - + "\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n" - + "\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n" - + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n" - + "\tat org.junit.runners.Suite.runChild(Suite.java:128)\n" - + "\tat org.junit.runners.Suite.runChild(Suite.java:27)\n" - + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n" - + "\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n" - + "\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n" - + "\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n" - + "\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n" - + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n" - + "\tCaused by: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.failure(MyTest.java:33)\n" - + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" - + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" - + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)\n" ) ); + is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n" + + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" + + "\tat surefire.MyTest.access$200(MyTest.java:9)\n" + + "\tat surefire.MyTest$A.t(MyTest.java:45)\n" + + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n" + + "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" + + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n" + + "\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n" + + "\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n" + + "\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n" + + "\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n" + + "\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n" + + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n" + + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n" + + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n" + + "\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n" + + "\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n" + + "\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n" + + "\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n" + + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n" + + "\tat org.junit.runners.Suite.runChild(Suite.java:128)\n" + + "\tat org.junit.runners.Suite.runChild(Suite.java:27)\n" + + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n" + + "\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n" + + "\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n" + + "\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n" + + "\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n" + + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n" + + "\tCaused by: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.failure(MyTest.java:33)\n" + + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" + + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" + + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)\n" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).hasError(), is( true ) ); } @Test - public void shouldParserEverythingInEnclosedTrimStackTraceTest() - throws Exception + public void shouldParserEverythingInEnclosedTrimStackTraceTest() throws Exception { TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger ); - List tests = parser.parse( "src/test/resources/fixture/testsuitexmlparser/" - + "TEST-surefire.MyTest-enclosed-trimStackTrace.xml" ); + List tests = parser.parse( + "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed-trimStackTrace.xml" ); assertTrue( parser.isValid() ); assertThat( tests.size(), is( 1 ) ); assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest$A" ) ); @@ -523,8 +509,7 @@ public void shouldParserEverythingInEnclosedTrimStackTraceTest() assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) ); assertFalse( tests.get( 0 ).getTestCases().get( 0 ).isSuccessful() ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureErrorLine(), is( "45" ) ); - assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), - is( "java.lang.RuntimeException" ) ); + assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), is( "java.lang.RuntimeException" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), is( "surefire.MyTest$A" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( "MyTest$A" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( "t" ) ); @@ -532,28 +517,27 @@ public void shouldParserEverythingInEnclosedTrimStackTraceTest() assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0f ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(), - is( "java.lang.IndexOutOfBoundsException" ) ); + is( "java.lang.IndexOutOfBoundsException" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(), - is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.failure(MyTest.java:33)\n" - + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" - + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" - + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)\n" - + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" - + "\tat surefire.MyTest.access$200(MyTest.java:9)\n" - + "\tat surefire.MyTest$A.t(MyTest.java:45)\n" ) ); + is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.failure(MyTest.java:33)\n" + + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" + + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" + + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)\n" + + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" + + "\tat surefire.MyTest.access$200(MyTest.java:9)\n" + + "\tat surefire.MyTest$A.t(MyTest.java:45)\n" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).hasError(), is( true ) ); } @Test - public void shouldParserEverythingInNestedClassTest() - throws Exception + public void shouldParserEverythingInNestedClassTest() throws Exception { TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger ); - List tests = parser.parse( "src/test/resources/fixture/testsuitexmlparser/" - + "TEST-surefire.MyTest-nestedClass.xml" ); + List tests = parser.parse( + "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass.xml" ); assertTrue( parser.isValid() ); assertThat( tests.size(), is( 1 ) ); assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest" ) ); @@ -566,8 +550,7 @@ public void shouldParserEverythingInNestedClassTest() assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) ); assertFalse( tests.get( 0 ).getTestCases().get( 0 ).isSuccessful() ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureErrorLine(), is( "13" ) ); - assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), - is( "java.lang.RuntimeException" ) ); + assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), is( "java.lang.RuntimeException" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), is( "surefire.MyTest" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( "MyTest" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( "test" ) ); @@ -575,53 +558,52 @@ public void shouldParserEverythingInNestedClassTest() assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0f ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(), - is( "java.lang.IndexOutOfBoundsException" ) ); + is( "java.lang.IndexOutOfBoundsException" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(), - is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n" - + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" - + "\tat surefire.MyTest.test(MyTest.java:13)\n" - + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" - + "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n" - + "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" - + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n" - + "\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n" - + "\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n" - + "\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n" - + "\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n" - + "\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n" - + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n" - + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n" - + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n" - + "\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n" - + "\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n" - + "\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n" - + "\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n" - + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n" - + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n" - + "\tat org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n" - + "\tCaused by: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.failure(MyTest.java:33)\n" - + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" - + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" - + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) ); + is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n" + + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" + + "\tat surefire.MyTest.test(MyTest.java:13)\n" + + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" + + "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n" + + "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" + + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n" + + "\tat org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n" + + "\tat org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n" + + "\tat org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n" + + "\tat org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n" + + "\tat org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n" + + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n" + + "\tat org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n" + + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n" + + "\tat org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n" + + "\tat org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n" + + "\tat org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n" + + "\tat org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n" + + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n" + + "\tat org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n" + + "\tat org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n" + + "\tCaused by: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.failure(MyTest.java:33)\n" + + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" + + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" + + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).hasError(), is( true ) ); } @Test - public void shouldParserEverythingInNestedClassTrimStackTraceTest() - throws Exception + public void shouldParserEverythingInNestedClassTrimStackTraceTest() throws Exception { TestSuiteXmlParser parser = new TestSuiteXmlParser( consoleLogger ); - List tests = parser.parse( "src/test/resources/fixture/testsuitexmlparser/" - + "TEST-surefire.MyTest-nestedClass-trimStackTrace.xml" ); + List tests = parser.parse( + "src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass-trimStackTrace.xml" ); assertTrue( parser.isValid() ); assertThat( tests.size(), is( 1 ) ); assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest" ) ); @@ -634,8 +616,7 @@ public void shouldParserEverythingInNestedClassTrimStackTraceTest() assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) ); assertFalse( tests.get( 0 ).getTestCases().get( 0 ).isSuccessful() ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureErrorLine(), is( "13" ) ); - assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), - is( "java.lang.RuntimeException" ) ); + assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), is( "java.lang.RuntimeException" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), is( "surefire.MyTest" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( "MyTest" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( "test" ) ); @@ -643,19 +624,19 @@ public void shouldParserEverythingInNestedClassTrimStackTraceTest() assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0f ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(), - is( "java.lang.IndexOutOfBoundsException" ) ); + is( "java.lang.IndexOutOfBoundsException" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(), - is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n" - + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" - + "\tat surefire.MyTest.test(MyTest.java:13)\n" - + "\tCaused by: java.lang.IndexOutOfBoundsException\n" - + "\tat surefire.MyTest.failure(MyTest.java:33)\n" - + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" - + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" - + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" - + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) ); + is( "java.lang.RuntimeException: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n" + + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n" + + "\tat surefire.MyTest.test(MyTest.java:13)\n" + + "\tCaused by: java.lang.IndexOutOfBoundsException\n" + + "\tat surefire.MyTest.failure(MyTest.java:33)\n" + + "\tat surefire.MyTest.access$100(MyTest.java:9)\n" + + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n" + + "\tat surefire.MyTest.delegate(MyTest.java:29)\n" + + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) ); assertThat( tests.get( 0 ).getTestCases().get( 0 ).hasError(), is( true ) ); } diff --git a/surefire-report-parser/src/test/resources/test-reports/com.shape.CircleTest.txt b/surefire-report-parser/src/test/resources/test-reports/com.shape.CircleTest.txt index 5030dee18c..0e2ee0475f 100644 --- a/surefire-report-parser/src/test/resources/test-reports/com.shape.CircleTest.txt +++ b/surefire-report-parser/src/test/resources/test-reports/com.shape.CircleTest.txt @@ -1,10 +1,10 @@ ------------------------------------------------------------------------------- Battery: com.shape.CircleTest ------------------------------------------------------------------------------- -testX(com.shape.CircleTest) -testY(com.shape.CircleTest) -testXY(com.shape.CircleTest) -testRadius(com.shape.CircleTest) +com.shape.CircleTest.testX +com.shape.CircleTest.testY +com.shape.CircleTest.testXY +com.shape.CircleTest.testRadius [ stdout ] --------------------------------------------------------------- @@ -63,7 +63,7 @@ junit.framework.AssertionFailedError: expected:<20> but was:<10> at org.codehaus.classworlds.Launcher.launch(Launcher.java:255) at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) at org.codehaus.classworlds.Launcher.main(Launcher.java:375) -testProperties(com.shape.CircleTest) +com.shape.CircleTest.testProperties [ stdout ] --------------------------------------------------------------- @@ -117,6 +117,6 @@ java.lang.ArithmeticException: / by zero at org.codehaus.classworlds.Launcher.launch(Launcher.java:255) at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) at org.codehaus.classworlds.Launcher.main(Launcher.java:375) -testPI(com.shape.CircleTest) -testCircumference(com.shape.CircleTest) -testDiameter(com.shape.CircleTest) +com.shape.CircleTest.testPI +com.shape.CircleTest.testCircumference +com.shape.CircleTest.testDiameter diff --git a/surefire-report-parser/src/test/resources/test-reports/com.shapeclone.CircleTest.txt b/surefire-report-parser/src/test/resources/test-reports/com.shapeclone.CircleTest.txt index 90e323991c..e190044725 100644 --- a/surefire-report-parser/src/test/resources/test-reports/com.shapeclone.CircleTest.txt +++ b/surefire-report-parser/src/test/resources/test-reports/com.shapeclone.CircleTest.txt @@ -1,10 +1,10 @@ ------------------------------------------------------------------------------- Battery: com.shapeclone.CircleTest ------------------------------------------------------------------------------- -testX(com.shapeclone.CircleTest) -testY(com.shapeclone.CircleTest) -testXY(com.shapeclone.CircleTest) -testRadius(com.shapeclone.CircleTest) +com.shapeclone.CircleTest.testX +com.shapeclone.CircleTest.testY +com.shapeclone.CircleTest.testXY +com.shapeclone.CircleTest.testRadius [ stdout ] --------------------------------------------------------------- @@ -63,7 +63,7 @@ junit.framework.AssertionFailedError: expected:<20> but was:<10> at org.codehaus.classworlds.Launcher.launch(Launcher.java:255) at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) at org.codehaus.classworlds.Launcher.main(Launcher.java:375) -testProperties(com.shapeclone.CircleTest) +com.shapeclone.CircleTest.testProperties [ stdout ] --------------------------------------------------------------- @@ -117,6 +117,6 @@ java.lang.ArithmeticException: / by zero at org.codehaus.classworlds.Launcher.launch(Launcher.java:255) at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) at org.codehaus.classworlds.Launcher.main(Launcher.java:375) -testPI(com.shapeclone.CircleTest) -testCircumference(com.shapeclone.CircleTest) -testDiameter(com.shapeclone.CircleTest) +com.shapeclone.CircleTest.testPI +com.shapeclone.CircleTest.testCircumference +com.shapeclone.CircleTest.testDiameter diff --git a/surefire-shadefire/pom.xml b/surefire-shadefire/pom.xml index 67adde1ed9..d3fb1c5d46 100644 --- a/surefire-shadefire/pom.xml +++ b/surefire-shadefire/pom.xml @@ -23,7 +23,7 @@ org.apache.maven.surefire surefire - 3.0.0-M3 + 3.0.0-M4 surefire-shadefire @@ -92,7 +92,7 @@ maven-surefire-plugin - 3.0.0-M2 + 3.0.0-M3 true diff --git a/surefire-shared-utils/pom.xml b/surefire-shared-utils/pom.xml new file mode 100644 index 0000000000..b15b3a1a33 --- /dev/null +++ b/surefire-shared-utils/pom.xml @@ -0,0 +1,113 @@ + + + + + 4.0.0 + + + org.apache.maven.surefire + surefire + 3.0.0-M4 + + + surefire-shared-utils + Surefire Shared Utils + Relocated Java packages of maven-shared-utils in Surefire + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + org.apache.maven.shared + maven-shared-utils + + + commons-io + commons-io + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-compress + + + commons-codec + commons-codec + + + + + + + maven-shade-plugin + + + + shade + + + + + org.apache.maven.shared:maven-shared-utils + commons-io:commons-io + org.apache.commons:commons-lang3 + org.apache.commons:commons-compress + commons-codec:commons-codec + + + + + org.apache.maven.shared.utils + org.apache.maven.surefire.shared.utils + + + org.apache.commons.io + org.apache.maven.surefire.shared.io + + + org.apache.commons.lang3 + org.apache.maven.surefire.shared.lang3 + + + org.apache.commons.compress + org.apache.maven.surefire.shared.compress + + + org.apache.commons.codec + org.apache.maven.surefire.shared.codec + + + + + + + + + + \ No newline at end of file

\"\"
\"\"
test
" + "" - + "\"\"" + + "
\"\"
" + "
" + "
MyTest
" + "" - + "\"\"" + + "
\"\"
" + "
" + "
MyTest
" + "" - + "\"\"" + + "
\"\"
" + "
" + "
MyTest
" + "" - + "\"\"" + + "
\"\"
" + "
" + "
MyTest$A
" + "" - + "\"\"" + + "
\"\"
" + "
" + "
MyTest$A