Skip to content

Commit 18b4078

Browse files
sormurassnicoll
authored andcommitted
[SUREFIRE-1614] JUnit Runner that writes to System.out corrupts Surefire's STDOUT when using JUnit's Vintage Engine
1 parent af417b8 commit 18b4078

File tree

5 files changed

+156
-28
lines changed

5 files changed

+156
-28
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package org.apache.maven.surefire.its;
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
import org.apache.maven.it.VerificationException;
23+
import org.apache.maven.surefire.its.fixture.OutputValidator;
24+
import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
25+
import org.junit.Before;
26+
import org.junit.Test;
27+
28+
import java.util.List;
29+
30+
import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaVersion;
31+
import static org.fest.assertions.Assertions.assertThat;
32+
import static org.hamcrest.CoreMatchers.startsWith;
33+
34+
public class JUnitPlatformStreamCorruptionIT
35+
extends SurefireJUnit4IntegrationTestCase
36+
{
37+
@Before
38+
public void setUp()
39+
{
40+
assumeJavaVersion( 1.8d );
41+
}
42+
43+
@Test
44+
public void warningIsNotEmitted() throws VerificationException
45+
{
46+
OutputValidator validator = unpack( "/surefire-1614-stream-corruption" )
47+
.executeTest()
48+
.verifyErrorFree( 1 );
49+
50+
List<String> lines = validator.loadLogLines(
51+
startsWith( "[WARNING] Corrupted STDOUT by directly writing to native stream in forked JVM" ) );
52+
53+
assertThat( lines )
54+
.isEmpty();
55+
}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<groupId>org.apache.maven.plugins.surefire</groupId>
6+
<artifactId>junit-platform-1.0.0</artifactId>
7+
<version>1.0</version>
8+
<name>[SUREFIRE-1614] JUnit 5: Vintage Output Stream Corruption</name>
9+
10+
<properties>
11+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12+
<maven.compiler.source>1.8</maven.compiler.source>
13+
<maven.compiler.target>1.8</maven.compiler.target>
14+
</properties>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>org.junit.vintage</groupId>
19+
<artifactId>junit-vintage-engine</artifactId>
20+
<version>5.3.2</version>
21+
<scope>test</scope>
22+
</dependency>
23+
</dependencies>
24+
25+
<build>
26+
<plugins>
27+
<plugin>
28+
<groupId>org.apache.maven.plugins</groupId>
29+
<artifactId>maven-surefire-plugin</artifactId>
30+
<version>${surefire.version}</version>
31+
</plugin>
32+
</plugins>
33+
</build>
34+
35+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.example.demo;
2+
3+
import org.junit.runners.BlockJUnit4ClassRunner;
4+
import org.junit.runners.model.InitializationError;
5+
import org.junit.runners.model.TestClass;
6+
7+
public class CustomRunner
8+
extends BlockJUnit4ClassRunner
9+
{
10+
11+
public CustomRunner( Class<?> klass ) throws InitializationError
12+
{
13+
super( klass );
14+
}
15+
16+
@Override
17+
protected TestClass createTestClass( Class<?> testClass )
18+
{
19+
System.out.println( "Creating test class" );
20+
return super.createTestClass( testClass );
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.example.demo;
2+
3+
import org.junit.Test;
4+
import org.junit.runner.RunWith;
5+
6+
@RunWith( CustomRunner.class )
7+
public class SurefireStreamCorruptionTest
8+
{
9+
@Test
10+
public void contextLoads()
11+
{
12+
}
13+
}

surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java

+30-28
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import static java.util.stream.Collectors.toList;
2828
import static org.apache.maven.surefire.booter.ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP;
2929
import static org.apache.maven.surefire.booter.ProviderParameterNames.TESTNG_GROUPS_PROP;
30+
import static org.apache.maven.surefire.report.ConsoleOutputCapture.startCapture;
31+
import static org.apache.maven.surefire.util.TestsToRun.fromClass;
3032
import static org.junit.platform.commons.util.StringUtils.isBlank;
3133
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
3234
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
@@ -44,7 +46,6 @@
4446

4547
import org.apache.maven.surefire.providerapi.AbstractProvider;
4648
import org.apache.maven.surefire.providerapi.ProviderParameters;
47-
import org.apache.maven.surefire.report.ConsoleOutputCapture;
4849
import org.apache.maven.surefire.report.ConsoleOutputReceiver;
4950
import org.apache.maven.surefire.report.ReporterException;
5051
import org.apache.maven.surefire.report.ReporterFactory;
@@ -104,22 +105,35 @@ public Iterable<Class<?>> getSuites()
104105
public RunResult invoke( Object forkTestSet )
105106
throws TestSetFailedException, ReporterException
106107
{
107-
if ( forkTestSet instanceof TestsToRun )
108-
{
109-
return invokeAllTests( (TestsToRun) forkTestSet );
110-
}
111-
else if ( forkTestSet instanceof Class )
112-
{
113-
return invokeAllTests( TestsToRun.fromClass( (Class<?>) forkTestSet ) );
114-
}
115-
else if ( forkTestSet == null )
108+
ReporterFactory reporterFactory = parameters.getReporterFactory();
109+
final RunResult runResult;
110+
try
116111
{
117-
return invokeAllTests( scanClasspath() );
112+
RunListener runListener = reporterFactory.createReporter();
113+
startCapture( ( ConsoleOutputReceiver ) runListener );
114+
if ( forkTestSet instanceof TestsToRun )
115+
{
116+
invokeAllTests( (TestsToRun) forkTestSet, runListener );
117+
}
118+
else if ( forkTestSet instanceof Class )
119+
{
120+
invokeAllTests( fromClass( ( Class<?> ) forkTestSet ), runListener );
121+
}
122+
else if ( forkTestSet == null )
123+
{
124+
invokeAllTests( scanClasspath(), runListener );
125+
}
126+
else
127+
{
128+
throw new IllegalArgumentException(
129+
"Unexpected value of forkTestSet: " + forkTestSet );
130+
}
118131
}
119-
else
132+
finally
120133
{
121-
throw new IllegalArgumentException( "Unexpected value of forkTestSet: " + forkTestSet );
134+
runResult = reporterFactory.close();
122135
}
136+
return runResult;
123137
}
124138

125139
private TestsToRun scanClasspath()
@@ -130,22 +144,10 @@ private TestsToRun scanClasspath()
130144
return parameters.getRunOrderCalculator().orderTestClasses( scannedClasses );
131145
}
132146

133-
private RunResult invokeAllTests( TestsToRun testsToRun )
147+
private void invokeAllTests( TestsToRun testsToRun, RunListener runListener )
134148
{
135-
RunResult runResult;
136-
ReporterFactory reporterFactory = parameters.getReporterFactory();
137-
try
138-
{
139-
RunListener runListener = reporterFactory.createReporter();
140-
ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) runListener );
141-
LauncherDiscoveryRequest discoveryRequest = buildLauncherDiscoveryRequest( testsToRun );
142-
launcher.execute( discoveryRequest, new RunListenerAdapter( runListener ) );
143-
}
144-
finally
145-
{
146-
runResult = reporterFactory.close();
147-
}
148-
return runResult;
149+
LauncherDiscoveryRequest discoveryRequest = buildLauncherDiscoveryRequest( testsToRun );
150+
launcher.execute( discoveryRequest, new RunListenerAdapter( runListener ) );
149151
}
150152

151153
private LauncherDiscoveryRequest buildLauncherDiscoveryRequest( TestsToRun testsToRun )

0 commit comments

Comments
 (0)