|
23 | 23 | import java.io.IOException;
|
24 | 24 | import java.net.URI;
|
25 | 25 | import java.util.ArrayList;
|
26 |
| -import java.util.Arrays; |
| 26 | +import java.util.HashSet; |
27 | 27 | import java.util.List;
|
| 28 | +import java.util.concurrent.atomic.AtomicBoolean; |
28 | 29 | import java.util.concurrent.atomic.AtomicInteger;
|
29 | 30 |
|
30 | 31 | import org.neo4j.driver.internal.cluster.RoutingSettings;
|
|
45 | 46 | import org.neo4j.driver.v1.TransactionWork;
|
46 | 47 | import org.neo4j.driver.v1.exceptions.ServiceUnavailableException;
|
47 | 48 | import org.neo4j.driver.v1.exceptions.SessionExpiredException;
|
| 49 | +import org.neo4j.driver.v1.net.ServerAddress; |
| 50 | +import org.neo4j.driver.v1.net.ServerAddressResolver; |
48 | 51 | import org.neo4j.driver.v1.util.StubServer;
|
49 | 52 |
|
50 | 53 | import static java.util.Arrays.asList;
|
51 |
| -import static java.util.logging.Level.INFO; |
| 54 | +import static java.util.Collections.singleton; |
52 | 55 | import static org.hamcrest.Matchers.hasSize;
|
53 | 56 | import static org.hamcrest.core.IsEqual.equalTo;
|
54 | 57 | import static org.hamcrest.junit.MatcherAssert.assertThat;
|
|
57 | 60 | import static org.junit.jupiter.api.Assertions.assertNotNull;
|
58 | 61 | import static org.junit.jupiter.api.Assertions.assertThrows;
|
59 | 62 | import static org.junit.jupiter.api.Assertions.assertTrue;
|
60 |
| -import static org.neo4j.driver.v1.Logging.console; |
| 63 | +import static org.mockito.ArgumentMatchers.any; |
| 64 | +import static org.mockito.Mockito.mock; |
| 65 | +import static org.mockito.Mockito.verify; |
| 66 | +import static org.mockito.Mockito.when; |
| 67 | +import static org.neo4j.driver.v1.Logging.none; |
61 | 68 |
|
62 | 69 | class RoutingDriverBoltKitTest
|
63 | 70 | {
|
64 | 71 | private static final Config config = Config.build()
|
65 | 72 | .withoutEncryption()
|
66 |
| - .withLogging( console( INFO ) ).toConfig(); |
| 73 | + .withLogging( none() ) |
| 74 | + .toConfig(); |
67 | 75 |
|
68 | 76 | @Test
|
69 | 77 | void shouldHandleAcquireReadSession() throws IOException, InterruptedException, StubServer.ForceKilled
|
@@ -917,7 +925,7 @@ void shouldSendMultipleBookmarks() throws Exception
|
917 | 925 | StubServer router = StubServer.start( "acquire_endpoints.script", 9001 );
|
918 | 926 | StubServer writer = StubServer.start( "multiple_bookmarks.script", 9007 );
|
919 | 927 |
|
920 |
| - List<String> bookmarks = Arrays.asList( "neo4j:bookmark:v1:tx5", "neo4j:bookmark:v1:tx29", |
| 928 | + List<String> bookmarks = asList( "neo4j:bookmark:v1:tx5", "neo4j:bookmark:v1:tx29", |
921 | 929 | "neo4j:bookmark:v1:tx94", "neo4j:bookmark:v1:tx56", "neo4j:bookmark:v1:tx16",
|
922 | 930 | "neo4j:bookmark:v1:tx68" );
|
923 | 931 |
|
@@ -963,10 +971,82 @@ void shouldForgetAddressOnDatabaseUnavailableError() throws Exception
|
963 | 971 | }
|
964 | 972 | finally
|
965 | 973 | {
|
966 |
| - assertEquals( router1.exitStatus(), 0 ); |
967 |
| - assertEquals( writer1.exitStatus(), 0 ); |
968 |
| - assertEquals( router2.exitStatus(), 0 ); |
969 |
| - assertEquals( writer2.exitStatus(), 0 ); |
| 974 | + assertEquals( 0, router1.exitStatus() ); |
| 975 | + assertEquals( 0, writer1.exitStatus() ); |
| 976 | + assertEquals( 0, router2.exitStatus() ); |
| 977 | + assertEquals( 0, writer2.exitStatus() ); |
| 978 | + } |
| 979 | + } |
| 980 | + |
| 981 | + @Test |
| 982 | + void shouldFailInitialDiscoveryWhenConfiguredResolverThrows() |
| 983 | + { |
| 984 | + ServerAddressResolver resolver = mock( ServerAddressResolver.class ); |
| 985 | + when( resolver.resolve( any( ServerAddress.class ) ) ).thenThrow( new RuntimeException( "Resolution failure!" ) ); |
| 986 | + |
| 987 | + Config config = Config.build() |
| 988 | + .withLogging( none() ) |
| 989 | + .withoutEncryption() |
| 990 | + .withResolver( resolver ) |
| 991 | + .toConfig(); |
| 992 | + |
| 993 | + RuntimeException error = assertThrows( RuntimeException.class, () -> GraphDatabase.driver( "bolt+routing://my.server.com:9001", config ) ); |
| 994 | + assertEquals( "Resolution failure!", error.getMessage() ); |
| 995 | + verify( resolver ).resolve( ServerAddress.of( "my.server.com", 9001 ) ); |
| 996 | + } |
| 997 | + |
| 998 | + @Test |
| 999 | + void shouldUseResolverDuringRediscoveryWhenExistingRoutersFail() throws Exception |
| 1000 | + { |
| 1001 | + StubServer router1 = StubServer.start( "get_routing_table.script", 9001 ); |
| 1002 | + StubServer router2 = StubServer.start( "acquire_endpoints.script", 9042 ); |
| 1003 | + StubServer reader = StubServer.start( "read_server.script", 9005 ); |
| 1004 | + |
| 1005 | + AtomicBoolean resolverInvoked = new AtomicBoolean(); |
| 1006 | + ServerAddressResolver resolver = address -> |
| 1007 | + { |
| 1008 | + if ( resolverInvoked.compareAndSet( false, true ) ) |
| 1009 | + { |
| 1010 | + // return the address first time |
| 1011 | + return singleton( address ); |
| 1012 | + } |
| 1013 | + if ( "127.0.0.1".equals( address.host() ) && address.port() == 9001 ) |
| 1014 | + { |
| 1015 | + // return list of addresses where onl 9042 is functional |
| 1016 | + return new HashSet<>( asList( |
| 1017 | + ServerAddress.of( "127.0.0.1", 9010 ), |
| 1018 | + ServerAddress.of( "127.0.0.1", 9011 ), |
| 1019 | + ServerAddress.of( "127.0.0.1", 9042 ) ) ); |
| 1020 | + } |
| 1021 | + throw new AssertionError(); |
| 1022 | + }; |
| 1023 | + |
| 1024 | + Config config = Config.build() |
| 1025 | + .withLogging( none() ) |
| 1026 | + .withoutEncryption() |
| 1027 | + .withResolver( resolver ) |
| 1028 | + .toConfig(); |
| 1029 | + |
| 1030 | + try ( Driver driver = GraphDatabase.driver( "bolt+routing://127.0.0.1:9001", config ) ) |
| 1031 | + { |
| 1032 | + try ( Session session = driver.session( AccessMode.READ ) ) |
| 1033 | + { |
| 1034 | + // run first query against 9001, which should return result and exit |
| 1035 | + List<String> names1 = session.run( "MATCH (n) RETURN n.name AS name" ) |
| 1036 | + .list( record -> record.get( "name" ).asString() ); |
| 1037 | + assertEquals( asList( "Alice", "Bob", "Eve" ), names1 ); |
| 1038 | + |
| 1039 | + // run second query with retries, it should rediscover using 9042 returned by the resolver and read from 9005 |
| 1040 | + List<String> names2 = session.readTransaction( tx -> tx.run( "MATCH (n) RETURN n.name" ) ) |
| 1041 | + .list( record -> record.get( 0 ).asString() ); |
| 1042 | + assertEquals( asList( "Bob", "Alice", "Tina" ), names2 ); |
| 1043 | + } |
| 1044 | + } |
| 1045 | + finally |
| 1046 | + { |
| 1047 | + assertEquals( 0, router1.exitStatus() ); |
| 1048 | + assertEquals( 0, router2.exitStatus() ); |
| 1049 | + assertEquals( 0, reader.exitStatus() ); |
970 | 1050 | }
|
971 | 1051 | }
|
972 | 1052 |
|
|
0 commit comments