diff --git a/driver/src/main/java/org/neo4j/driver/internal/security/TLSSocketChannel.java b/driver/src/main/java/org/neo4j/driver/internal/security/TLSSocketChannel.java index a0e2dc8ada..923399e067 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/security/TLSSocketChannel.java +++ b/driver/src/main/java/org/neo4j/driver/internal/security/TLSSocketChannel.java @@ -30,6 +30,7 @@ import org.neo4j.driver.v1.Logger; import org.neo4j.driver.internal.util.BytePrinter; import org.neo4j.driver.v1.exceptions.ClientException; +import org.neo4j.driver.v1.exceptions.ServiceUnavailableException; import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED; import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING; @@ -163,7 +164,8 @@ private HandshakeStatus unwrap( ByteBuffer buffer ) throws IOException */ if ( channel.read( cipherIn ) < 0 ) { - throw new ClientException( "SSL Connection terminated while receiving data. " + + throw new ServiceUnavailableException( + "SSL Connection terminated while receiving data. " + "This can happen due to network instabilities, or due to restarts of the database." ); } cipherIn.flip(); diff --git a/driver/src/test/java/org/neo4j/driver/v1/integration/ServerKilledIT.java b/driver/src/test/java/org/neo4j/driver/v1/integration/ServerKilledIT.java index 26ad9af44c..6aaa6ea881 100644 --- a/driver/src/test/java/org/neo4j/driver/v1/integration/ServerKilledIT.java +++ b/driver/src/test/java/org/neo4j/driver/v1/integration/ServerKilledIT.java @@ -20,7 +20,12 @@ import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.concurrent.TimeUnit; @@ -43,19 +48,33 @@ * Mainly concerned about the connection pool - we want to make sure that bad connections are evacuated from the * pool properly if the server dies, or all connections are lost for some other reason. */ +@RunWith(Parameterized.class) public class ServerKilledIT { @Rule public TestNeo4j neo4j = new TestNeo4j(); + @Parameters(name = "{0} connections") + public static Collection data() { + return Arrays.asList(new Object[][] { + { "plaintext", Config.EncryptionLevel.NONE }, + { "tls encrypted", Config.EncryptionLevel.REQUIRED } + }); + } + + private Config.EncryptionLevel encryptionLevel; + + public ServerKilledIT( String testName, Config.EncryptionLevel encryptionLevel ) + { + this.encryptionLevel = encryptionLevel; + } + @Test public void shouldRecoverFromServerRestart() throws Throwable { // Given // config with sessionLivenessCheckTimeout not set, i.e. turned off - Config config = Config.build() - .withEncryptionLevel( Config.EncryptionLevel.NONE ) - .toConfig(); + Config config = Config.build().withEncryptionLevel( encryptionLevel ).toConfig(); try ( Driver driver = GraphDatabase.driver( Neo4jRunner.DEFAULT_URI, config ) ) { @@ -77,8 +96,7 @@ public void shouldRecoverFromServerRestart() throws Throwable if ( toleratedFailures-- == 0 ) { fail( "Expected (for now) at most four failures, one for each old connection, but now I've " + - "gotten " + - "five: " + e.getMessage() ); + "gotten " + "five: " + e.getMessage() ); } } } @@ -95,9 +113,8 @@ public void shouldDropBrokenOldSessions() throws Throwable { // config with set liveness check timeout int livenessCheckTimeoutMinutes = 10; - Config config = Config.build() + Config config = Config.build().withEncryptionLevel( encryptionLevel ) .withConnectionLivenessCheckTimeout( livenessCheckTimeoutMinutes, TimeUnit.MINUTES ) - .withEncryptionLevel( Config.EncryptionLevel.NONE ) .toConfig(); FakeClock clock = new FakeClock();