mirror of
https://github.com/google/nomulus.git
synced 2025-05-22 04:09:46 +02:00
Get rid of all remaining JUnit 4 usages except in prober & proxy (#731)
* Get rid of all remaining JUnit 4 usages except in prober & proxy subprojects Caveat: Test suites aren't yet implemented in JUnit 5 so we still use the ones from JUnit 5 in the core subproject. * Fix some build errors
This commit is contained in:
parent
a02b67caf5
commit
16a31e460c
347 changed files with 3785 additions and 1536 deletions
|
@ -33,10 +33,9 @@ dependencies {
|
|||
runtime deps['io.netty:netty-tcnative-boringssl-static']
|
||||
|
||||
testCompile deps['com.google.truth:truth']
|
||||
testCompile deps['junit:junit']
|
||||
testCompile deps['org.junit.jupiter:junit-jupiter-api']
|
||||
testCompile deps['org.junit.jupiter:junit-jupiter-engine']
|
||||
testCompile deps['org.junit.vintage:junit-vintage-engine']
|
||||
testCompile deps['org.junit.jupiter:junit-jupiter-params']
|
||||
testCompile deps['org.bouncycastle:bcpkix-jdk15on']
|
||||
testCompile deps['org.bouncycastle:bcprov-jdk15on']
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ javax.inject:javax.inject:1
|
|||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.13
|
||||
junit:junit:4.12
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
|
@ -53,9 +53,9 @@ org.checkerframework:checker-qual:2.11.1
|
|||
org.hamcrest:hamcrest-core:1.3
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit.vintage:junit-vintage-engine:5.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
|
|
@ -42,7 +42,7 @@ javax.inject:javax.inject:1
|
|||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.13
|
||||
junit:junit:4.12
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
|
@ -53,9 +53,9 @@ org.checkerframework:checker-qual:2.11.1
|
|||
org.hamcrest:hamcrest-core:1.3
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit.vintage:junit-vintage-engine:5.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
|
|
@ -44,7 +44,7 @@ javax.inject:javax.inject:1
|
|||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.13
|
||||
junit:junit:4.12
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
|
@ -55,9 +55,9 @@ org.checkerframework:checker-qual:2.11.1
|
|||
org.hamcrest:hamcrest-core:1.3
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit.vintage:junit-vintage-engine:5.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
|
|
@ -44,7 +44,7 @@ javax.inject:javax.inject:1
|
|||
javax.mail:mail:1.4
|
||||
javax.xml.bind:jaxb-api:2.3.0
|
||||
joda-time:joda-time:2.9.2
|
||||
junit:junit:4.13
|
||||
junit:junit:4.12
|
||||
org.apache.httpcomponents:httpclient:4.5.11
|
||||
org.apache.httpcomponents:httpcore:4.4.13
|
||||
org.apiguardian:apiguardian-api:1.1.0
|
||||
|
@ -55,9 +55,9 @@ org.checkerframework:checker-qual:2.11.1
|
|||
org.hamcrest:hamcrest-core:1.3
|
||||
org.junit.jupiter:junit-jupiter-api:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-engine:5.6.2
|
||||
org.junit.jupiter:junit-jupiter-params:5.6.2
|
||||
org.junit.platform:junit-platform-commons:1.6.2
|
||||
org.junit.platform:junit-platform-engine:1.6.2
|
||||
org.junit.vintage:junit-vintage-engine:5.6.2
|
||||
org.junit:junit-bom:5.6.2
|
||||
org.opentest4j:opentest4j:1.2.0
|
||||
org.yaml:snakeyaml:1.17
|
||||
|
|
|
@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkState;
|
|||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.truth.ThrowableSubject;
|
||||
|
@ -41,14 +41,15 @@ import io.netty.util.ReferenceCountUtil;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import org.junit.rules.ExternalResource;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
|
||||
/**
|
||||
* Helper for setting up and testing client / server connection with netty.
|
||||
* JUnit extension to set up and test the client / server connection with netty.
|
||||
*
|
||||
* <p>Used in {@link SslClientInitializerTest} and {@link SslServerInitializerTest}.
|
||||
*/
|
||||
public final class NettyRule extends ExternalResource {
|
||||
public final class NettyExtension implements AfterEachCallback {
|
||||
|
||||
// All I/O operations are done inside the single thread within this event loop group, which is
|
||||
// different from the main test thread. Therefore synchronizations are required to make sure that
|
||||
|
@ -223,7 +224,7 @@ public final class NettyRule extends ExternalResource {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
public void afterEach(ExtensionContext context) {
|
||||
Future<?> unusedFuture = eventLoopGroup.shutdownGracefully();
|
||||
}
|
||||
|
|
@ -47,14 +47,13 @@ import java.time.Duration;
|
|||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import org.junit.Rule;
|
||||
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;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SslClientInitializer}.
|
||||
|
@ -67,8 +66,7 @@ import org.junit.runners.Parameterized.Parameters;
|
|||
* <p>The local addresses used in each test method must to be different, otherwise tests run in
|
||||
* parallel may interfere with each other.
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class SslClientInitializerTest {
|
||||
class SslClientInitializerTest {
|
||||
|
||||
/** Fake host to test if the SSL engine gets the correct peer host. */
|
||||
private static final String SSL_HOST = "www.example.tld";
|
||||
|
@ -80,17 +78,17 @@ public class SslClientInitializerTest {
|
|||
|
||||
private static final Function<Channel, Integer> portProvider = channel -> SSL_PORT;
|
||||
|
||||
@Rule public NettyRule nettyRule = new NettyRule();
|
||||
@RegisterExtension NettyExtension nettyExtension = new NettyExtension();
|
||||
|
||||
@Parameter(0)
|
||||
public SslProvider sslProvider;
|
||||
|
||||
// We do our best effort to test all available SSL providers.
|
||||
@Parameters(name = "{0}")
|
||||
public static SslProvider[] data() {
|
||||
return OpenSsl.isAvailable()
|
||||
? new SslProvider[] {SslProvider.JDK, SslProvider.OPENSSL}
|
||||
: new SslProvider[] {SslProvider.JDK};
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<Arguments> provideTestCombinations() {
|
||||
Stream.Builder<Arguments> args = Stream.builder();
|
||||
// We do our best effort to test all available SSL providers.
|
||||
args.add(Arguments.of(SslProvider.JDK));
|
||||
if (OpenSsl.isAvailable()) {
|
||||
args.add(Arguments.of(SslProvider.OPENSSL));
|
||||
}
|
||||
return args.build();
|
||||
}
|
||||
|
||||
/** Saves the SNI hostname received by the server, if sent by the client. */
|
||||
|
@ -111,8 +109,9 @@ public class SslClientInitializerTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_swappedInitializerWithSslHandler() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_swappedInitializerWithSslHandler(SslProvider sslProvider) {
|
||||
SslClientInitializer<EmbeddedChannel> sslClientInitializer =
|
||||
new SslClientInitializer<>(
|
||||
sslProvider, hostProvider, portProvider, ImmutableList.of(), null, null);
|
||||
|
@ -127,8 +126,9 @@ public class SslClientInitializerTest {
|
|||
assertThat(channel.isActive()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_nullHost() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_nullHost(SslProvider sslProvider) {
|
||||
SslClientInitializer<EmbeddedChannel> sslClientInitializer =
|
||||
new SslClientInitializer<>(
|
||||
sslProvider, channel -> null, portProvider, ImmutableList.of(), null, null);
|
||||
|
@ -139,8 +139,9 @@ public class SslClientInitializerTest {
|
|||
assertThat(channel.isActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_nullPort() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_nullPort(SslProvider sslProvider) {
|
||||
SslClientInitializer<EmbeddedChannel> sslClientInitializer =
|
||||
new SslClientInitializer<>(
|
||||
sslProvider, hostProvider, channel -> null, ImmutableList.of(), null, null);
|
||||
|
@ -151,25 +152,29 @@ public class SslClientInitializerTest {
|
|||
assertThat(channel.isActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_defaultTrustManager_rejectSelfSignedCert() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_defaultTrustManager_rejectSelfSignedCert(SslProvider sslProvider)
|
||||
throws Exception {
|
||||
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress =
|
||||
new LocalAddress("DEFAULT_TRUST_MANAGER_REJECT_SELF_SIGNED_CERT_" + sslProvider);
|
||||
nettyRule.setUpServer(localAddress, getServerHandler(false, ssc.key(), ssc.cert()));
|
||||
nettyExtension.setUpServer(localAddress, getServerHandler(false, ssc.key(), ssc.cert()));
|
||||
SslClientInitializer<LocalChannel> sslClientInitializer =
|
||||
new SslClientInitializer<>(
|
||||
sslProvider, hostProvider, portProvider, ImmutableList.of(), null, null);
|
||||
nettyRule.setUpClient(localAddress, sslClientInitializer);
|
||||
nettyExtension.setUpClient(localAddress, sslClientInitializer);
|
||||
// The connection is now terminated, both the client side and the server side should get
|
||||
// exceptions.
|
||||
nettyRule.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class);
|
||||
nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class);
|
||||
assertThat(nettyRule.getClientChannel().isActive()).isFalse();
|
||||
nettyExtension.assertThatClientRootCause().isInstanceOf(CertPathBuilderException.class);
|
||||
nettyExtension.assertThatServerRootCause().isInstanceOf(SSLException.class);
|
||||
assertThat(nettyExtension.getClientChannel().isActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_customTrustManager_acceptCertSignedByTrustedCa() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_customTrustManager_acceptCertSignedByTrustedCa(SslProvider sslProvider)
|
||||
throws Exception {
|
||||
LocalAddress localAddress =
|
||||
new LocalAddress("CUSTOM_TRUST_MANAGER_ACCEPT_CERT_SIGNED_BY_TRUSTED_CA_" + sslProvider);
|
||||
|
||||
|
@ -182,23 +187,24 @@ public class SslClientInitializerTest {
|
|||
|
||||
// Set up the server to use the signed cert and private key to perform handshake;
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
nettyRule.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
|
||||
nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
|
||||
|
||||
// Set up the client to trust the self signed cert used to sign the cert that server provides.
|
||||
SslClientInitializer<LocalChannel> sslClientInitializer =
|
||||
new SslClientInitializer<>(
|
||||
sslProvider, hostProvider, portProvider, ImmutableList.of(ssc.cert()), null, null);
|
||||
nettyRule.setUpClient(localAddress, sslClientInitializer);
|
||||
nettyExtension.setUpClient(localAddress, sslClientInitializer);
|
||||
|
||||
setUpSslChannel(nettyRule.getClientChannel(), cert);
|
||||
nettyRule.assertThatMessagesWork();
|
||||
setUpSslChannel(nettyExtension.getClientChannel(), cert);
|
||||
nettyExtension.assertThatMessagesWork();
|
||||
|
||||
// Verify that the SNI extension is sent during handshake.
|
||||
assertThat(sniHostReceived).isEqualTo(SSL_HOST);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_customTrustManager_serverCertExpired() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_customTrustManager_serverCertExpired(SslProvider sslProvider) throws Exception {
|
||||
LocalAddress localAddress =
|
||||
new LocalAddress("CUSTOM_TRUST_MANAGER_SERVE_CERT_EXPIRED_" + sslProvider);
|
||||
|
||||
|
@ -217,22 +223,24 @@ public class SslClientInitializerTest {
|
|||
|
||||
// Set up the server to use the signed cert and private key to perform handshake;
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
nettyRule.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
|
||||
nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
|
||||
|
||||
// Set up the client to trust the self signed cert used to sign the cert that server provides.
|
||||
SslClientInitializer<LocalChannel> sslClientInitializer =
|
||||
new SslClientInitializer<>(
|
||||
sslProvider, hostProvider, portProvider, ImmutableList.of(ssc.cert()), null, null);
|
||||
nettyRule.setUpClient(localAddress, sslClientInitializer);
|
||||
nettyExtension.setUpClient(localAddress, sslClientInitializer);
|
||||
|
||||
verifySslException(
|
||||
nettyRule.getClientChannel(),
|
||||
nettyExtension.getClientChannel(),
|
||||
channel -> channel.pipeline().get(SslHandler.class).handshakeFuture().get(),
|
||||
CertificateExpiredException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_customTrustManager_serverCertNotYetValid() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_customTrustManager_serverCertNotYetValid(SslProvider sslProvider)
|
||||
throws Exception {
|
||||
LocalAddress localAddress =
|
||||
new LocalAddress("CUSTOM_TRUST_MANAGER_SERVE_CERT_NOT_YET_VALID_" + sslProvider);
|
||||
|
||||
|
@ -251,23 +259,24 @@ public class SslClientInitializerTest {
|
|||
|
||||
// Set up the server to use the signed cert and private key to perform handshake;
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
nettyRule.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
|
||||
nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
|
||||
|
||||
// Set up the client to trust the self signed cert used to sign the cert that server provides.
|
||||
SslClientInitializer<LocalChannel> sslClientInitializer =
|
||||
new SslClientInitializer<>(
|
||||
sslProvider, hostProvider, portProvider, ImmutableList.of(ssc.cert()), null, null);
|
||||
nettyRule.setUpClient(localAddress, sslClientInitializer);
|
||||
nettyExtension.setUpClient(localAddress, sslClientInitializer);
|
||||
|
||||
verifySslException(
|
||||
nettyRule.getClientChannel(),
|
||||
nettyExtension.getClientChannel(),
|
||||
channel -> channel.pipeline().get(SslHandler.class).handshakeFuture().get(),
|
||||
CertificateNotYetValidException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_customTrustManager_acceptSelfSignedCert_clientCertRequired()
|
||||
throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_customTrustManager_acceptSelfSignedCert_clientCertRequired(
|
||||
SslProvider sslProvider) throws Exception {
|
||||
LocalAddress localAddress =
|
||||
new LocalAddress(
|
||||
"CUSTOM_TRUST_MANAGER_ACCEPT_SELF_SIGNED_CERT_CLIENT_CERT_REQUIRED_" + sslProvider);
|
||||
|
@ -276,7 +285,8 @@ public class SslClientInitializerTest {
|
|||
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate.create();
|
||||
|
||||
// Set up the server to require client certificate.
|
||||
nettyRule.setUpServer(localAddress, getServerHandler(true, serverSsc.key(), serverSsc.cert()));
|
||||
nettyExtension.setUpServer(
|
||||
localAddress, getServerHandler(true, serverSsc.key(), serverSsc.cert()));
|
||||
|
||||
// Set up the client to trust the server certificate and use the client certificate.
|
||||
SslClientInitializer<LocalChannel> sslClientInitializer =
|
||||
|
@ -287,10 +297,10 @@ public class SslClientInitializerTest {
|
|||
ImmutableList.of(serverSsc.cert()),
|
||||
() -> clientSsc.key(),
|
||||
() -> ImmutableList.of(clientSsc.cert()));
|
||||
nettyRule.setUpClient(localAddress, sslClientInitializer);
|
||||
nettyExtension.setUpClient(localAddress, sslClientInitializer);
|
||||
|
||||
SSLSession sslSession = setUpSslChannel(nettyRule.getClientChannel(), serverSsc.cert());
|
||||
nettyRule.assertThatMessagesWork();
|
||||
SSLSession sslSession = setUpSslChannel(nettyExtension.getClientChannel(), serverSsc.cert());
|
||||
nettyExtension.assertThatMessagesWork();
|
||||
|
||||
// Verify that the SNI extension is sent during handshake.
|
||||
assertThat(sniHostReceived).isEqualTo(SSL_HOST);
|
||||
|
@ -302,8 +312,10 @@ public class SslClientInitializerTest {
|
|||
assertThat(sslSession.getPeerCertificates()).asList().containsExactly(serverSsc.cert());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_customTrustManager_wrongHostnameInCertificate() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_customTrustManager_wrongHostnameInCertificate(SslProvider sslProvider)
|
||||
throws Exception {
|
||||
LocalAddress localAddress =
|
||||
new LocalAddress("CUSTOM_TRUST_MANAGER_WRONG_HOSTNAME_" + sslProvider);
|
||||
|
||||
|
@ -316,19 +328,19 @@ public class SslClientInitializerTest {
|
|||
|
||||
// Set up the server to use the signed cert and private key to perform handshake;
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
nettyRule.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
|
||||
nettyExtension.setUpServer(localAddress, getServerHandler(false, privateKey, cert));
|
||||
|
||||
// Set up the client to trust the self signed cert used to sign the cert that server provides.
|
||||
SslClientInitializer<LocalChannel> sslClientInitializer =
|
||||
new SslClientInitializer<>(
|
||||
sslProvider, hostProvider, portProvider, ImmutableList.of(ssc.cert()), null, null);
|
||||
nettyRule.setUpClient(localAddress, sslClientInitializer);
|
||||
nettyExtension.setUpClient(localAddress, sslClientInitializer);
|
||||
|
||||
// When the client rejects the server cert due to wrong hostname, both the client and server
|
||||
// should throw exceptions.
|
||||
nettyRule.assertThatClientRootCause().isInstanceOf(CertificateException.class);
|
||||
nettyRule.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST);
|
||||
nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class);
|
||||
assertThat(nettyRule.getClientChannel().isActive()).isFalse();
|
||||
nettyExtension.assertThatClientRootCause().isInstanceOf(CertificateException.class);
|
||||
nettyExtension.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST);
|
||||
nettyExtension.assertThatServerRootCause().isInstanceOf(SSLException.class);
|
||||
assertThat(nettyExtension.getClientChannel().isActive()).isFalse();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
package google.registry.networking.handler;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import google.registry.networking.util.SelfSignedCaCertificate;
|
||||
|
|
|
@ -43,17 +43,16 @@ import java.security.cert.X509Certificate;
|
|||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.stream.Stream;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import org.junit.Rule;
|
||||
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;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SslServerInitializer}.
|
||||
|
@ -66,8 +65,7 @@ import org.junit.runners.Parameterized.Parameters;
|
|||
* <p>The local addresses used in each test method must to be different, otherwise tests run in
|
||||
* parallel may interfere with each other.
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class SslServerInitializerTest {
|
||||
class SslServerInitializerTest {
|
||||
|
||||
/** Fake host to test if the SSL engine gets the correct peer host. */
|
||||
private static final String SSL_HOST = "www.example.tld";
|
||||
|
@ -75,22 +73,23 @@ public class SslServerInitializerTest {
|
|||
/** Fake port to test if the SSL engine gets the correct peer port. */
|
||||
private static final int SSL_PORT = 12345;
|
||||
|
||||
@Rule public NettyRule nettyRule = new NettyRule();
|
||||
@RegisterExtension NettyExtension nettyExtension = new NettyExtension();
|
||||
|
||||
@Parameter(0)
|
||||
public SslProvider sslProvider;
|
||||
|
||||
// We do our best effort to test all available SSL providers.
|
||||
@Parameters(name = "{0}")
|
||||
public static SslProvider[] data() {
|
||||
return OpenSsl.isAvailable()
|
||||
? new SslProvider[] {SslProvider.OPENSSL, SslProvider.JDK}
|
||||
: new SslProvider[] {SslProvider.JDK};
|
||||
@SuppressWarnings("unused")
|
||||
static Stream<Arguments> provideTestCombinations() {
|
||||
Stream.Builder<Arguments> args = Stream.builder();
|
||||
// We do our best effort to test all available SSL providers.
|
||||
args.add(Arguments.of(SslProvider.JDK));
|
||||
if (OpenSsl.isAvailable()) {
|
||||
args.add(Arguments.of(SslProvider.OPENSSL));
|
||||
}
|
||||
return args.build();
|
||||
}
|
||||
|
||||
private ChannelHandler getServerHandler(
|
||||
boolean requireClientCert,
|
||||
boolean validateClientCert,
|
||||
SslProvider sslProvider,
|
||||
PrivateKey privateKey,
|
||||
X509Certificate... certificates) {
|
||||
return new SslServerInitializer<LocalChannel>(
|
||||
|
@ -102,7 +101,10 @@ public class SslServerInitializerTest {
|
|||
}
|
||||
|
||||
private ChannelHandler getClientHandler(
|
||||
X509Certificate trustedCertificate, PrivateKey privateKey, X509Certificate certificate) {
|
||||
SslProvider sslProvider,
|
||||
X509Certificate trustedCertificate,
|
||||
PrivateKey privateKey,
|
||||
X509Certificate certificate) {
|
||||
return new ChannelInitializer<LocalChannel>() {
|
||||
@Override
|
||||
protected void initChannel(LocalChannel ch) throws Exception {
|
||||
|
@ -125,8 +127,9 @@ public class SslServerInitializerTest {
|
|||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_swappedInitializerWithSslHandler() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_swappedInitializerWithSslHandler(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate ssc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
SslServerInitializer<EmbeddedChannel> sslServerInitializer =
|
||||
new SslServerInitializer<>(
|
||||
|
@ -145,19 +148,22 @@ public class SslServerInitializerTest {
|
|||
assertThat(channel.isActive()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_trustAnyClientCert() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_trustAnyClientCert(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("TRUST_ANY_CLIENT_CERT_" + sslProvider);
|
||||
|
||||
nettyRule.setUpServer(
|
||||
localAddress, getServerHandler(true, false, serverSsc.key(), serverSsc.cert()));
|
||||
nettyExtension.setUpServer(
|
||||
localAddress,
|
||||
getServerHandler(true, false, sslProvider, serverSsc.key(), serverSsc.cert()));
|
||||
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate.create();
|
||||
nettyRule.setUpClient(
|
||||
localAddress, getClientHandler(serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
|
||||
SSLSession sslSession = setUpSslChannel(nettyRule.getClientChannel(), serverSsc.cert());
|
||||
nettyRule.assertThatMessagesWork();
|
||||
SSLSession sslSession = setUpSslChannel(nettyExtension.getClientChannel(), serverSsc.cert());
|
||||
nettyExtension.assertThatMessagesWork();
|
||||
|
||||
// Verify that the SSL session gets the client cert. Note that this SslSession is for the client
|
||||
// channel, therefore its local certificates are the remote certificates of the SslSession for
|
||||
|
@ -166,59 +172,66 @@ public class SslServerInitializerTest {
|
|||
assertThat(sslSession.getPeerCertificates()).asList().containsExactly(serverSsc.cert());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_clientCertExpired() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_clientCertExpired(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("CLIENT_CERT_EXPIRED_" + sslProvider);
|
||||
|
||||
nettyRule.setUpServer(
|
||||
localAddress, getServerHandler(true, true, serverSsc.key(), serverSsc.cert()));
|
||||
nettyExtension.setUpServer(
|
||||
localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert()));
|
||||
SelfSignedCaCertificate clientSsc =
|
||||
SelfSignedCaCertificate.create(
|
||||
"CLIENT",
|
||||
Date.from(Instant.now().minus(Duration.ofDays(2))),
|
||||
Date.from(Instant.now().minus(Duration.ofDays(1))));
|
||||
nettyRule.setUpClient(
|
||||
localAddress, getClientHandler(serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
|
||||
verifySslException(
|
||||
nettyRule.getServerChannel(),
|
||||
nettyExtension.getServerChannel(),
|
||||
channel -> channel.attr(CLIENT_CERTIFICATE_PROMISE_KEY).get().get(),
|
||||
CertificateExpiredException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_clientCertNotYetValid() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_clientCertNotYetValid(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("CLIENT_CERT_EXPIRED_" + sslProvider);
|
||||
|
||||
nettyRule.setUpServer(
|
||||
localAddress, getServerHandler(true, true, serverSsc.key(), serverSsc.cert()));
|
||||
nettyExtension.setUpServer(
|
||||
localAddress, getServerHandler(true, true, sslProvider, serverSsc.key(), serverSsc.cert()));
|
||||
SelfSignedCaCertificate clientSsc =
|
||||
SelfSignedCaCertificate.create(
|
||||
"CLIENT",
|
||||
Date.from(Instant.now().plus(Duration.ofDays(1))),
|
||||
Date.from(Instant.now().plus(Duration.ofDays(2))));
|
||||
nettyRule.setUpClient(
|
||||
localAddress, getClientHandler(serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
|
||||
verifySslException(
|
||||
nettyRule.getServerChannel(),
|
||||
nettyExtension.getServerChannel(),
|
||||
channel -> channel.attr(CLIENT_CERTIFICATE_PROMISE_KEY).get().get(),
|
||||
CertificateNotYetValidException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_doesNotRequireClientCert() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_doesNotRequireClientCert(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("DOES_NOT_REQUIRE_CLIENT_CERT_" + sslProvider);
|
||||
|
||||
nettyRule.setUpServer(
|
||||
localAddress, getServerHandler(false, false, serverSsc.key(), serverSsc.cert()));
|
||||
nettyRule.setUpClient(localAddress, getClientHandler(serverSsc.cert(), null, null));
|
||||
nettyExtension.setUpServer(
|
||||
localAddress,
|
||||
getServerHandler(false, false, sslProvider, serverSsc.key(), serverSsc.cert()));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress, getClientHandler(sslProvider, serverSsc.cert(), null, null));
|
||||
|
||||
SSLSession sslSession = setUpSslChannel(nettyRule.getClientChannel(), serverSsc.cert());
|
||||
nettyRule.assertThatMessagesWork();
|
||||
SSLSession sslSession = setUpSslChannel(nettyExtension.getClientChannel(), serverSsc.cert());
|
||||
nettyExtension.assertThatMessagesWork();
|
||||
|
||||
// Verify that the SSL session does not contain any client cert. Note that this SslSession is
|
||||
// for the client channel, therefore its local certificates are the remote certificates of the
|
||||
|
@ -227,32 +240,38 @@ public class SslServerInitializerTest {
|
|||
assertThat(sslSession.getPeerCertificates()).asList().containsExactly(serverSsc.cert());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_CertSignedByOtherCA() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testSuccess_CertSignedByOtherCa(SslProvider sslProvider) throws Exception {
|
||||
// The self-signed cert of the CA.
|
||||
SelfSignedCaCertificate caSsc = SelfSignedCaCertificate.create();
|
||||
KeyPair keyPair = getKeyPair();
|
||||
X509Certificate serverCert = signKeyPair(caSsc, keyPair, SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("CERT_SIGNED_BY_OTHER_CA_" + sslProvider);
|
||||
|
||||
nettyRule.setUpServer(
|
||||
nettyExtension.setUpServer(
|
||||
localAddress,
|
||||
getServerHandler(
|
||||
true,
|
||||
false,
|
||||
sslProvider,
|
||||
keyPair.getPrivate(),
|
||||
// Serving both the server cert, and the CA cert
|
||||
serverCert,
|
||||
caSsc.cert()));
|
||||
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate.create();
|
||||
nettyRule.setUpClient(
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(
|
||||
sslProvider,
|
||||
// Client trusts the CA cert
|
||||
caSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
caSsc.cert(),
|
||||
clientSsc.key(),
|
||||
clientSsc.cert()));
|
||||
|
||||
SSLSession sslSession = setUpSslChannel(nettyRule.getClientChannel(), serverCert, caSsc.cert());
|
||||
nettyRule.assertThatMessagesWork();
|
||||
SSLSession sslSession =
|
||||
setUpSslChannel(nettyExtension.getClientChannel(), serverCert, caSsc.cert());
|
||||
nettyExtension.assertThatMessagesWork();
|
||||
|
||||
assertThat(sslSession.getLocalCertificates()).asList().containsExactly(clientSsc.cert());
|
||||
assertThat(sslSession.getPeerCertificates())
|
||||
|
@ -261,16 +280,19 @@ public class SslServerInitializerTest {
|
|||
.inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_requireClientCertificate() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_requireClientCertificate(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create(SSL_HOST);
|
||||
LocalAddress localAddress = new LocalAddress("REQUIRE_CLIENT_CERT_" + sslProvider);
|
||||
|
||||
nettyRule.setUpServer(
|
||||
localAddress, getServerHandler(true, false, serverSsc.key(), serverSsc.cert()));
|
||||
nettyRule.setUpClient(
|
||||
nettyExtension.setUpServer(
|
||||
localAddress,
|
||||
getServerHandler(true, false, sslProvider, serverSsc.key(), serverSsc.cert()));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(
|
||||
sslProvider,
|
||||
serverSsc.cert(),
|
||||
// No client cert/private key used.
|
||||
null,
|
||||
|
@ -278,27 +300,30 @@ public class SslServerInitializerTest {
|
|||
|
||||
// When the server rejects the client during handshake due to lack of client certificate, both
|
||||
// should throw exceptions.
|
||||
nettyRule.assertThatServerRootCause().isInstanceOf(SSLHandshakeException.class);
|
||||
nettyRule.assertThatClientRootCause().isInstanceOf(SSLException.class);
|
||||
assertThat(nettyRule.getClientChannel().isActive()).isFalse();
|
||||
nettyExtension.assertThatServerRootCause().isInstanceOf(SSLHandshakeException.class);
|
||||
nettyExtension.assertThatClientRootCause().isInstanceOf(SSLException.class);
|
||||
assertThat(nettyExtension.getClientChannel().isActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_wrongHostnameInCertificate() throws Exception {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideTestCombinations")
|
||||
void testFailure_wrongHostnameInCertificate(SslProvider sslProvider) throws Exception {
|
||||
SelfSignedCaCertificate serverSsc = SelfSignedCaCertificate.create("wrong.com");
|
||||
LocalAddress localAddress = new LocalAddress("WRONG_HOSTNAME_" + sslProvider);
|
||||
|
||||
nettyRule.setUpServer(
|
||||
localAddress, getServerHandler(true, false, serverSsc.key(), serverSsc.cert()));
|
||||
nettyExtension.setUpServer(
|
||||
localAddress,
|
||||
getServerHandler(true, false, sslProvider, serverSsc.key(), serverSsc.cert()));
|
||||
SelfSignedCaCertificate clientSsc = SelfSignedCaCertificate.create();
|
||||
nettyRule.setUpClient(
|
||||
localAddress, getClientHandler(serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
nettyExtension.setUpClient(
|
||||
localAddress,
|
||||
getClientHandler(sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert()));
|
||||
|
||||
// When the client rejects the server cert due to wrong hostname, both the server and the client
|
||||
// throw exceptions.
|
||||
nettyRule.assertThatClientRootCause().isInstanceOf(CertificateException.class);
|
||||
nettyRule.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST);
|
||||
nettyRule.assertThatServerRootCause().isInstanceOf(SSLException.class);
|
||||
assertThat(nettyRule.getClientChannel().isActive()).isFalse();
|
||||
nettyExtension.assertThatClientRootCause().isInstanceOf(CertificateException.class);
|
||||
nettyExtension.assertThatClientRootCause().hasMessageThat().contains(SSL_HOST);
|
||||
nettyExtension.assertThatServerRootCause().isInstanceOf(SSLException.class);
|
||||
assertThat(nettyExtension.getClientChannel().isActive()).isFalse();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import static google.registry.networking.handler.SslInitializerTestUtils.getKeyPair;
|
||||
import static google.registry.networking.handler.SslInitializerTestUtils.signKeyPair;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import dagger.BindsInstance;
|
||||
|
@ -38,14 +38,11 @@ import java.util.function.Supplier;
|
|||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link CertificateSupplierModule}. */
|
||||
@RunWith(JUnit4.class)
|
||||
public class CertificateSupplierModuleTest {
|
||||
class CertificateSupplierModuleTest {
|
||||
|
||||
private SelfSignedCaCertificate ssc;
|
||||
private PrivateKey key;
|
||||
|
@ -60,8 +57,8 @@ public class CertificateSupplierModuleTest {
|
|||
.build();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@BeforeEach
|
||||
void beforeEach() throws Exception {
|
||||
ssc = SelfSignedCaCertificate.create();
|
||||
KeyPair keyPair = getKeyPair();
|
||||
key = keyPair.getPrivate();
|
||||
|
@ -69,14 +66,14 @@ public class CertificateSupplierModuleTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess() throws Exception {
|
||||
void testSuccess() throws Exception {
|
||||
component = createComponentForPem(cert, ssc.cert(), key);
|
||||
assertThat(component.privateKeySupplier().get()).isEqualTo(key);
|
||||
assertThat(component.certificatesSupplier().get()).containsExactly(cert, ssc.cert()).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuccess_certificateChainNotContinuous() throws Exception {
|
||||
void testSuccess_certificateChainNotContinuous() throws Exception {
|
||||
component = createComponentForPem(cert, key, ssc.cert());
|
||||
assertThat(component.privateKeySupplier().get()).isEqualTo(key);
|
||||
assertThat(component.certificatesSupplier().get()).containsExactly(cert, ssc.cert()).inOrder();
|
||||
|
@ -84,7 +81,7 @@ public class CertificateSupplierModuleTest {
|
|||
|
||||
@Test
|
||||
@SuppressWarnings("ReturnValueIgnored")
|
||||
public void testFailure_noPrivateKey() throws Exception {
|
||||
void testFailure_noPrivateKey() throws Exception {
|
||||
component = createComponentForPem(cert, ssc.cert());
|
||||
IllegalStateException thrown =
|
||||
assertThrows(IllegalStateException.class, () -> component.privateKeySupplier().get());
|
||||
|
@ -93,7 +90,7 @@ public class CertificateSupplierModuleTest {
|
|||
|
||||
@Test
|
||||
@SuppressWarnings("ReturnValueIgnored")
|
||||
public void testFailure_twoPrivateKeys() throws Exception {
|
||||
void testFailure_twoPrivateKeys() throws Exception {
|
||||
component = createComponentForPem(cert, ssc.cert(), key, ssc.key());
|
||||
IllegalStateException thrown =
|
||||
assertThrows(IllegalStateException.class, () -> component.privateKeySupplier().get());
|
||||
|
@ -102,7 +99,7 @@ public class CertificateSupplierModuleTest {
|
|||
|
||||
@Test
|
||||
@SuppressWarnings("ReturnValueIgnored")
|
||||
public void testFailure_certificatesOutOfOrder() throws Exception {
|
||||
void testFailure_certificatesOutOfOrder() throws Exception {
|
||||
component = createComponentForPem(ssc.cert(), cert, key);
|
||||
IllegalStateException thrown =
|
||||
assertThrows(IllegalStateException.class, () -> component.certificatesSupplier().get());
|
||||
|
@ -111,7 +108,7 @@ public class CertificateSupplierModuleTest {
|
|||
|
||||
@Test
|
||||
@SuppressWarnings("ReturnValueIgnored")
|
||||
public void testFailure_noCertificates() throws Exception {
|
||||
void testFailure_noCertificates() throws Exception {
|
||||
component = createComponentForPem(key);
|
||||
IllegalStateException thrown =
|
||||
assertThrows(IllegalStateException.class, () -> component.certificatesSupplier().get());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue