Skip to content

Commit

Permalink
[SUREFIRE-1975] JDK18 - The Security Manager is deprecated and will b…
Browse files Browse the repository at this point in the history
…e removed in a future release
  • Loading branch information
Tibor17 committed Jan 21, 2022
1 parent 97afea1 commit aeb6a32
Show file tree
Hide file tree
Showing 12 changed files with 153 additions and 70 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/maven-verify.yml
Expand Up @@ -26,6 +26,7 @@ jobs:
name: Verify
uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v2
with:
jdk-matrix: '[ "8", "11", "17", "18-ea" ]'
ff-goal: 'clean install -nsu -P run-its'
ff-site-goal: 'clean install site -nsu -DskipTests -P reporting'
verify-goal: 'clean install -nsu -P run-its'
Expand All @@ -35,5 +36,5 @@ jobs:
surefire-its/target/*/log.txt
surefire-its/target/**/surefire-reports/*
surefire-its/target/**/failsafe-reports/*
max-parallel: 4
max-parallel: 5
timeout-minutes: 420
Expand Up @@ -141,12 +141,12 @@
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
import static org.apache.maven.surefire.api.util.ReflectionUtils.tryGetMethod;
import static org.apache.maven.surefire.booter.Classpath.emptyClasspath;
import static org.apache.maven.surefire.booter.SystemUtils.JAVA_SPECIFICATION_VERSION;
import static org.apache.maven.surefire.booter.SystemUtils.endsWithJavaPath;
import static org.apache.maven.surefire.booter.SystemUtils.isBuiltInJava9AtLeast;
import static org.apache.maven.surefire.booter.SystemUtils.isJava9AtLeast;
import static org.apache.maven.surefire.booter.SystemUtils.toJdkHomeFromJvmExec;
import static org.apache.maven.surefire.booter.SystemUtils.toJdkVersionFromReleaseFile;
import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_RECENT;
import static org.apache.maven.surefire.shared.lang3.StringUtils.substringBeforeLast;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_WINDOWS;
import static org.apache.maven.surefire.shared.utils.StringUtils.capitalizeFirstLetter;
Expand Down Expand Up @@ -2673,8 +2673,7 @@ else if ( !getEnvironmentVariables().containsKey( "JAVA_HOME" ) )

// use the same JVM as the one used to run Maven (the "java.home" one)
String jvmToUse = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
getConsoleLogger().debug( "Using JVM: " + jvmToUse + " with Java version "
+ JAVA_SPECIFICATION_VERSION.toPlainString() );
getConsoleLogger().debug( "Using JVM: " + jvmToUse + " with Java version " + JAVA_RECENT );

return new JdkAttributes( jvmToUse, isBuiltInJava9AtLeast() );
}
Expand Down
3 changes: 3 additions & 0 deletions maven-surefire-plugin/src/site/apt/examples/junit.apt.vm
Expand Up @@ -204,6 +204,9 @@ else
As long as <<<forkCount>>> is not 0 and you use JUnit3, you can run your tests with a Java security manager enabled.
The class name of the security manager must be sent as a system property variable to the JUnit3 provider.

The JDK 17 deprecated the class <<<java.lang.SecurityManager>>> and the security manager is not fully supported
since JDK 18. The JUnit3 provider fails with enabled system property <<surefire.security.manager>>> in JDK 18+.

JUnit4 uses mechanisms internally that are not compatible with the tested
security managers and thus this means of configuring a security manager with JUnit4 is not supported
by Surefire.
Expand Down
Expand Up @@ -22,6 +22,9 @@
import java.lang.management.ManagementFactory;
import java.util.Map;

import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_17;
import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_RECENT;

/**
* Similar to Java 7 java.util.Objects.
*
Expand All @@ -44,4 +47,12 @@ public static Map<String, String> systemProps()
{
return ManagementFactory.getRuntimeMXBean().getSystemProperties();
}

/**
* @return true if SecurityManager is supported (even if deprecated) in JDK (up to 17)
*/
public static boolean isSecurityManagerSupported()
{
return JAVA_RECENT.atMost( JAVA_17 );
}
}
Expand Up @@ -42,6 +42,7 @@
import org.apache.maven.surefire.api.util.internal.ChannelsWriterTest;
import org.apache.maven.surefire.api.util.internal.ConcurrencyUtilsTest;
import org.apache.maven.surefire.api.util.internal.ImmutableMapTest;
import org.apache.maven.surefire.api.util.internal.ObjectUtilsTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

