diff --git a/driver/src/test/java/org/neo4j/driver/integration/RoutingDriverBoltKitTest.java b/driver/src/test/java/org/neo4j/driver/integration/RoutingDriverBoltKitTest.java index f31e5da9c4..36afe38eb2 100644 --- a/driver/src/test/java/org/neo4j/driver/integration/RoutingDriverBoltKitTest.java +++ b/driver/src/test/java/org/neo4j/driver/integration/RoutingDriverBoltKitTest.java @@ -18,6 +18,8 @@ */ package org.neo4j.driver.integration; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -57,6 +59,7 @@ import org.neo4j.driver.net.ServerAddress; import org.neo4j.driver.net.ServerAddressResolver; import org.neo4j.driver.util.StubServer; +import org.neo4j.driver.util.StubServerController; import static java.util.Arrays.asList; import static java.util.Collections.singleton; @@ -82,14 +85,28 @@ class RoutingDriverBoltKitTest { + private static StubServerController stubController; + + @BeforeAll + public static void setup() + { + stubController = new StubServerController(); + } + + @AfterEach + public void killServers() + { + stubController.reset(); + } + @Test void shouldHandleAcquireReadSession() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a read server - StubServer readServer = StubServer.start( "read_server_v3_read.script", 9005 ); + StubServer readServer = stubController.startStub( "read_server_v3_read.script", 9005 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); Session session = driver.session( builder().withDefaultAccessMode( AccessMode.READ ).build() ) ) @@ -107,10 +124,10 @@ void shouldHandleAcquireReadSession() throws IOException, InterruptedException, void shouldHandleAcquireReadTransaction() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a read server - StubServer readServer = StubServer.start( "read_server_v3_read_tx.script", 9005 ); + StubServer readServer = stubController.startStub( "read_server_v3_read_tx.script", 9005 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); Session session = driver.session( builder().withDefaultAccessMode( AccessMode.READ ).build() ) ) @@ -130,10 +147,10 @@ void shouldHandleAcquireReadTransaction() throws IOException, InterruptedExcepti void shouldHandleAcquireReadSessionAndTransaction() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a read server - StubServer readServer = StubServer.start( "read_server_v3_read_tx.script", 9005 ); + StubServer readServer = stubController.startStub( "read_server_v3_read_tx.script", 9005 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); Session session = driver.session( builder().withDefaultAccessMode( AccessMode.READ ).build() ); @@ -153,11 +170,11 @@ void shouldHandleAcquireReadSessionAndTransaction() throws IOException, Interrup void shouldRoundRobinReadServers() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START two read servers - StubServer readServer1 = StubServer.start( "read_server_v3_read.script", 9005 ); - StubServer readServer2 = StubServer.start( "read_server_v3_read.script", 9006 ); + StubServer readServer1 = stubController.startStub( "read_server_v3_read.script", 9005 ); + StubServer readServer2 = stubController.startStub( "read_server_v3_read.script", 9006 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ) ) { @@ -181,11 +198,11 @@ void shouldRoundRobinReadServers() throws IOException, InterruptedException, Stu void shouldRoundRobinReadServersWhenUsingTransaction() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START two read servers - StubServer readServer1 = StubServer.start( "read_server_v3_read_tx.script", 9005 ); - StubServer readServer2 = StubServer.start( "read_server_v3_read_tx.script", 9006 ); + StubServer readServer1 = stubController.startStub( "read_server_v3_read_tx.script", 9005 ); + StubServer readServer2 = stubController.startStub( "read_server_v3_read_tx.script", 9006 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ) ) { @@ -210,10 +227,10 @@ void shouldRoundRobinReadServersWhenUsingTransaction() throws IOException, Inter void shouldThrowSessionExpiredIfReadServerDisappears() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a read server - final StubServer readServer = StubServer.start( "dead_read_server.script", 9005 ); + final StubServer readServer = stubController.startStub( "dead_read_server.script", 9005 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); //Expect @@ -232,10 +249,10 @@ void shouldThrowSessionExpiredIfReadServerDisappears() throws IOException, Inter void shouldThrowSessionExpiredIfReadServerDisappearsWhenUsingTransaction() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a read server - final StubServer readServer = StubServer.start( "dead_read_server_tx.script", 9005 ); + final StubServer readServer = stubController.startStub( "dead_read_server_tx.script", 9005 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); //Expect @@ -257,10 +274,10 @@ void shouldThrowSessionExpiredIfReadServerDisappearsWhenUsingTransaction() throw void shouldThrowSessionExpiredIfWriteServerDisappears() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a dead write server - final StubServer writeServer = StubServer.start( "dead_write_server.script", 9007 ); + final StubServer writeServer = stubController.startStub( "dead_write_server.script", 9007 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); //Expect @@ -280,10 +297,10 @@ void shouldThrowSessionExpiredIfWriteServerDisappears() throws IOException, Inte void shouldThrowSessionExpiredIfWriteServerDisappearsWhenUsingTransaction() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a dead write servers - final StubServer writeServer = StubServer.start( "dead_read_server_tx.script", 9007 ); + final StubServer writeServer = stubController.startStub( "dead_read_server_tx.script", 9007 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); //Expect @@ -304,10 +321,10 @@ void shouldThrowSessionExpiredIfWriteServerDisappearsWhenUsingTransaction() thro void shouldHandleAcquireWriteSession() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a write server - StubServer writeServer = StubServer.start( "write_server_v3_write.script", 9007 ); + StubServer writeServer = stubController.startStub( "write_server_v3_write.script", 9007 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).build() ) ) @@ -323,10 +340,10 @@ void shouldHandleAcquireWriteSession() throws IOException, InterruptedException, void shouldHandleAcquireWriteTransaction() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a write server - StubServer writeServer = StubServer.start( "write_server_v3_write_tx.script", 9007 ); + StubServer writeServer = stubController.startStub( "write_server_v3_write_tx.script", 9007 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); Session session = driver.session() ) { @@ -341,10 +358,10 @@ void shouldHandleAcquireWriteTransaction() throws IOException, InterruptedExcept void shouldHandleAcquireWriteSessionAndTransaction() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a write server - StubServer writeServer = StubServer.start( "write_server_v3_write_tx.script", 9007 ); + StubServer writeServer = stubController.startStub( "write_server_v3_write_tx.script", 9007 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).build() ); @@ -362,11 +379,11 @@ void shouldHandleAcquireWriteSessionAndTransaction() throws IOException, Interru void shouldRoundRobinWriteSessions() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a write server - StubServer writeServer1 = StubServer.start( "write_server_v3_write.script", 9007 ); - StubServer writeServer2 = StubServer.start( "write_server_v3_write.script", 9008 ); + StubServer writeServer1 = stubController.startStub( "write_server_v3_write.script", 9007 ); + StubServer writeServer2 = stubController.startStub( "write_server_v3_write.script", 9008 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ) ) { @@ -388,11 +405,11 @@ void shouldRoundRobinWriteSessions() throws IOException, InterruptedException, S void shouldRoundRobinWriteSessionsInTransaction() throws Exception { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a write server - StubServer writeServer1 = StubServer.start( "write_server_v3_write_tx.script", 9007 ); - StubServer writeServer2 = StubServer.start( "write_server_v3_write_tx.script", 9008 ); + StubServer writeServer1 = stubController.startStub( "write_server_v3_write_tx.script", 9007 ); + StubServer writeServer2 = stubController.startStub( "write_server_v3_write_tx.script", 9008 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ) ) { @@ -415,7 +432,8 @@ void shouldRoundRobinWriteSessionsInTransaction() throws Exception void shouldFailOnNonDiscoverableServer() throws IOException, InterruptedException { // Given - StubServer.start( "discover_not_supported_9001.script", 9001 ); + stubController.startStub( "discover_not_supported_9001.script", 9001 ); + URI uri = URI.create( "neo4j://127.0.0.1:9001" ); final Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); @@ -427,7 +445,7 @@ void shouldFailOnNonDiscoverableServer() throws IOException, InterruptedExceptio void shouldFailRandomFailureInGetServers() throws IOException, InterruptedException { // Given - StubServer.start( "discover_failed.script", 9001 ); + stubController.startStub( "discover_failed.script", 9001 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); final Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); @@ -439,10 +457,10 @@ void shouldFailRandomFailureInGetServers() throws IOException, InterruptedExcept void shouldHandleLeaderSwitchWhenWriting() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a write server that doesn't accept writes - StubServer.start( "not_able_to_write_server.script", 9007 ); + stubController.startStub( "not_able_to_write_server.script", 9007 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); boolean failed = false; @@ -466,10 +484,10 @@ void shouldHandleLeaderSwitchWhenWriting() throws IOException, InterruptedExcept void shouldHandleLeaderSwitchWhenWritingWithoutConsuming() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a write server that doesn't accept writes - StubServer.start( "not_able_to_write_server.script", 9007 ); + stubController.startStub( "not_able_to_write_server.script", 9007 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); boolean failed = false; @@ -493,10 +511,10 @@ void shouldHandleLeaderSwitchWhenWritingWithoutConsuming() throws IOException, I void shouldHandleLeaderSwitchWhenWritingInTransaction() throws IOException, InterruptedException, StubServer.ForceKilled { // Given - StubServer server = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer server = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); //START a write server that doesn't accept writes - StubServer.start( "not_able_to_write_server.script", 9007 ); + stubController.startStub( "not_able_to_write_server.script", 9007 ); URI uri = URI.create( "neo4j://127.0.0.1:9001" ); Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); boolean failed = false; @@ -519,8 +537,8 @@ void shouldHandleLeaderSwitchWhenWritingInTransaction() throws IOException, Inte @Test void shouldSendInitialBookmark() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer writer = StubServer.start( "write_tx_with_bookmarks.script", 9007 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer writer = stubController.startStub( "write_tx_with_bookmarks.script", 9007 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9001", INSECURE_CONFIG ); Session session = driver.session( builder().withBookmarks( parse( "OldBookmark" ) ).build() ) ) @@ -541,8 +559,8 @@ void shouldSendInitialBookmark() throws Exception @Test void shouldUseWriteSessionModeAndInitialBookmark() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer writer = StubServer.start( "write_tx_with_bookmarks.script", 9008 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer writer = stubController.startStub( "write_tx_with_bookmarks.script", 9008 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9001", INSECURE_CONFIG ); Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).withBookmarks( parse( "OldBookmark" ) ).build() ) ) @@ -563,8 +581,8 @@ void shouldUseWriteSessionModeAndInitialBookmark() throws Exception @Test void shouldUseReadSessionModeAndInitialBookmark() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer writer = StubServer.start( "read_tx_with_bookmarks.script", 9005 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer writer = stubController.startStub( "read_tx_with_bookmarks.script", 9005 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9001", INSECURE_CONFIG ); Session session = driver.session( builder().withDefaultAccessMode( AccessMode.READ ).withBookmarks( parse( "OldBookmark" ) ).build() ) ) @@ -588,8 +606,8 @@ void shouldUseReadSessionModeAndInitialBookmark() throws Exception @Test void shouldPassBookmarkFromTransactionToTransaction() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer writer = StubServer.start( "write_read_tx_with_bookmarks.script", 9007 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer writer = stubController.startStub( "write_read_tx_with_bookmarks.script", 9007 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9001", INSECURE_CONFIG ); Session session = driver.session( builder().withBookmarks( parse( "BookmarkA" ) ).build() ) ) @@ -620,9 +638,9 @@ void shouldPassBookmarkFromTransactionToTransaction() throws Exception @Test void shouldRetryReadTransactionUntilSuccess() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer brokenReader = StubServer.start( "dead_read_server_tx.script", 9005 ); - StubServer reader = StubServer.start( "read_server_v3_read_tx.script", 9006 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer brokenReader = stubController.startStub( "dead_read_server_tx.script", 9005 ); + StubServer reader = stubController.startStub( "read_server_v3_read_tx.script", 9006 ); try ( Driver driver = newDriverWithSleeplessClock( "neo4j://127.0.0.1:9001" ); Session session = driver.session() ) { @@ -643,9 +661,9 @@ void shouldRetryReadTransactionUntilSuccess() throws Exception @Test void shouldRetryWriteTransactionUntilSuccess() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer brokenWriter = StubServer.start( "dead_write_server.script", 9007 ); - StubServer writer = StubServer.start( "write_server_v3_write_tx.script", 9008 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer brokenWriter = stubController.startStub( "dead_write_server.script", 9007 ); + StubServer writer = stubController.startStub( "write_server_v3_write_tx.script", 9008 ); try ( Driver driver = newDriverWithSleeplessClock( "neo4j://127.0.0.1:9001" ); Session session = driver.session() ) { @@ -672,9 +690,9 @@ void shouldRetryWriteTransactionUntilSuccessWithWhenLeaderIsRemoved() throws Exc // Then at the second time the router returns the same RT with the killed writer inside. // At the third round, the router removes the the writer server from RT reply. // Finally, the router returns a RT with a reachable writer. - StubServer router = StubServer.start( "acquire_endpoints_v3_leader_killed.script", 9001 ); - StubServer brokenWriter = StubServer.start( "dead_write_server.script", 9004 ); - StubServer writer = StubServer.start( "write_server_v3_write_tx.script", 9008 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3_leader_killed.script", 9001 ); + StubServer brokenWriter = stubController.startStub( "dead_write_server.script", 9004 ); + StubServer writer = stubController.startStub( "write_server_v3_write_tx.script", 9008 ); Logger logger = mock( Logger.class ); Config config = insecureBuilder().withLogging( ignored -> logger ).build(); @@ -706,9 +724,9 @@ void shouldRetryWriteTransactionUntilSuccessWithWhenLeaderIsRemovedV3() throws E // Then at the second time the router returns the same RT with the killed writer inside. // At the third round, the router removes the the writer server from RT reply. // Finally, the router returns a RT with a reachable writer. - StubServer router = StubServer.start( "acquire_endpoints_v3_leader_killed.script", 9001 ); - StubServer brokenWriter = StubServer.start( "database_shutdown_at_commit.script", 9004 ); - StubServer writer = StubServer.start( "write_server_v3_write_tx.script", 9008 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3_leader_killed.script", 9001 ); + StubServer brokenWriter = stubController.startStub( "database_shutdown_at_commit.script", 9004 ); + StubServer writer = stubController.startStub( "write_server_v3_write_tx.script", 9008 ); Logger logger = mock( Logger.class ); Config config = insecureBuilder().withLogging( ignored -> logger ).build(); @@ -735,9 +753,9 @@ void shouldRetryWriteTransactionUntilSuccessWithWhenLeaderIsRemovedV3() throws E @Test void shouldRetryReadTransactionUntilFailure() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer brokenReader1 = StubServer.start( "dead_read_server_tx.script", 9005 ); - StubServer brokenReader2 = StubServer.start( "dead_read_server_tx.script", 9006 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer brokenReader1 = stubController.startStub( "dead_read_server_tx.script", 9005 ); + StubServer brokenReader2 = stubController.startStub( "dead_read_server_tx.script", 9006 ); try ( Driver driver = newDriverWithFixedRetries( "neo4j://127.0.0.1:9001", 1 ); Session session = driver.session() ) @@ -757,9 +775,9 @@ void shouldRetryReadTransactionUntilFailure() throws Exception @Test void shouldRetryWriteTransactionUntilFailure() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer brokenWriter1 = StubServer.start( "dead_write_server.script", 9007 ); - StubServer brokenWriter2 = StubServer.start( "dead_write_server.script", 9008 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer brokenWriter1 = stubController.startStub( "dead_write_server.script", 9007 ); + StubServer brokenWriter2 = stubController.startStub( "dead_write_server.script", 9008 ); try ( Driver driver = newDriverWithFixedRetries( "neo4j://127.0.0.1:9001", 1 ); Session session = driver.session() ) { @@ -778,11 +796,11 @@ void shouldRetryWriteTransactionUntilFailure() throws Exception @Test void shouldRetryReadTransactionAndPerformRediscoveryUntilSuccess() throws Exception { - StubServer router1 = StubServer.start( "acquire_endpoints_v3_9010.script", 9010 ); - StubServer brokenReader1 = StubServer.start( "dead_read_server_tx.script", 9005 ); - StubServer brokenReader2 = StubServer.start( "dead_read_server_tx.script", 9006 ); - StubServer router2 = StubServer.start( "discover_servers_9010.script", 9003 ); - StubServer reader = StubServer.start( "read_server_v3_read_tx.script", 9004 ); + StubServer router1 = stubController.startStub( "acquire_endpoints_v3_9010.script", 9010 ); + StubServer brokenReader1 = stubController.startStub( "dead_read_server_tx.script", 9005 ); + StubServer brokenReader2 = stubController.startStub( "dead_read_server_tx.script", 9006 ); + StubServer router2 = stubController.startStub( "discover_servers_9010.script", 9003 ); + StubServer reader = stubController.startStub( "read_server_v3_read_tx.script", 9004 ); try ( Driver driver = newDriverWithSleeplessClock( "neo4j://127.0.0.1:9010" ); Session session = driver.session() ) { @@ -805,11 +823,11 @@ void shouldRetryReadTransactionAndPerformRediscoveryUntilSuccess() throws Except @Test void shouldRetryWriteTransactionAndPerformRediscoveryUntilSuccess() throws Exception { - StubServer router1 = StubServer.start( "discover_servers_9010.script", 9010 ); - StubServer brokenWriter1 = StubServer.start( "dead_write_server.script", 9001 ); - StubServer router2 = StubServer.start( "acquire_endpoints_v3_9010.script", 9002 ); - StubServer brokenWriter2 = StubServer.start( "dead_write_server.script", 9008 ); - StubServer writer = StubServer.start( "write_server_v3_write_tx.script", 9007 ); + StubServer router1 = stubController.startStub( "discover_servers_9010.script", 9010 ); + StubServer brokenWriter1 = stubController.startStub( "dead_write_server.script", 9001 ); + StubServer router2 = stubController.startStub( "acquire_endpoints_v3_9010.script", 9002 ); + StubServer brokenWriter2 = stubController.startStub( "dead_write_server.script", 9008 ); + StubServer writer = stubController.startStub( "write_server_v3_write_tx.script", 9007 ); try ( Driver driver = newDriverWithSleeplessClock( "neo4j://127.0.0.1:9010" ); Session session = driver.session() ) { @@ -833,7 +851,7 @@ void shouldRetryWriteTransactionAndPerformRediscoveryUntilSuccess() throws Excep void shouldUseInitialRouterForRediscoveryWhenAllOtherRoutersAreDead() throws Exception { // initial router does not have itself in the returned set of routers - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9001", INSECURE_CONFIG ) ) { @@ -842,7 +860,8 @@ void shouldUseInitialRouterForRediscoveryWhenAllOtherRoutersAreDead() throws Exc { // restart router on the same port with different script that contains itself as reader assertEquals( 0, router.exitStatus() ); - router = StubServer.start( "rediscover_using_initial_router.script", 9001 ); + + router = stubController.startStub( "rediscover_using_initial_router.script", 9001 ); List names = readStrings( "MATCH (n) RETURN n.name AS name", session ); assertEquals( asList( "Bob", "Alice" ), names ); @@ -856,7 +875,7 @@ void shouldUseInitialRouterForRediscoveryWhenAllOtherRoutersAreDead() throws Exc void shouldInvokeProcedureGetRoutingTableWhenServerVersionPermits() throws Exception { // stub server is both a router and reader - StubServer server = StubServer.start( "get_routing_table.script", 9001 ); + StubServer server = stubController.startStub( "get_routing_table.script", 9001 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9001", INSECURE_CONFIG ); Session session = driver.session() ) { @@ -876,7 +895,7 @@ void shouldInvokeProcedureGetRoutingTableWhenServerVersionPermits() throws Excep void shouldSendRoutingContextToServer() throws Exception { // stub server is both a router and reader - StubServer server = StubServer.start( "get_routing_table_with_context.script", 9001 ); + StubServer server = stubController.startStub( "get_routing_table_with_context.script", 9001 ); URI uri = URI.create( "neo4j://127.0.0.1:9001/?policy=my_policy®ion=china" ); try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ); Session session = driver.session() ) @@ -895,9 +914,9 @@ void shouldSendRoutingContextToServer() throws Exception @Test void shouldServeReadsButFailWritesWhenNoWritersAvailable() throws Exception { - StubServer router1 = StubServer.start( "discover_no_writers_9010.script", 9010 ); - StubServer router2 = StubServer.start( "discover_no_writers_9010.script", 9004 ); - StubServer reader = StubServer.start( "read_server_v3_read_tx.script", 9003 ); + StubServer router1 = stubController.startStub( "discover_no_writers_9010.script", 9010 ); + StubServer router2 = stubController.startStub( "discover_no_writers_9010.script", 9004 ); + StubServer reader = stubController.startStub( "read_server_v3_read_tx.script", 9003 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9010", INSECURE_CONFIG ); Session session = driver.session() ) @@ -919,10 +938,10 @@ void shouldAcceptRoutingTableWithoutWritersAndThenRediscover() throws Exception { // first router does not have itself in the resulting routing table so connection // towards it will be closed after rediscovery - StubServer router1 = StubServer.start( "discover_no_writers_9010.script", 9010 ); + StubServer router1 = stubController.startStub( "discover_no_writers_9010.script", 9010 ); StubServer router2 = null; - StubServer reader = StubServer.start( "read_server_v3_read_tx.script", 9003 ); - StubServer writer = StubServer.start( "write_with_bookmarks.script", 9007 ); + StubServer reader = stubController.startStub( "read_server_v3_read_tx.script", 9003 ); + StubServer writer = stubController.startStub( "write_with_bookmarks.script", 9007 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9010", INSECURE_CONFIG ) ) { @@ -930,7 +949,7 @@ void shouldAcceptRoutingTableWithoutWritersAndThenRediscover() throws Exception try ( Session session = driver.session() ) { // start another router which knows about writes, use same address as the initial router - router2 = StubServer.start( "acquire_endpoints_v3_9010.script", 9010 ); + router2 = stubController.startStub( "acquire_endpoints_v3_9010.script", 9010 ); assertEquals( asList( "Bob", "Alice", "Tina" ), readStrings( "MATCH (n) RETURN n.name", session ) ); @@ -951,9 +970,9 @@ void shouldAcceptRoutingTableWithoutWritersAndThenRediscover() throws Exception @Test void shouldTreatRoutingTableWithSingleRouterAsValid() throws Exception { - StubServer router = StubServer.start( "discover_one_router.script", 9010 ); - StubServer reader1 = StubServer.start( "read_server_v3_read.script", 9003 ); - StubServer reader2 = StubServer.start( "read_server_v3_read.script", 9004 ); + StubServer router = stubController.startStub( "discover_one_router.script", 9010 ); + StubServer reader1 = stubController.startStub( "read_server_v3_read.script", 9003 ); + StubServer reader2 = stubController.startStub( "read_server_v3_read.script", 9004 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9010", INSECURE_CONFIG ); Session session = driver.session( builder().withDefaultAccessMode( AccessMode.READ ).build() ) ) @@ -980,8 +999,8 @@ void shouldTreatRoutingTableWithSingleRouterAsValid() throws Exception @Test void shouldSendMultipleBookmarks() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer writer = StubServer.start( "multiple_bookmarks.script", 9007 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer writer = stubController.startStub( "multiple_bookmarks.script", 9007 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9001", INSECURE_CONFIG ); Session session = driver.session( builder().withBookmarks( InternalBookmark.parse( @@ -1007,14 +1026,17 @@ void shouldSendMultipleBookmarks() throws Exception void shouldForgetAddressOnDatabaseUnavailableError() throws Exception { // perform initial discovery using router1 - StubServer router1 = StubServer.start( "discover_servers_9010.script", 9010 ); + StubServer router1 = stubController.startStub( "discover_servers_9010.script", 9010 ); + // attempt to write using writer1 which fails with 'Neo.TransientError.General.DatabaseUnavailable' // it should then be forgotten and trigger new rediscovery - StubServer writer1 = StubServer.start( "writer_unavailable.script", 9001 ); + StubServer writer1 = stubController.startStub( "writer_unavailable.script", 9001 ); + // perform rediscovery using router2, it should return a valid writer2 - StubServer router2 = StubServer.start( "acquire_endpoints_v3_9010.script", 9002 ); + StubServer router2 = stubController.startStub( "acquire_endpoints_v3_9010.script", 9002 ); + // write on writer2 should be successful - StubServer writer2 = StubServer.start( "write_server_v3_write_tx.script", 9007 ); + StubServer writer2 = stubController.startStub( "write_server_v3_write_tx.script", 9007 ); try ( Driver driver = newDriverWithSleeplessClock( "neo4j://127.0.0.1:9010" ); Session session = driver.session() ) { @@ -1050,9 +1072,9 @@ void shouldFailInitialDiscoveryWhenConfiguredResolverThrows() @Test void shouldUseResolverDuringRediscoveryWhenExistingRoutersFail() throws Exception { - StubServer router1 = StubServer.start( "get_routing_table.script", 9001 ); - StubServer router2 = StubServer.start( "acquire_endpoints_v3.script", 9042 ); - StubServer reader = StubServer.start( "read_server_v3_read_tx.script", 9005 ); + StubServer router1 = stubController.startStub( "get_routing_table.script", 9001 ); + StubServer router2 = stubController.startStub( "acquire_endpoints_v3.script", 9042 ); + StubServer reader = stubController.startStub( "read_server_v3_read_tx.script", 9005 ); AtomicBoolean resolverInvoked = new AtomicBoolean(); ServerAddressResolver resolver = address -> { @@ -1098,8 +1120,8 @@ void shouldUseResolverDuringRediscoveryWhenExistingRoutersFail() throws Exceptio @Test void useSessionAfterDriverIsClosed() throws Exception { - StubServer router = StubServer.start( "acquire_endpoints_v3.script", 9001 ); - StubServer readServer = StubServer.start( "read_server_v3_read.script", 9005 ); + StubServer router = stubController.startStub( "acquire_endpoints_v3.script", 9001 ); + StubServer readServer = stubController.startStub( "read_server_v3_read.script", 9005 ); try ( Driver driver = GraphDatabase.driver( "neo4j://127.0.0.1:9001", INSECURE_CONFIG ) ) { @@ -1134,10 +1156,10 @@ void shouldRevertToInitialRouterIfKnownRouterThrowsProtocolErrors() throws Excep Config config = insecureBuilder().withResolver( resolver ).build(); - StubServer router1 = StubServer.start( "acquire_endpoints_v3_point_to_empty_router_and_exit.script", 9001 ); - StubServer router2 = StubServer.start( "acquire_endpoints_v3_empty.script", 9004 ); - StubServer router3 = StubServer.start( "acquire_endpoints_v3_three_servers_and_exit.script", 9003 ); - StubServer reader = StubServer.start( "read_server_v3_read_tx.script", 9002 ); + StubServer router1 = stubController.startStub( "acquire_endpoints_v3_point_to_empty_router_and_exit.script", 9001 ); + StubServer router2 = stubController.startStub( "acquire_endpoints_v3_empty.script", 9004 ); + StubServer router3 = stubController.startStub( "acquire_endpoints_v3_three_servers_and_exit.script", 9003 ); + StubServer reader = stubController.startStub( "read_server_v3_read_tx.script", 9002 ); try ( Driver driver = GraphDatabase.driver( "neo4j://my.virtual.host:8080", config ) ) { @@ -1159,7 +1181,7 @@ void shouldRevertToInitialRouterIfKnownRouterThrowsProtocolErrors() throws Excep @Test void shouldServerWithBoltV4SupportMultiDb() throws Throwable { - StubServer server = StubServer.start( "support_multidb_v4.script", 9001 ); + StubServer server = stubController.startStub( "support_multidb_v4.script", 9001 ); try ( Driver driver = GraphDatabase.driver( "neo4j://localhost:9001", INSECURE_CONFIG ) ) { assertTrue( driver.supportsMultiDb() ); @@ -1173,7 +1195,7 @@ void shouldServerWithBoltV4SupportMultiDb() throws Throwable @Test void shouldServerWithBoltV3NotSupportMultiDb() throws Throwable { - StubServer server = StubServer.start( "support_multidb_v3.script", 9001 ); + StubServer server = stubController.startStub( "support_multidb_v3.script", 9001 ); try ( Driver driver = GraphDatabase.driver( "neo4j://localhost:9001", INSECURE_CONFIG ) ) { assertFalse( driver.supportsMultiDb() ); diff --git a/driver/src/test/java/org/neo4j/driver/internal/DirectDriverBoltKitTest.java b/driver/src/test/java/org/neo4j/driver/internal/DirectDriverBoltKitTest.java index 301cafc0a8..f017f225d2 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/DirectDriverBoltKitTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/DirectDriverBoltKitTest.java @@ -544,6 +544,24 @@ void shouldServerWithBoltV3NotSupportMultiDb() throws Throwable } } + @Test + void shouldBeAbleHandleNOOPsDuringRunCypher() throws Exception + { + StubServer server = StubServer.start( "noop.script", 9001 ); + URI uri = URI.create( "bolt://127.0.0.1:9001" ); + + try ( Driver driver = GraphDatabase.driver( uri, INSECURE_CONFIG ) ) + { + try ( Session session = driver.session() ) + { + List names = session.run( "MATCH (n) RETURN n.name" ).list( rec -> rec.get( 0 ).asString() ); + assertEquals( asList( "Foo", "Bar", "Baz" ), names ); + } + } + + assertThat( server.exitStatus(), equalTo( 0 ) ); + } + private static void testTxCloseErrorPropagation( String script, Consumer txAction, String expectedErrorMessage ) throws Exception { diff --git a/driver/src/test/java/org/neo4j/driver/util/StubServer.java b/driver/src/test/java/org/neo4j/driver/util/StubServer.java index b074ebfb9f..c0ea59a131 100644 --- a/driver/src/test/java/org/neo4j/driver/util/StubServer.java +++ b/driver/src/test/java/org/neo4j/driver/util/StubServer.java @@ -51,15 +51,16 @@ public class StubServer // This may be thrown if the driver has not been closed properly public static class ForceKilled extends Exception {} - private static final String BOLT_STUB_COMMAND = "boltstub"; + private static final String BOLT_COMMAND = "bolt"; + private static final String BOLT_STUB_COMMAND = "stub"; private Process process; private StubServer( String script, int port ) throws IOException, InterruptedException { List command = new ArrayList<>(); - command.addAll( singletonList( BOLT_STUB_COMMAND ) ); - command.addAll( asList( Integer.toString( port ), script ) ); + command.addAll( asList( BOLT_COMMAND, BOLT_STUB_COMMAND ) ); + command.addAll( asList( "-l", "localhost:" + port, script ) ); ProcessBuilder server = new ProcessBuilder().command( command ); process = server.start(); startReadingOutput( process ); @@ -72,7 +73,7 @@ public static StubServer start( String resource, int port ) throws IOException, return new StubServer( resource(resource), port ); } - public int exitStatus() throws InterruptedException, ForceKilled + public int exitStatus() throws InterruptedException { sleep( 500 ); // wait for a moment to allow disconnection to occur try @@ -83,8 +84,8 @@ public int exitStatus() throws InterruptedException, ForceKilled { // not exited yet exit(); - throw new ForceKilled(); } + return -1; } public static Config.ConfigBuilder insecureBuilder() @@ -92,10 +93,17 @@ public static Config.ConfigBuilder insecureBuilder() return Config.builder().withoutEncryption().withLogging( none() ); } - private void exit() throws InterruptedException + private void exit() { process.destroy(); - process.waitFor(); + try + { + process.waitFor(); + } + catch ( InterruptedException ex ) + { + throw new RuntimeException( "Interrupted whilst waiting for forced stub shutdown", ex); + } } private static String resource( String fileName ) @@ -113,7 +121,7 @@ private static boolean boltKitAvailable() try { // run 'help' command to see if boltstub is available - Process process = new ProcessBuilder( BOLT_STUB_COMMAND, "-h" ).start(); + Process process = new ProcessBuilder( "bolt" ).start(); int exitCode = process.waitFor(); return exitCode == 0; } diff --git a/driver/src/test/java/org/neo4j/driver/util/StubServerController.java b/driver/src/test/java/org/neo4j/driver/util/StubServerController.java new file mode 100644 index 0000000000..48ed0d05b6 --- /dev/null +++ b/driver/src/test/java/org/neo4j/driver/util/StubServerController.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2002-2020 "Neo4j," + * Neo4j Sweden AB [http://neo4j.com] + * + * This file is part of Neo4j. + * + * Licensed 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. + */ +package org.neo4j.driver.util; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class StubServerController +{ + private final List currentStubServers = new CopyOnWriteArrayList<>(); + + public StubServer startStub( String script, int port) throws IOException, InterruptedException + { + StubServer server = StubServer.start( script, port ); + currentStubServers.add( server ); + return server; + } + + public void reset() + { + for ( StubServer server : currentStubServers ) + { + try + { + server.exitStatus(); + } + catch ( InterruptedException e ) + { + throw new RuntimeException( "Interrupted whilst waiting for stub shutdown", e); + } + currentStubServers.remove( server ); + } + + } +} diff --git a/driver/src/test/resources/acquire_endpoints_v3_point_to_empty_router_and_exit.script b/driver/src/test/resources/acquire_endpoints_v3_point_to_empty_router_and_exit.script index b62da37957..f6598a6d52 100644 --- a/driver/src/test/resources/acquire_endpoints_v3_point_to_empty_router_and_exit.script +++ b/driver/src/test/resources/acquire_endpoints_v3_point_to_empty_router_and_exit.script @@ -8,6 +8,3 @@ C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {"addre S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9010"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9011"], "role": "READ"},{"addresses": ["127.0.0.1:9004"], "role": "ROUTE"}]] SUCCESS {} -C: RESET -S: SUCCESS {} - diff --git a/driver/src/test/resources/acquire_endpoints_v3_three_servers_and_exit.script b/driver/src/test/resources/acquire_endpoints_v3_three_servers_and_exit.script index 8658f86c3f..c6ad010fd4 100644 --- a/driver/src/test/resources/acquire_endpoints_v3_three_servers_and_exit.script +++ b/driver/src/test/resources/acquire_endpoints_v3_three_servers_and_exit.script @@ -2,12 +2,11 @@ !: AUTO RESET !: AUTO HELLO !: AUTO GOODBYE +!: AUTO BEGIN C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": {"address": "my.virtual.host:8080"}} {} PULL_ALL S: SUCCESS {"fields": ["ttl", "servers"]} RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002","127.0.0.1:9003"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] SUCCESS {} -C: RESET -S: SUCCESS {} diff --git a/driver/src/test/resources/noop.script b/driver/src/test/resources/noop.script new file mode 100644 index 0000000000..6f9560fc04 --- /dev/null +++ b/driver/src/test/resources/noop.script @@ -0,0 +1,16 @@ +!: BOLT 4.1 +!: AUTO RESET +!: AUTO HELLO +!: AUTO GOODBYE + +C: RUN "MATCH (n) RETURN n.name" {} {} + PULL { "n": 1000 } +S: SUCCESS {"fields": ["n.name"]} + + RECORD ["Foo"] + + RECORD ["Bar"] + + + RECORD ["Baz"] + SUCCESS {} diff --git a/driver/src/test/resources/reset_error.script b/driver/src/test/resources/reset_error.script index 052b60f662..715e80d670 100644 --- a/driver/src/test/resources/reset_error.script +++ b/driver/src/test/resources/reset_error.script @@ -1,7 +1,6 @@ !: BOLT 3 !: AUTO HELLO !: AUTO GOODBYE -!: AUTO RESET C: RUN "RETURN 42 AS answer" {} {} PULL_ALL