Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SUREFIRE-1975] JDK18 - The Security Manager is deprecated and will be removed in a future release #422

Merged
merged 1 commit into from Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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