diff --git a/driver/src/test/java/org/neo4j/driver/GraphDatabaseTest.java b/driver/src/test/java/org/neo4j/driver/GraphDatabaseTest.java index eee0a863f6..5c6ef0ea4a 100644 --- a/driver/src/test/java/org/neo4j/driver/GraphDatabaseTest.java +++ b/driver/src/test/java/org/neo4j/driver/GraphDatabaseTest.java @@ -49,11 +49,16 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.neo4j.driver.Logging.none; import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING; -import static org.neo4j.driver.util.StubServer.INSECURE_CONFIG; class GraphDatabaseTest { + private static final Config INSECURE_CONFIG = Config.builder() + .withoutEncryption() + .withLogging( none() ) + .build(); + @Test void throwsWhenBoltSchemeUsedWithRoutingParams() { diff --git a/driver/src/test/java/org/neo4j/driver/integration/ResolverIT.java b/driver/src/test/java/org/neo4j/driver/integration/ResolverIT.java new file mode 100644 index 0000000000..e1d3b7fcd2 --- /dev/null +++ b/driver/src/test/java/org/neo4j/driver/integration/ResolverIT.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) "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.integration; + +import org.junit.jupiter.api.Test; + +import org.neo4j.driver.Config; +import org.neo4j.driver.Driver; +import org.neo4j.driver.GraphDatabase; +import org.neo4j.driver.net.ServerAddress; +import org.neo4j.driver.net.ServerAddressResolver; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.neo4j.driver.Logging.none; + +class ResolverIT +{ + @Test + void shouldFailInitialDiscoveryWhenConfiguredResolverThrows() + { + ServerAddressResolver resolver = mock( ServerAddressResolver.class ); + when( resolver.resolve( any( ServerAddress.class ) ) ).thenThrow( new RuntimeException( "Resolution failure!" ) ); + + Config config = Config.builder() + .withoutEncryption() + .withLogging( none() ) + .withResolver( resolver ) + .build(); + final Driver driver = GraphDatabase.driver( "neo4j://my.server.com:9001", config ); + + RuntimeException error = assertThrows( RuntimeException.class, driver::verifyConnectivity ); + assertEquals( "Resolution failure!", error.getMessage() ); + verify( resolver ).resolve( ServerAddress.of( "my.server.com", 9001 ) ); + } +} diff --git a/driver/src/test/java/org/neo4j/driver/integration/RoutingDriverBoltKitIT.java b/driver/src/test/java/org/neo4j/driver/integration/RoutingDriverBoltKitIT.java deleted file mode 100644 index ccad42b29f..0000000000 --- a/driver/src/test/java/org/neo4j/driver/integration/RoutingDriverBoltKitIT.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) "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.integration; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import java.io.IOException; -import java.net.URI; -import java.util.concurrent.TimeUnit; - -import org.neo4j.driver.Config; -import org.neo4j.driver.Driver; -import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.Record; -import org.neo4j.driver.net.ServerAddress; -import org.neo4j.driver.net.ServerAddressResolver; -import org.neo4j.driver.reactive.RxResult; -import org.neo4j.driver.reactive.RxSession; -import org.neo4j.driver.util.StubServer; -import org.neo4j.driver.util.StubServerController; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.hamcrest.junit.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.driver.SessionConfig.builder; -import static org.neo4j.driver.util.StubServer.insecureBuilder; - -/** - * New tests should be added to testkit (https://github.com/neo4j-drivers/testkit). - * - * This class exists only for the following: - * - to keep the remaining tests that are due to be migrated - * - to keep the tests that are currently not portable - */ -@Deprecated -class RoutingDriverBoltKitIT -{ - private static StubServerController stubController; - - @BeforeAll - public static void setup() - { - stubController = new StubServerController(); - } - - @AfterEach - public void killServers() - { - stubController.reset(); - } - - private static String extractNameField( Record record ) - { - return record.get( 0 ).asString(); - } - - // RX is not currently supported in testkit. - - // This does not exactly reproduce the async and blocking versions above, as we don't have any means of ignoring - // the flux of the RETURN 1 query (not pulling the result) like we do in above, so this is "just" a test for - // a leader going away during the execution of a flux. - @Test - void shouldHandleLeaderSwitchAndRetryWhenWritingInTxFunctionRX() throws IOException, InterruptedException - { - // Given - StubServer server = stubController.startStub( "acquire_endpoints_twice_v4.script", 9001 ); - - // START a write server that fails on the first write attempt but then succeeds on the second - StubServer writeServer = stubController.startStub( "not_able_to_write_server_tx_func_retries_rx.script", 9007 ); - URI uri = URI.create( "neo4j://127.0.0.1:9001" ); - - Driver driver = GraphDatabase.driver( uri, Config.builder().withMaxTransactionRetryTime( 1, TimeUnit.MILLISECONDS ).build() ); - - Flux fluxOfNames = Flux.usingWhen( Mono.fromSupplier( () -> driver.rxSession( builder().withDatabase( "mydatabase" ).build() ) ), - session -> session.writeTransaction( tx -> - { - RxResult result = tx.run( "RETURN 1" ); - return Flux.from( result.records() ).limitRate( 100 ).thenMany( tx.run( "MATCH (n) RETURN n.name" ).records() ).limitRate( 100 ).map( - RoutingDriverBoltKitIT::extractNameField ); - } ), RxSession::close ); - - StepVerifier.create( fluxOfNames ).expectNext( "Foo", "Bar" ).verifyComplete(); - - // Finally - driver.close(); - assertThat( server.exitStatus(), equalTo( 0 ) ); - assertThat( writeServer.exitStatus(), equalTo( 0 ) ); - } - - @Test - void shouldFailInitialDiscoveryWhenConfiguredResolverThrows() - { - ServerAddressResolver resolver = mock( ServerAddressResolver.class ); - when( resolver.resolve( any( ServerAddress.class ) ) ).thenThrow( new RuntimeException( "Resolution failure!" ) ); - - Config config = insecureBuilder().withResolver( resolver ).build(); - final Driver driver = GraphDatabase.driver( "neo4j://my.server.com:9001", config ); - - RuntimeException error = assertThrows( RuntimeException.class, driver::verifyConnectivity ); - assertEquals( "Resolution failure!", error.getMessage() ); - verify( resolver ).resolve( ServerAddress.of( "my.server.com", 9001 ) ); - } -} diff --git a/driver/src/test/java/org/neo4j/driver/internal/DirectDriverBoltKitIT.java b/driver/src/test/java/org/neo4j/driver/internal/DirectDriverBoltKitIT.java deleted file mode 100644 index 095d501dae..0000000000 --- a/driver/src/test/java/org/neo4j/driver/internal/DirectDriverBoltKitIT.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) "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.internal; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import java.util.List; - -import org.neo4j.driver.Driver; -import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.reactive.RxResult; -import org.neo4j.driver.reactive.RxSession; -import org.neo4j.driver.util.StubServer; -import org.neo4j.driver.util.StubServerController; - -import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.neo4j.driver.util.StubServer.INSECURE_CONFIG; - -class DirectDriverBoltKitIT -{ - private static StubServerController stubController; - - @BeforeAll - public static void setup() - { - stubController = new StubServerController(); - } - - @AfterEach - public void killServers() - { - stubController.reset(); - } - - @Test - void shouldStreamingRecordsInBatchesRx() throws Exception - { - StubServer server = stubController.startStub( "streaming_records_v4_rx.script", 9001 ); - try - { - try ( Driver driver = GraphDatabase.driver( "bolt://localhost:9001", INSECURE_CONFIG ) ) - { - RxSession session = driver.rxSession(); - RxResult result = session.run( "MATCH (n) RETURN n.name" ); - Flux records = Flux.from( result.records() ).limitRate( 2 ).map( record -> record.get( "n.name" ).asString() ); - StepVerifier.create( records ).expectNext( "Bob", "Alice", "Tina" ).verifyComplete(); - } - } - finally - { - assertEquals( 0, server.exitStatus() ); - } - } - - @Test - void shouldDiscardIfPullNotFinished() throws Throwable - { - StubServer server = stubController.startStub( "read_tx_v4_discard.script", 9001 ); - - try ( Driver driver = GraphDatabase.driver( "bolt://localhost:9001", INSECURE_CONFIG ) ) - { - Flux> keys = Flux.usingWhen( - Mono.fromSupplier( driver::rxSession ), - session -> session.readTransaction( tx -> tx.run( "UNWIND [1,2,3,4] AS a RETURN a" ).keys() ), - RxSession::close ); - StepVerifier.create( keys ).expectNext( singletonList( "a" ) ).verifyComplete(); - } - finally - { - assertEquals( 0, server.exitStatus() ); - } - } -} diff --git a/driver/src/test/java/org/neo4j/driver/util/StubServer.java b/driver/src/test/java/org/neo4j/driver/util/StubServer.java deleted file mode 100644 index 4f3733bad8..0000000000 --- a/driver/src/test/java/org/neo4j/driver/util/StubServer.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) "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.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutorService; - -import org.neo4j.driver.Config; - -import static java.lang.Thread.sleep; -import static java.util.Arrays.asList; -import static java.util.concurrent.Executors.newCachedThreadPool; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.neo4j.driver.Logging.none; -import static org.neo4j.driver.util.DaemonThreadFactory.daemon; - -public class StubServer -{ - private static final int SOCKET_CONNECT_ATTEMPTS = 20; - - public static final Config INSECURE_CONFIG = insecureBuilder().withLogging( none() ).build(); - - private static final ExecutorService executor = newCachedThreadPool( daemon( "stub-server-output-reader-" ) ); - - // This may be thrown if the driver has not been closed properly - public static class ForceKilled extends Exception {} - - 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( asList( BOLT_COMMAND, BOLT_STUB_COMMAND ) ); - command.addAll( asList( "-l", "localhost:" + port, script ) ); - ProcessBuilder server = new ProcessBuilder().command( command ); - process = server.start(); - startReadingOutput( process ); - waitForSocket( port ); - } - - public static StubServer start( String resource, int port ) throws IOException, InterruptedException - { - assumeTrue( boltKitAvailable() ); - return new StubServer( resource(resource), port ); - } - - public int exitStatus() throws InterruptedException - { - sleep( 500 ); // wait for a moment to allow disconnection to occur - try - { - return process.exitValue(); - } - catch ( IllegalThreadStateException ex ) - { - // not exited yet - exit(); - } - return -1; - } - - public static Config.ConfigBuilder insecureBuilder() - { - return Config.builder().withoutEncryption().withLogging( none() ); - } - - private void exit() - { - process.destroy(); - try - { - process.waitFor(); - } - catch ( InterruptedException ex ) - { - throw new RuntimeException( "Interrupted whilst waiting for forced stub shutdown", ex); - } - } - - private static String resource( String fileName ) - { - File resource = new File( DatabaseExtension.TEST_RESOURCE_FOLDER_PATH, fileName ); - if ( !resource.exists() ) - { - fail( fileName + " does not exists" ); - } - return resource.getAbsolutePath(); - } - - private static boolean boltKitAvailable() - { - try - { - // run 'help' command to see if boltstub is available - Process process = new ProcessBuilder( "bolt" ).start(); - int exitCode = process.waitFor(); - return exitCode == 0; - } - catch ( IOException | InterruptedException e ) - { - // unable to run boltstub command, thus it is unavailable - return false; - } - } - - private static void waitForSocket( int port ) throws InterruptedException - { - SocketAddress address = new InetSocketAddress( "localhost", port ); - for ( int i = 0; i < SOCKET_CONNECT_ATTEMPTS; i++ ) - { - try - { - SocketChannel.open( address ); - return; - } - catch ( Exception e ) - { - sleep( 300 ); - } - } - throw new AssertionError( "Can't connect to " + address ); - } - - /** - * Read output of the given process using a separate thread. - * Since maven-surefire-plugin 2.20.0 it is not good to simply inherit IO using {@link ProcessBuilder#inheritIO()}. - * It will result in "Corrupted stdin stream in forked JVM 1" warning being printed and output being redirected to a - * separate temporary file. - *

- * Fore more details see: - *

    - *
  • http://maven.apache.org/surefire/maven-surefire-plugin/faq.html#corruptedstream
  • - *
  • https://issues.apache.org/jira/browse/SUREFIRE-1359
  • - *
- * - * @param process the process to read output. - */ - private static void startReadingOutput( Process process ) - { - executor.submit( () -> - { - try ( BufferedReader reader = new BufferedReader( new InputStreamReader( process.getInputStream() ) ) ) - { - String line; - while ( (line = reader.readLine()) != null ) - { - System.out.println( line ); - } - } - return null; - } ); - } -} diff --git a/driver/src/test/java/org/neo4j/driver/util/StubServerController.java b/driver/src/test/java/org/neo4j/driver/util/StubServerController.java deleted file mode 100644 index 7b2db89d04..0000000000 --- a/driver/src/test/java/org/neo4j/driver/util/StubServerController.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) "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_twice_v4.script b/driver/src/test/resources/acquire_endpoints_twice_v4.script deleted file mode 100644 index f92363e573..0000000000 --- a/driver/src/test/resources/acquire_endpoints_twice_v4.script +++ /dev/null @@ -1,16 +0,0 @@ -!: BOLT 4 -!: AUTO RESET -!: AUTO HELLO -!: AUTO GOODBYE - -C: RUN "CALL dbms.routing.getRoutingTable($context, $database)" {"context": { "address": "127.0.0.1:9001"}, "database": "mydatabase"} {"mode": "r", "db": "system"} - PULL {"n": -1} -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9007"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] - SUCCESS {} -C: RUN "CALL dbms.routing.getRoutingTable($context, $database)" {"context": { "address": "127.0.0.1:9001"}, "database": "mydatabase"} {"mode": "r", "db": "system"} - PULL {"n": -1} -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9007"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9005","127.0.0.1:9006"], "role": "READ"},{"addresses": ["127.0.0.1:9001","127.0.0.1:9002","127.0.0.1:9003"], "role": "ROUTE"}]] - SUCCESS {} - diff --git a/driver/src/test/resources/not_able_to_write_server_tx_func_retries_rx.script b/driver/src/test/resources/not_able_to_write_server_tx_func_retries_rx.script deleted file mode 100644 index b2d651000c..0000000000 --- a/driver/src/test/resources/not_able_to_write_server_tx_func_retries_rx.script +++ /dev/null @@ -1,25 +0,0 @@ -!: BOLT 4 -!: AUTO RESET -!: AUTO BEGIN -!: AUTO HELLO -!: AUTO GOODBYE -!: AUTO ROLLBACK - -C: RUN "RETURN 1" {} {} -S: SUCCESS {"fields": ["1"]} -C: PULL {"n": 100} -S: FAILURE {"code": "Neo.ClientError.Cluster.NotALeader", "message": "blabla"} -C: RUN "RETURN 1" {} {} -S: SUCCESS {"fields": ["1"]} -C: PULL {"n": 100} -S: RECORD [1] - SUCCESS {"has_more": false} -C: RUN "MATCH (n) RETURN n.name" {} {} -S: SUCCESS {"fields": ["n.name"]} -C: PULL {"n": 100} -S: RECORD ["Foo"] - RECORD ["Bar"] - SUCCESS {"has_more": false} -C: COMMIT -S: SUCCESS {"bookmark": "NewBookmark"} - diff --git a/driver/src/test/resources/read_tx_v4_discard.script b/driver/src/test/resources/read_tx_v4_discard.script deleted file mode 100644 index ea13b249f1..0000000000 --- a/driver/src/test/resources/read_tx_v4_discard.script +++ /dev/null @@ -1,13 +0,0 @@ -!: BOLT 4 -!: AUTO RESET -!: AUTO HELLO -!: AUTO GOODBYE - -C: BEGIN { "mode": "r" } -S: SUCCESS {} -C: RUN "UNWIND [1,2,3,4] AS a RETURN a" {} {} -S: SUCCESS {"t_first": 110, "fields": ["a"], "qid": 0} -C: DISCARD {"qid": 0, "n": -1} -S: SUCCESS {"type": "r", "t_last": 3, "db": "neo4j"} -C: COMMIT -S: SUCCESS {"bookmark": "e57085e2-727f-43f3-b632-7ec57978806e:117"} diff --git a/driver/src/test/resources/streaming_records_v4_rx.script b/driver/src/test/resources/streaming_records_v4_rx.script deleted file mode 100644 index 74543b6f86..0000000000 --- a/driver/src/test/resources/streaming_records_v4_rx.script +++ /dev/null @@ -1,14 +0,0 @@ -!: BOLT 4 -!: AUTO RESET -!: AUTO HELLO -!: AUTO GOODBYE - -C: RUN "MATCH (n) RETURN n.name" {} {} -S: SUCCESS {"fields": ["n.name"]} -C: PULL { "n": 2 } -S: RECORD ["Bob"] - RECORD ["Alice"] - SUCCESS {"has_more": true} -C: PULL { "n": 2 } -S: RECORD ["Tina"] - SUCCESS {} diff --git a/examples/src/main/java/org/neo4j/docs/driver/ConfigCustomResolverExample.java b/examples/src/main/java/org/neo4j/docs/driver/ConfigCustomResolverExample.java index ec55d06382..394b7f09f1 100644 --- a/examples/src/main/java/org/neo4j/docs/driver/ConfigCustomResolverExample.java +++ b/examples/src/main/java/org/neo4j/docs/driver/ConfigCustomResolverExample.java @@ -18,33 +18,35 @@ */ package org.neo4j.docs.driver; // tag::config-custom-resolver-import[] + import java.util.Arrays; import java.util.HashSet; import org.neo4j.driver.AccessMode; +import org.neo4j.driver.AuthToken; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.Config; import org.neo4j.driver.Driver; import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.Session; import org.neo4j.driver.Result; +import org.neo4j.driver.Session; import org.neo4j.driver.net.ServerAddress; -import static org.neo4j.driver.Values.parameters; import static org.neo4j.driver.SessionConfig.builder; +import static org.neo4j.driver.Values.parameters; + // end::config-custom-resolver-import[] public class ConfigCustomResolverExample implements AutoCloseable { private final Driver driver; - public ConfigCustomResolverExample( String virtualUri, ServerAddress... addresses ) + public ConfigCustomResolverExample( String virtualUri, AuthToken authToken, ServerAddress... addresses ) { Config config = Config.builder() - .withoutEncryption() - .withResolver( address -> new HashSet<>( Arrays.asList( addresses ) ) ) - .build(); + .withResolver( address -> new HashSet<>( Arrays.asList( addresses ) ) ) + .build(); - driver = GraphDatabase.driver( virtualUri, AuthTokens.none(), config ); + driver = GraphDatabase.driver( virtualUri, authToken, config ); } // tag::config-custom-resolver[] diff --git a/examples/src/test/java/org/neo4j/docs/driver/ExamplesStubIT.java b/examples/src/test/java/org/neo4j/docs/driver/RoutingExamplesIT.java similarity index 67% rename from examples/src/test/java/org/neo4j/docs/driver/ExamplesStubIT.java rename to examples/src/test/java/org/neo4j/docs/driver/RoutingExamplesIT.java index 2765eadb9b..8c4b6ceeed 100644 --- a/examples/src/test/java/org/neo4j/docs/driver/ExamplesStubIT.java +++ b/examples/src/test/java/org/neo4j/docs/driver/RoutingExamplesIT.java @@ -19,31 +19,30 @@ package org.neo4j.docs.driver; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.net.URI; import org.neo4j.driver.net.ServerAddress; -import org.neo4j.driver.util.StubServer; +import org.neo4j.driver.util.cc.ClusterExtension; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -class ExamplesStubIT +class RoutingExamplesIT { + @RegisterExtension + static final ClusterExtension neo4j = new ClusterExtension(); + @Test void testShouldRunConfigCustomResolverExample() throws Exception { - StubServer server1 = StubServer.start( "get_routing_table_only.script", 9001 ); - StubServer server2 = StubServer.start( "return_1.script", 9002 ); - // Given - try ( ConfigCustomResolverExample example = new ConfigCustomResolverExample( "neo4j://x.example.com", ServerAddress.of( "localhost", 9001 ) ) ) + URI uri = neo4j.getCluster().leader().getRoutingUri(); + try ( ConfigCustomResolverExample example = new ConfigCustomResolverExample( "neo4j://x.example.com", neo4j.getDefaultAuthToken(), + ServerAddress.of( uri.getHost(), uri.getPort() ) ) ) { // Then assertTrue( example.canConnect() ); } - finally - { - assertEquals( 0, server1.exitStatus() ); - assertEquals( 0, server2.exitStatus() ); - } } } diff --git a/examples/src/test/resources/get_routing_table_only.script b/examples/src/test/resources/get_routing_table_only.script deleted file mode 100644 index f42314646b..0000000000 --- a/examples/src/test/resources/get_routing_table_only.script +++ /dev/null @@ -1,11 +0,0 @@ -!: BOLT 3 -!: AUTO RESET -!: AUTO HELLO -!: AUTO GOODBYE - -C: RUN "CALL dbms.cluster.routing.getRoutingTable($context)" {"context": { "address": "x.example.com:7687" }} {} - PULL_ALL -S: SUCCESS {"fields": ["ttl", "servers"]} - RECORD [9223372036854775807, [{"addresses": ["127.0.0.1:9001"],"role": "WRITE"}, {"addresses": ["127.0.0.1:9002"], "role": "READ"},{"addresses": ["127.0.0.1:9001"], "role": "ROUTE"}]] - SUCCESS {} -S: diff --git a/examples/src/test/resources/return_1.script b/examples/src/test/resources/return_1.script deleted file mode 100644 index 0b80d8bc20..0000000000 --- a/examples/src/test/resources/return_1.script +++ /dev/null @@ -1,10 +0,0 @@ -!: BOLT 3 -!: AUTO HELLO -!: AUTO GOODBYE -!: AUTO RESET - -C: RUN "RETURN 1" {} {"mode": "r"} - PULL_ALL -S: SUCCESS {"fields": ["1"]} - RECORD [1] - SUCCESS {} diff --git a/testkit-backend/src/main/java/neo4j/org/testkit/backend/RxBufferedSubscriber.java b/testkit-backend/src/main/java/neo4j/org/testkit/backend/RxBufferedSubscriber.java index 4137b464a2..2264c553ae 100644 --- a/testkit-backend/src/main/java/neo4j/org/testkit/backend/RxBufferedSubscriber.java +++ b/testkit-backend/src/main/java/neo4j/org/testkit/backend/RxBufferedSubscriber.java @@ -161,30 +161,32 @@ public static T executeWithLock( Lock lock, Supplier supplier ) private static class OneSignalSubscriber extends BaseSubscriber { private final Lock lock = new ReentrantLock(); + private final CompletableFuture completionFuture = new CompletableFuture<>(); private MonoSink sink; private boolean emitted; - private boolean done; - private Throwable throwable; public void requestNext( MonoSink sink ) { - boolean done = executeWithLock( lock, () -> + executeWithLock( lock, () -> { this.sink = sink; - emitted = false; - return this.done; + return emitted = false; } ); - if ( done ) + if ( completionFuture.isDone() ) { - if ( throwable != null ) - { - this.sink.error( throwable ); - } - else - { - this.sink.success(); - } + completionFuture.whenComplete( + ( ignored, throwable ) -> + { + if ( throwable != null ) + { + this.sink.error( throwable ); + } + else + { + this.sink.success(); + } + } ); } else { @@ -214,7 +216,7 @@ protected void hookOnComplete() { MonoSink sink = executeWithLock( lock, () -> { - done = true; + completionFuture.complete( null ); return !emitted ? this.sink : null; } ); if ( sink != null ) @@ -228,8 +230,7 @@ protected void hookOnError( Throwable throwable ) { MonoSink sink = executeWithLock( lock, () -> { - done = true; - this.throwable = throwable; + completionFuture.completeExceptionally( throwable ); return !emitted ? this.sink : null; } ); if ( sink != null )