Skip to content

Commit

Permalink
Update JDK SSL Tests to use SSL Context Builder.
Browse files Browse the repository at this point in the history
Motivation: 

Use new / non-deprecated APIs for creating SSL Context
in tests, in order to be able to implement OpenSsl
tests with maximum code reuse.

Modifications: 

Use `SslContextBuilder.(forServer|forClient)` instead
of deprecated `JdkSslServerContext` constructor. 
Use `ApplicationProtocolConfig` instead of Protocol
Negotiator. 
Use custom exception type for skipping tests to avoid
swallowing exceptions arising from tests.

Result:
 
Exceptions from tests aren't swallowed.
Using new APIs allows reusing same test code for 
OpenSsl tests.
  • Loading branch information
ifesdjeen committed Dec 4, 2015
1 parent e4b716a commit 7e101e1
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 47 deletions.
134 changes: 95 additions & 39 deletions handler/src/test/java/io/netty/handler/ssl/JdkSslEngineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectorFactory;
import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.NetUtil;
Expand Down Expand Up @@ -59,13 +62,13 @@ public void testNpn() throws Exception {
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkNpnSslEngine.isAvailable()) {
throw new RuntimeException("NPN not on classpath");
throw tlsExtensionNotFound(Protocol.NPN);
}
JdkApplicationProtocolNegotiator apn = new JdkNpnApplicationProtocolNegotiator(true, true,
ApplicationProtocolConfig apn = failingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
mySetup(apn);
runTest();
} catch (RuntimeException e) {
} catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
Expand All @@ -79,15 +82,15 @@ public void testNpnNoCompatibleProtocolsNoHandshakeFailure() throws Exception {
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkNpnSslEngine.isAvailable()) {
throw new RuntimeException("NPN not on classpath");
throw tlsExtensionNotFound(Protocol.NPN);
}
JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false,
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false,
ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn);
runTest(null);
} catch (Exception e) {
} catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
Expand All @@ -101,16 +104,16 @@ public void testNpnNoCompatibleProtocolsClientHandshakeFailure() throws Exceptio
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkNpnSslEngine.isAvailable()) {
throw new RuntimeException("NPN not on classpath");
throw tlsExtensionNotFound(Protocol.NPN);
}
JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(true, true,
ApplicationProtocolConfig clientApn = failingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false,
ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn);
assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
assertTrue(clientException instanceof SSLHandshakeException);
} catch (RuntimeException e) {
} catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
Expand All @@ -124,16 +127,16 @@ public void testNpnNoCompatibleProtocolsServerHandshakeFailure() throws Exceptio
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkNpnSslEngine.isAvailable()) {
throw new RuntimeException("NPN not on classpath");
throw tlsExtensionNotFound(Protocol.NPN);
}
JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false,
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(true, true,
ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn);
assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
assertTrue(serverException instanceof SSLHandshakeException);
} catch (RuntimeException e) {
} catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
Expand All @@ -147,13 +150,13 @@ public void testAlpn() throws Exception {
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath");
throw tlsExtensionNotFound(Protocol.ALPN);
}
JdkApplicationProtocolNegotiator apn = new JdkAlpnApplicationProtocolNegotiator(true, true,
ApplicationProtocolConfig apn = failingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
mySetup(apn);
runTest();
} catch (Exception e) {
} catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
Expand All @@ -167,15 +170,15 @@ public void testAlpnNoCompatibleProtocolsNoHandshakeFailure() throws Exception {
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath");
throw tlsExtensionNotFound(Protocol.ALPN);
}
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false,
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(false, false,
ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.ALPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn);
runTest(null);
} catch (Exception e) {
} catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
Expand All @@ -189,16 +192,16 @@ public void testAlpnNoCompatibleProtocolsServerHandshakeFailure() throws Excepti
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath");
throw tlsExtensionNotFound(Protocol.ALPN);
}
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false,
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true,
ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn);
assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
assertTrue(serverException instanceof SSLHandshakeException);
} catch (Exception e) {
} catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
Expand All @@ -212,18 +215,18 @@ public void testAlpnCompatibleProtocolsDifferentClientOrder() throws Exception {
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath");
throw tlsExtensionNotFound(Protocol.ALPN);
}
// Even the preferred application protocol appears second in the client's list, it will be picked
// because it's the first one on server's list.
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false,
ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true,
ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL);
mySetup(serverApn, clientApn);
assertNull(serverException);
runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL);
} catch (Exception e) {
} catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
Expand All @@ -237,8 +240,9 @@ public void testAlpnNoCompatibleProtocolsClientHandshakeFailure() throws Excepti
// Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error.
if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath");
throw tlsExtensionNotFound(Protocol.ALPN);
}
SelfSignedCertificate ssc = new SelfSignedCertificate();
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(true, true,
PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(
Expand All @@ -258,28 +262,54 @@ public String select(List<String> protocols) {
}
}, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn);