Expand Down Expand Up @@ -72,7 +73,8 @@
ChannelsWriterTest.class,
AsyncSocketTest.class,
AbstractStreamEncoderTest.class,
AbstractStreamDecoderTest.class
AbstractStreamDecoderTest.class,
ObjectUtilsTest.class
} )
@RunWith( Suite.class )
public class JUnit4SuiteTest
Expand Down
@@ -0,0 +1,39 @@
package org.apache.maven.surefire.api.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 org.junit.Test;

import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_17;
import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_RECENT;
import static org.fest.assertions.Assertions.assertThat;

/**
* @since 3.0.0-M6
*/
public class ObjectUtilsTest
{
@Test
public void shouldSupportSecurityManager()
{
assertThat( ObjectUtils.isSecurityManagerSupported() )
.isEqualTo( JAVA_RECENT.atMost( JAVA_17 ) );
}
}
Expand Up @@ -32,6 +32,7 @@
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeGetter;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray2;
import static org.apache.maven.surefire.api.util.internal.ObjectUtils.isSecurityManagerSupported;

/**
* Creates the surefire provider.
Expand Down Expand Up @@ -85,7 +86,7 @@ public static RunResult invokeProvider( Object testSet, ClassLoader testsClassLo
}
finally
{
if ( restoreStreams && System.getSecurityManager() == null )
if ( restoreStreams && ( !isSecurityManagerSupported() || System.getSecurityManager() == null ) )
{
System.setOut( orgSystemOut );
System.setErr( orgSystemErr );
Expand Down
Expand Up @@ -33,17 +33,18 @@
import java.util.Properties;
import java.util.StringTokenizer;

import static java.lang.Character.isDigit;
import static java.lang.Thread.currentThread;
import static java.util.Objects.requireNonNull;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_RECENT;
import static org.apache.maven.surefire.shared.lang3.JavaVersion.JAVA_9;
import static org.apache.maven.surefire.shared.lang3.StringUtils.isNumeric;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_FREE_BSD;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodChain;
import static org.apache.maven.surefire.api.util.ReflectionUtils.tryLoadClass;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_LINUX;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_FREE_BSD;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_NET_BSD;
import static org.apache.maven.surefire.shared.lang3.SystemUtils.IS_OS_OPEN_BSD;
import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodChain;
import static org.apache.maven.surefire.api.util.ReflectionUtils.tryLoadClass;

/**
* JDK 9 support.
Expand All @@ -53,8 +54,6 @@
*/
public final class SystemUtils
{
public static final BigDecimal JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion();

private static final BigDecimal JIGSAW_JAVA_VERSION = new BigDecimal( 9 ).stripTrailingZeros();

private static final int PROC_STATUS_PID_FIRST_CHARS = 20;
Expand Down Expand Up @@ -165,43 +164,6 @@ else if ( versions.countTokens() >= 2 )
}
}

/**
* Safely extracts major and minor version as fractional number from
* <pre>
* $MAJOR.$MINOR.$SECURITY
* </pre>.
* <br>
* The security version is usually not needed to know.
* It can be applied to not certified JRE.
*
* @return major.minor version derived from java specification version of <em>this</em> JVM, e.g. 1.8, 9, etc.
*/
private static BigDecimal getJavaSpecificationVersion()
{
StringBuilder fractionalVersion = new StringBuilder( "0" );
for ( char c : org.apache.maven.surefire.shared.lang3.SystemUtils.JAVA_SPECIFICATION_VERSION.toCharArray() )
{
if ( isDigit( c ) )
{
fractionalVersion.append( c );
}
else if ( c == '.' )
{
if ( fractionalVersion.indexOf( "." ) == -1 )
{
fractionalVersion.append( '.' );
}
else
{
break;
}
}
}
String majorMinorVersion = fractionalVersion.toString();
return new BigDecimal( majorMinorVersion.endsWith( "." ) ? majorMinorVersion + "0" : majorMinorVersion )
.stripTrailingZeros();
}

