20
20
21
21
import static org .junit .jupiter .api .Assertions .assertEquals ;
22
22
import static org .junit .jupiter .api .Assertions .assertFalse ;
23
+ import static org .junit .jupiter .api .Assertions .assertNull ;
23
24
import static org .junit .jupiter .api .Assertions .assertNotNull ;
24
25
import static org .junit .jupiter .api .Assertions .assertThrows ;
25
26
import static org .junit .jupiter .api .Assertions .assertTrue ;
28
29
public class ClientReconnectIT extends AbstractTarantoolConnectorIT {
29
30
private static final String INSTANCE_NAME = "jdk-testing" ;
30
31
private TarantoolClient client ;
32
+ private static final int NON_EXIST_PORT = 3333 ;
31
33
32
34
@ AfterEach
33
35
public void tearDown () {
@@ -215,19 +217,27 @@ public void run() {
215
217
216
218
/**
217
219
* Test concurrent operations, reconnects and close.
220
+ *
218
221
* Expected situation is nothing gets stuck.
222
+ *
223
+ * The test sets SO_LINGER to 0 for outgoing connections to avoid producing
224
+ * many TIME_WAIT sockets, because an available port range can be
225
+ * exhausted.
219
226
*/
220
227
@ Test
221
228
public void testLongParallelCloseReconnects () {
222
229
int numThreads = 4 ;
223
230
int numClients = 4 ;
224
231
int timeBudget = 30 *1000 ;
225
232
233
+ SocketChannelProvider provider = new TestSocketChannelProvider (host ,
234
+ port , RESTART_TIMEOUT ).setSoLinger (0 );
235
+
226
236
final AtomicReferenceArray <TarantoolClient > clients =
227
237
new AtomicReferenceArray <TarantoolClient >(numClients );
228
238
229
239
for (int idx = 0 ; idx < clients .length (); idx ++) {
230
- clients .set (idx , makeClient ());
240
+ clients .set (idx , makeClient (provider ));
231
241
}
232
242
233
243
final Random rnd = new Random ();
@@ -256,7 +266,7 @@ public void run() {
256
266
257
267
cli .close ();
258
268
259
- TarantoolClient next = makeClient ();
269
+ TarantoolClient next = makeClient (provider );
260
270
if (!clients .compareAndSet (idx , cli , next )) {
261
271
next .close ();
262
272
}
@@ -284,7 +294,9 @@ public void run() {
284
294
fail (e );
285
295
}
286
296
if (deadline > System .currentTimeMillis ()) {
287
- System .out .println ("" + (deadline - System .currentTimeMillis ())/1000 + "s remains." );
297
+ System .out .println ("testLongParallelCloseReconnects: " +
298
+ (deadline - System .currentTimeMillis ()) / 1000 +
299
+ "s remain" );
288
300
}
289
301
}
290
302
@@ -302,4 +314,86 @@ public void run() {
302
314
303
315
assertTrue (cnt .get () > threads .length );
304
316
}
317
+
318
+ /**
319
+ * Verify that we don't exceed a file descriptor limit (and so likely don't
320
+ * leak file descriptors) when trying to connect to a non existing node.
321
+ *
322
+ * The test sets SO_LINGER to 0 for outgoing connections to avoid producing
323
+ * many TIME_WAIT sockets, because an available port range can be
324
+ * exhausted.
325
+ */
326
+ @ Test
327
+ public void testReconnectNonExist () throws Exception {
328
+ SocketChannelProvider provider = new TestSocketChannelProvider (host ,
329
+ NON_EXIST_PORT , RESTART_TIMEOUT ).setSoLinger (0 );
330
+ TarantoolClientConfig config = makeClientConfig ();
331
+ config .initTimeoutMillis = 100 ;
332
+ for (int i = 0 ; i < 100 ; ++i ) {
333
+ if (i % 10 == 0 )
334
+ System .out .println ("testReconnectNonExist: " + (100 - i ) +
335
+ " iterations remain" );
336
+ CommunicationException e = assertThrows (CommunicationException .class ,
337
+ new Executable () {
338
+ @ Override
339
+ public void execute () throws Throwable {
340
+ client = new TarantoolClientImpl (provider , config );
341
+ }
342
+ }
343
+ );
344
+ assertEquals (e .getMessage (), "100ms is exceeded when waiting " +
345
+ "for client initialization. You could configure init " +
346
+ "timeout in TarantoolConfig" );
347
+ }
348
+
349
+ /*
350
+ * Verify we don't exceed a file descriptor limit. If we exceed it, a
351
+ * client will not able to connect to tarantool.
352
+ */
353
+ TarantoolClient client = makeClient ();
354
+ client .syncOps ().ping ();
355
+ client .close ();
356
+ }
357
+
358
+ /**
359
+ * Verify that we don't exceed a file descriptor limit (and so likely don't
360
+ * leak file descriptors) when trying to connect to an existing node with
361
+ * wrong authentification credentials.
362
+ *
363
+ * The test sets SO_LINGER to 0 for outgoing connections to avoid producing
364
+ * many TIME_WAIT sockets, because an available port range can be
365
+ * exhausted.
366
+ */
367
+ @ Test
368
+ public void testReconnectWrongAuth () throws Exception {
369
+ SocketChannelProvider provider = new TestSocketChannelProvider (host ,
370
+ port , RESTART_TIMEOUT ).setSoLinger (0 );
371
+ TarantoolClientConfig config = makeClientConfig ();
372
+ config .initTimeoutMillis = 100 ;
373
+ config .password = config .password + 'x' ;
374
+ for (int i = 0 ; i < 100 ; ++i ) {
375
+ if (i % 10 == 0 )
376
+ System .out .println ("testReconnectWrongAuth: " + (100 - i ) +
377
+ " iterations remain" );
378
+ CommunicationException e = assertThrows (CommunicationException .class ,
379
+ new Executable () {
380
+ @ Override
381
+ public void execute () throws Throwable {
382
+ client = new TarantoolClientImpl (provider , config );
383
+ }
384
+ }
385
+ );
386
+ assertEquals (e .getMessage (), "100ms is exceeded when waiting " +
387
+ "for client initialization. You could configure init " +
388
+ "timeout in TarantoolConfig" );
389
+ }
390
+
391
+ /*
392
+ * Verify we don't exceed a file descriptor limit. If we exceed it, a
393
+ * client will not able to connect to tarantool.
394
+ */
395
+ TarantoolClient client = makeClient ();
396
+ client .syncOps ().ping ();
397
+ client .close ();
398
+ }
305
399
}
0 commit comments