3939import org .neo4j .driver .Config ;
4040import org .neo4j .driver .Driver ;
4141import org .neo4j .driver .GraphDatabase ;
42- import org .neo4j .driver .Logger ;
4342import org .neo4j .driver .Record ;
4443import org .neo4j .driver .Session ;
45- import org .neo4j .driver .Transaction ;
4644import org .neo4j .driver .TransactionWork ;
4745import org .neo4j .driver .async .AsyncSession ;
4846import org .neo4j .driver .exceptions .SessionExpiredException ;
49- import org .neo4j .driver .exceptions .TransientException ;
5047import org .neo4j .driver .internal .DriverFactory ;
5148import org .neo4j .driver .internal .cluster .RoutingSettings ;
5249import org .neo4j .driver .internal .retry .RetrySettings ;
7067import static org .junit .jupiter .api .Assertions .assertThrows ;
7168import static org .junit .jupiter .api .Assertions .assertTrue ;
7269import static org .mockito .ArgumentMatchers .any ;
73- import static org .mockito .ArgumentMatchers .startsWith ;
7470import static org .mockito .Mockito .mock ;
75- import static org .mockito .Mockito .times ;
7671import static org .mockito .Mockito .verify ;
7772import static org .mockito .Mockito .when ;
7873import static org .neo4j .driver .SessionConfig .builder ;
79- import static org .neo4j .driver .internal .InternalBookmark .parse ;
8074import static org .neo4j .driver .util .StubServer .INSECURE_CONFIG ;
8175import static org .neo4j .driver .util .StubServer .insecureBuilder ;
8276
77+ /**
78+ * New tests should be added to testkit (https://github.com/neo4j-drivers/testkit).
79+ *
80+ * This class exists only for the following:
81+ * - to keep the remaining tests that are due to be migrated
82+ * - to keep the tests that are currently not portable
83+ */
84+ @ Deprecated
8385class RoutingDriverBoltKitIT
8486{
8587 private static StubServerController stubController ;
@@ -96,43 +98,7 @@ public void killServers()
9698 stubController .reset ();
9799 }
98100
99- @ Test
100- void shouldHandleLeaderSwitchAndRetryWhenWritingInTxFunction () throws IOException , InterruptedException
101- {
102- // Given
103- StubServer server = stubController .startStub ( "acquire_endpoints_twice_v4.script" , 9001 );
104-
105- // START a write server that fails on the first write attempt but then succeeds on the second
106- StubServer writeServer = stubController .startStub ( "not_able_to_write_server_tx_func_retries.script" , 9007 );
107- URI uri = URI .create ( "neo4j://127.0.0.1:9001" );
108-
109- Driver driver = GraphDatabase .driver ( uri , Config .builder ().withMaxTransactionRetryTime ( 1 , TimeUnit .MILLISECONDS ).build () );
110- List <String > names ;
111-
112- try ( Session session = driver .session ( builder ().withDatabase ( "mydatabase" ).build () ) )
113- {
114- names = session .writeTransaction ( tx ->
115- {
116- tx .run ( "RETURN 1" );
117- try
118- {
119- Thread .sleep ( 100 );
120- }
121- catch ( InterruptedException ex )
122- {
123- }
124- return tx .run ( "MATCH (n) RETURN n.name" ).list ( RoutingDriverBoltKitIT ::extractNameField );
125- } );
126- }
127-
128- assertEquals ( asList ( "Foo" , "Bar" ), names );
129-
130- // Finally
131- driver .close ();
132- assertThat ( server .exitStatus (), equalTo ( 0 ) );
133- assertThat ( writeServer .exitStatus (), equalTo ( 0 ) );
134- }
135-
101+ // Async is not currently supported in testkit.
136102 @ Test
137103 void shouldHandleLeaderSwitchAndRetryWhenWritingInTxFunctionAsync () throws IOException , InterruptedException
138104 {
@@ -167,11 +133,13 @@ void shouldHandleLeaderSwitchAndRetryWhenWritingInTxFunctionAsync() throws IOExc
167133 assertThat ( writeServer .exitStatus (), equalTo ( 0 ) );
168134 }
169135
170- private static String extractNameField (Record record )
136+ private static String extractNameField ( Record record )
171137 {
172138 return record .get ( 0 ).asString ();
173139 }
174140
141+ // RX is not currently supported in testkit.
142+
175143 // This does not exactly reproduce the async and blocking versions above, as we don't have any means of ignoring
176144 // the flux of the RETURN 1 query (not pulling the result) like we do in above, so this is "just" a test for
177145 // a leader going away during the execution of a flux.
@@ -203,95 +171,7 @@ void shouldHandleLeaderSwitchAndRetryWhenWritingInTxFunctionRX() throws IOExcept
203171 assertThat ( writeServer .exitStatus (), equalTo ( 0 ) );
204172 }
205173
206- @ Test
207- void shouldSendInitialBookmark () throws Exception
208- {
209- StubServer router = stubController .startStub ( "acquire_endpoints_v3.script" , 9001 );
210- StubServer writer = stubController .startStub ( "write_tx_with_bookmarks.script" , 9007 );
211-
212- try ( Driver driver = GraphDatabase .driver ( "neo4j://127.0.0.1:9001" , INSECURE_CONFIG );
213- Session session = driver .session ( builder ().withBookmarks ( parse ( "OldBookmark" ) ).build () ) )
214- {
215- try ( Transaction tx = session .beginTransaction () )
216- {
217- tx .run ( "CREATE (n {name:'Bob'})" );
218- tx .commit ();
219- }
220-
221- assertEquals ( parse ( "NewBookmark" ), session .lastBookmark () );
222- }
223-
224- assertThat ( router .exitStatus (), equalTo ( 0 ) );
225- assertThat ( writer .exitStatus (), equalTo ( 0 ) );
226- }
227-
228- @ Test
229- void shouldRetryWriteTransactionUntilSuccessWithWhenLeaderIsRemoved () throws Exception
230- {
231- // This test simulates a router in a cluster when a leader is removed.
232- // The router first returns a RT with a writer inside.
233- // However this writer is killed while the driver is running a tx with it.
234- // Then at the second time the router returns the same RT with the killed writer inside.
235- // At the third round, the router removes the the writer server from RT reply.
236- // Finally, the router returns a RT with a reachable writer.
237- StubServer router = stubController .startStub ( "acquire_endpoints_v3_leader_killed.script" , 9001 );
238- StubServer brokenWriter = stubController .startStub ( "dead_write_server.script" , 9004 );
239- StubServer writer = stubController .startStub ( "write_server_v3_write_tx.script" , 9008 );
240-
241- Logger logger = mock ( Logger .class );
242- Config config = insecureBuilder ().withLogging ( ignored -> logger ).build ();
243- try ( Driver driver = newDriverWithSleeplessClock ( "neo4j://127.0.0.1:9001" , config ); Session session = driver .session () )
244- {
245- AtomicInteger invocations = new AtomicInteger ();
246- List <Record > records = session .writeTransaction ( queryWork ( "CREATE (n {name:'Bob'})" , invocations ) );
247-
248- assertEquals ( 0 , records .size () );
249- assertEquals ( 2 , invocations .get () );
250- }
251- finally
252- {
253- assertEquals ( 0 , router .exitStatus () );
254- assertEquals ( 0 , brokenWriter .exitStatus () );
255- assertEquals ( 0 , writer .exitStatus () );
256- }
257- verify ( logger , times ( 3 ) ).warn ( startsWith ( "Transaction failed and will be retried in" ), any ( SessionExpiredException .class ) );
258- verify ( logger ).warn ( startsWith ( "Failed to obtain a connection towards address 127.0.0.1:9004" ), any ( SessionExpiredException .class ) );
259- }
260-
261- @ Test
262- void shouldRetryWriteTransactionUntilSuccessWithWhenLeaderIsRemovedV3 () throws Exception
263- {
264- // This test simulates a router in a cluster when a leader is removed.
265- // The router first returns a RT with a writer inside.
266- // However this writer is killed while the driver is running a tx with it.
267- // Then at the second time the router returns the same RT with the killed writer inside.
268- // At the third round, the router removes the the writer server from RT reply.
269- // Finally, the router returns a RT with a reachable writer.
270- StubServer router = stubController .startStub ( "acquire_endpoints_v3_leader_killed.script" , 9001 );
271- StubServer brokenWriter = stubController .startStub ( "database_shutdown_at_commit.script" , 9004 );
272- StubServer writer = stubController .startStub ( "write_server_v3_write_tx.script" , 9008 );
273-
274- Logger logger = mock ( Logger .class );
275- Config config = insecureBuilder ().withLogging ( ignored -> logger ).build ();
276- try ( Driver driver = newDriverWithSleeplessClock ( "neo4j://127.0.0.1:9001" , config ); Session session = driver .session () )
277- {
278- AtomicInteger invocations = new AtomicInteger ();
279- List <Record > records = session .writeTransaction ( queryWork ( "CREATE (n {name:'Bob'})" , invocations ) );
280-
281- assertEquals ( 0 , records .size () );
282- assertEquals ( 2 , invocations .get () );
283- }
284- finally
285- {
286- assertEquals ( 0 , router .exitStatus () );
287- assertEquals ( 0 , brokenWriter .exitStatus () );
288- assertEquals ( 0 , writer .exitStatus () );
289- }
290- verify ( logger , times ( 1 ) ).warn ( startsWith ( "Transaction failed and will be retried in" ), any ( TransientException .class ) );
291- verify ( logger , times ( 2 ) ).warn ( startsWith ( "Transaction failed and will be retried in" ), any ( SessionExpiredException .class ) );
292- verify ( logger ).warn ( startsWith ( "Failed to obtain a connection towards address 127.0.0.1:9004" ), any ( SessionExpiredException .class ) );
293- }
294-
174+ // fixed retries are not currently supported in testkit
295175 @ Test
296176 void shouldRetryReadTransactionUntilFailure () throws Exception
297177 {
@@ -313,6 +193,7 @@ void shouldRetryReadTransactionUntilFailure() throws Exception
313193 }
314194 }
315195
196+ // fixed retries are not currently supported in testkit
316197 @ Test
317198 void shouldRetryWriteTransactionUntilFailure () throws Exception
318199 {
@@ -334,46 +215,6 @@ void shouldRetryWriteTransactionUntilFailure() throws Exception
334215 }
335216 }
336217
337- @ Test
338- void shouldSendRoutingContextToServer () throws Exception
339- {
340- // stub server is both a router and reader
341- StubServer server = stubController .startStub ( "get_routing_table_with_context.script" , 9001 );
342-
343- URI uri = URI .create ( "neo4j://127.0.0.1:9001/?policy=my_policy®ion=china" );
344- try ( Driver driver = GraphDatabase .driver ( uri , INSECURE_CONFIG ); Session session = driver .session () )
345- {
346- List <Record > records = session .run ( "MATCH (n) RETURN n.name AS name" ).list ();
347- assertEquals ( 2 , records .size () );
348- assertEquals ( "Alice" , records .get ( 0 ).get ( "name" ).asString () );
349- assertEquals ( "Bob" , records .get ( 1 ).get ( "name" ).asString () );
350- }
351- finally
352- {
353- assertEquals ( 0 , server .exitStatus () );
354- }
355- }
356-
357- @ Test
358- void shouldSendRoutingContextInHelloMessage () throws Exception
359- {
360- // stub server is both a router and reader
361- StubServer server = StubServer .start ( "routing_context_in_hello_neo4j.script" , 9001 );
362-
363- URI uri = URI .create ( "neo4j://127.0.0.1:9001/?policy=my_policy®ion=china" );
364- try ( Driver driver = GraphDatabase .driver ( uri , INSECURE_CONFIG ); Session session = driver .session () )
365- {
366- List <Record > records = session .run ( "MATCH (n) RETURN n.name AS name" ).list ();
367- assertEquals ( 2 , records .size () );
368- assertEquals ( "Alice" , records .get ( 0 ).get ( "name" ).asString () );
369- assertEquals ( "Bob" , records .get ( 1 ).get ( "name" ).asString () );
370- }
371- finally
372- {
373- assertEquals ( 0 , server .exitStatus () );
374- }
375- }
376-
377218 @ Test
378219 void shouldFailInitialDiscoveryWhenConfiguredResolverThrows ()
379220 {
0 commit comments