public static boolean isJava9AtLeast( String jvmExecutablePath )
{
File externalJavaHome = toJdkHomeFromJvmExec( jvmExecutablePath );
Expand All @@ -220,7 +182,7 @@ public static boolean isJava9AtLeast( String jvmExecutablePath )

public static boolean isBuiltInJava9AtLeast()
{
return JAVA_SPECIFICATION_VERSION.compareTo( JIGSAW_JAVA_VERSION ) >= 0;
return JAVA_RECENT.atLeast( JAVA_9 );
}

public static boolean isJava9AtLeast( BigDecimal version )
Expand Down
Expand Up @@ -46,7 +46,6 @@
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
import static org.powermock.reflect.Whitebox.invokeMethod;

/**
* Test of {@link SystemUtils}.
Expand All @@ -63,17 +62,6 @@ public class SystemUtilsTest
*/
public static class PlainUnitTests
{

@Test
public void shouldMatchJavaSpecVersion() throws Exception
{
BigDecimal actual = invokeMethod( SystemUtils.class, "getJavaSpecificationVersion" );
BigDecimal expected =
new BigDecimal( System.getProperty( "java.specification.version" ) ).stripTrailingZeros();
assertThat( actual ).isEqualTo( expected );
assertThat( SystemUtils.JAVA_SPECIFICATION_VERSION ).isEqualTo( expected );
}

@Test
public void shouldParseProprietaryReleaseFile() throws IOException
{
Expand Down
Expand Up @@ -21,8 +21,11 @@

import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
import org.apache.maven.surefire.its.fixture.SurefireLauncher;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.apache.maven.surefire.its.fixture.HelperAssertions.assumeJavaMaxVersion;

/**
* SUREFIRE-621 Asserts proper test counts when running junit 3 tests in parallel
*
Expand All @@ -31,6 +34,12 @@
public class Surefire34SecurityManagerIT
extends SurefireJUnit4IntegrationTestCase
{
@BeforeClass
public static void checkJavaVersion()
{
assumeJavaMaxVersion( 17 );
}

@Test
public void testSecurityManager()
{
Expand Down
Expand Up @@ -31,13 +31,14 @@
import org.apache.maven.surefire.api.report.TestSetReportEntry;
import org.apache.maven.surefire.api.suite.RunResult;
import org.apache.maven.surefire.api.testset.TestSetFailedException;
import org.apache.maven.surefire.api.util.ReflectionUtils;
import org.apache.maven.surefire.api.util.RunOrderCalculator;
import org.apache.maven.surefire.api.util.ScanResult;
import org.apache.maven.surefire.api.util.TestsToRun;

import java.util.Map;

import static org.apache.maven.surefire.api.util.ReflectionUtils.instantiate;
import static org.apache.maven.surefire.api.util.internal.ObjectUtils.isSecurityManagerSupported;
import static org.apache.maven.surefire.api.util.internal.ObjectUtils.systemProps;

/**
Expand Down Expand Up @@ -100,13 +101,7 @@ else if ( forkTestSet instanceof Class )
final RunListener reporter = reporterFactory.createReporter();
ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
Map<String, String> systemProperties = systemProps();
String smClassName = System.getProperty( "surefire.security.manager" );
if ( smClassName != null )
{
SecurityManager securityManager =
ReflectionUtils.instantiate( getClass().getClassLoader(), smClassName, SecurityManager.class );
System.setSecurityManager( securityManager );
}
setSystemManager( System.getProperty( "surefire.security.manager" ) );

for ( Class<?> clazz : testsToRun )
{
Expand All @@ -121,6 +116,21 @@ else if ( forkTestSet instanceof Class )
return runResult;
}

static void setSystemManager( String smClassName ) throws TestSetFailedException
{
if ( smClassName != null )
{
if ( !isSecurityManagerSupported() )
{
throw new TestSetFailedException( "JDK does not support overriding Security Manager with "
+ "a value in system property 'surefire.security.manager'." );
}
ClassLoader classLoader = JUnit3Provider.class.getClassLoader();
SecurityManager sm = instantiate( classLoader, smClassName, SecurityManager.class );
System.setSecurityManager( sm );
}
}

private SurefireTestSet createTestSet( Class<?> clazz )
{
return reflector.isJUnit3Available() && jUnit3TestChecker.accept( clazz )
Expand Down

0 comments on commit aeb6a32

Please sign in to comment.