SslContext serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null,
IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0);
SslContext clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null,
IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0);

mySetup(serverSslCtx, clientSslCtx);
assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
assertTrue(clientException instanceof SSLHandshakeException);
} catch (Exception e) {
} catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e);
}
}

private void mySetup(JdkApplicationProtocolNegotiator apn) throws InterruptedException, SSLException,
private void mySetup(ApplicationProtocolConfig apn) throws InterruptedException, SSLException,
CertificateException {
mySetup(apn, apn);
}

private void mySetup(JdkApplicationProtocolNegotiator serverApn, JdkApplicationProtocolNegotiator clientApn)
private void mySetup(ApplicationProtocolConfig serverApn, ApplicationProtocolConfig clientApn)
throws InterruptedException, SSLException, CertificateException {
SelfSignedCertificate ssc = new SelfSignedCertificate();
serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null,
IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0);
clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null,
IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0);

mySetup(SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null)
.sslProvider(sslProvider())
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.applicationProtocolConfig(serverApn)
.sessionCacheSize(0)
.sessionTimeout(0)
.build(),

SslContextBuilder.forClient()
.sslProvider(sslProvider())
.applicationProtocolConfig(clientApn)
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.sessionCacheSize(0)
.sessionTimeout(0)
.build());
}

private void mySetup(SslContext serverCtx, SslContext clientCtx)
throws InterruptedException, SSLException, CertificateException {

serverSslCtx = serverCtx;
clientSslCtx = clientCtx;

serverConnectedChannel = null;
sb = new ServerBootstrap();
Expand Down Expand Up @@ -346,4 +376,30 @@ private void runTest() throws Exception {
protected SslProvider sslProvider() {
return SslProvider.JDK;
}

private ApplicationProtocolConfig failingNegotiator(Protocol protocol,
String... supportedProtocols) {
return new ApplicationProtocolConfig(protocol,
SelectorFailureBehavior.FATAL_ALERT,
SelectedListenerFailureBehavior.FATAL_ALERT,
supportedProtocols);
}

private ApplicationProtocolConfig acceptingNegotiator(Protocol protocol,
String... supportedProtocols) {
return new ApplicationProtocolConfig(protocol,
SelectorFailureBehavior.NO_ADVERTISE,
SelectedListenerFailureBehavior.ACCEPT,
supportedProtocols);
}

private SkipTestException tlsExtensionNotFound(Protocol protocol) {
throw new SkipTestException(protocol + " not on classpath");
}

private static final class SkipTestException extends RuntimeException {
public SkipTestException(String message) {
super(message);
}
}
}
23 changes: 16 additions & 7 deletions handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,22 @@ private void mySetupMutualAuth(
File servertTrustCrtFile, File serverKeyFile, File serverCrtFile, String serverKeyPassword,
File clientTrustCrtFile, File clientKeyFile, File clientCrtFile, String clientKeyPassword)
throws InterruptedException, SSLException {
serverSslCtx = SslContext.newServerContext(sslProvider(), servertTrustCrtFile, null,
serverCrtFile, serverKeyFile, serverKeyPassword, null,
null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0);
clientSslCtx = SslContext.newClientContext(sslProvider(), clientTrustCrtFile, null,
clientCrtFile, clientKeyFile, clientKeyPassword, null,
null, IdentityCipherSuiteFilter.INSTANCE,
null, 0, 0);
serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, serverKeyPassword)
.sslProvider(sslProvider())
.trustManager(servertTrustCrtFile)
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.sessionCacheSize(0)
.sessionTimeout(0)
.build();

clientSslCtx = SslContextBuilder.forClient()
.sslProvider(sslProvider())
.trustManager(clientTrustCrtFile)
.keyManager(clientCrtFile, clientKeyFile, clientKeyPassword)
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.sessionCacheSize(0)
.sessionTimeout(0)
.build();

serverConnectedChannel = null;
sb = new ServerBootstrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private static SslContext makeSslContext() throws Exception {
File keyFile = new File(SniHandlerTest.class.getResource("test_encrypted.pem").getFile());
File crtFile = new File(SniHandlerTest.class.getResource("test.crt").getFile());

return new JdkSslServerContext(crtFile, keyFile, "12345");
return SslContextBuilder.forServer(crtFile, keyFile, "12345").build();
}

@Test
Expand Down

2 comments on commit 7e101e1

@netkins
Copy link

@netkins netkins commented on 7e101e1 Dec 4, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TeamCity pull requests :: netty Build 789 is now running

@netkins
Copy link

@netkins netkins commented on 7e101e1 Dec 4, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TeamCity pull requests :: netty Build 789 outcome was SUCCESS
Summary: Tests passed: 5291, ignored: 21 Build time: 00:15:17

Please sign in to comment.