Skip to content

Commit 561b860

Browse files
authored
Fix PreparedStatementTestBase#XXXX42P18 intermittent failures (#1654)
Changed implementation for the in-transaction case. There was a racy behavior between the closing of the connection close and the invocation of the assertion. Changed the implementation to close the connection after verifying expectations. Repeating test to make it more likely to fail on CI if there's still a problem. Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
1 parent a647366 commit 561b860

File tree

1 file changed

+51
-38
lines changed

1 file changed

+51
-38
lines changed

vertx-pg-client/src/test/java/io/vertx/tests/pgclient/PreparedStatementTestBase.java

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
/*
2-
* Copyright (C) 2017 Julien Viet
2+
* Copyright (c) 2011-2026 Contributors to the Eclipse Foundation
33
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7+
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
158
*
9+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
1610
*/
1711

1812
package io.vertx.tests.pgclient;
@@ -24,33 +18,20 @@
2418
import io.vertx.core.json.JsonObject;
2519
import io.vertx.ext.unit.Async;
2620
import io.vertx.ext.unit.TestContext;
21+
import io.vertx.ext.unit.junit.Repeat;
22+
import io.vertx.ext.unit.junit.RepeatRule;
2723
import io.vertx.pgclient.PgConnectOptions;
2824
import io.vertx.pgclient.PgConnection;
2925
import io.vertx.pgclient.PgException;
30-
import io.vertx.pgclient.data.Box;
31-
import io.vertx.pgclient.data.Circle;
32-
import io.vertx.pgclient.data.Interval;
33-
import io.vertx.pgclient.data.Line;
34-
import io.vertx.pgclient.data.LineSegment;
35-
import io.vertx.pgclient.data.Path;
36-
import io.vertx.pgclient.data.Point;
37-
import io.vertx.pgclient.data.Polygon;
38-
import io.vertx.sqlclient.Cursor;
39-
import io.vertx.sqlclient.Row;
40-
import io.vertx.sqlclient.RowIterator;
41-
import io.vertx.sqlclient.RowSet;
42-
import io.vertx.sqlclient.RowStream;
43-
import io.vertx.sqlclient.Tuple;
26+
import io.vertx.pgclient.data.*;
27+
import io.vertx.sqlclient.*;
4428
import org.junit.After;
4529
import org.junit.Before;
30+
import org.junit.Rule;
4631
import org.junit.Test;
4732

4833
import java.lang.reflect.Array;
49-
import java.time.LocalDate;
50-
import java.time.LocalDateTime;
51-
import java.time.LocalTime;
52-
import java.time.OffsetDateTime;
53-
import java.time.ZoneOffset;
34+
import java.time.*;
5435
import java.time.format.DateTimeFormatter;
5536
import java.util.Collections;
5637
import java.util.List;
@@ -65,6 +46,9 @@
6546
*/
6647
public abstract class PreparedStatementTestBase extends PgTestBase {
6748

49+
@Rule
50+
public RepeatRule rule = new RepeatRule();
51+
6852
Vertx vertx;
6953

7054
protected abstract PgConnectOptions options();
@@ -397,126 +381,148 @@ public void testCloseStatement(TestContext ctx) {
397381
}
398382

399383
@Test
384+
@Repeat(10)
400385
public void testInferDataTypeString42P18(TestContext ctx) {
401386
testInferDataType42P18(ctx, String.class, "WORLD", "WORLD");
402387
}
403388

404389
@Test
390+
@Repeat(10)
405391
public void testInferDataTypeBoolean42P18(TestContext ctx) {
406392
testInferDataType42P18(ctx, Boolean.class, true, "t");
407393
}
408394

409395
@Test
396+
@Repeat(10)
410397
public void testInferDataTypeShort42P18(TestContext ctx) {
411398
testInferDataType42P18(ctx, Short.class, (short)2, "2");
412399
}
413400

414401
@Test
402+
@Repeat(10)
415403
public void testInferDataTypeInteger42P18(TestContext ctx) {
416404
testInferDataType42P18(ctx, Integer.class, Integer.MAX_VALUE, "" + Integer.MAX_VALUE);
417405
}
418406

419407
@Test
408+
@Repeat(10)
420409
public void testInferDataTypeLong42P18(TestContext ctx) {
421410
testInferDataType42P18(ctx, Long.class, Long.MAX_VALUE, "" + Long.MAX_VALUE);
422411
}
423412

424413
@Test
414+
@Repeat(10)
425415
public void testInferDataTypeFloat42P18(TestContext ctx) {
426416
testInferDataType42P18(ctx, Float.class, 0F, "0");
427417
}
428418

429419
@Test
420+
@Repeat(10)
430421
public void testInferDataTypeDouble42P18(TestContext ctx) {
431422
testInferDataType42P18(ctx, Double.class, 0D, "0");
432423
}
433424

434425
@Test
426+
@Repeat(10)
435427
public void testInferDataTypeLocalDate42P18(TestContext ctx) {
436428
LocalDate value = LocalDate.now();
437429
testInferDataType42P18(ctx, LocalDate.class, value, value.toString());
438430
}
439431

440432
@Test
433+
@Repeat(10)
441434
public void testInferDataTypeLocalDateTime42P18(TestContext ctx) {
442435
LocalDateTime value = LocalDateTime.of(LocalDate.now(), LocalTime.NOON);
443436
String suffix = value.toLocalDate() + " " + value.toLocalTime().format(DateTimeFormatter.ISO_LOCAL_TIME);
444437
testInferDataType42P18(ctx, LocalDateTime.class, value, suffix, "{\"" + suffix + "\"}");
445438
}
446439

447440
@Test
441+
@Repeat(10)
448442
public void testInferDataTypeOffsetDateTime42P18(TestContext ctx) {
449443
OffsetDateTime value = OffsetDateTime.of(LocalDateTime.of(LocalDate.now(), LocalTime.NOON), ZoneOffset.UTC);
450444
String suffix = value.toLocalDate() + " " + value.toLocalTime().format(DateTimeFormatter.ISO_LOCAL_TIME) + "+00";
451445
testInferDataType42P18(ctx, OffsetDateTime.class, value, suffix, "{\"" + suffix + "\"}");
452446
}
453447

454448
@Test
449+
@Repeat(10)
455450
public void testInferDataTypeOffsetInterval42P18(TestContext ctx) {
456451
Interval value = Interval.of(1);
457452
testInferDataType42P18(ctx, Interval.class, value, "1 year", "{\"1 year\"}");
458453
}
459454

460455
@Test
456+
@Repeat(10)
461457
public void testInferDataTypeBuffer42P18(TestContext ctx) {
462458
testInferDataType42P18(ctx, Buffer.class, Buffer.buffer("WORLD"), "\\x574f524c44", "{\"\\\\x574f524c44\"}");
463459
}
464460

465461
@Test
462+
@Repeat(10)
466463
public void testInferDataTypeUUID42P18(TestContext ctx) {
467464
UUID value = UUID.randomUUID();
468465
testInferDataType42P18(ctx, UUID.class, value, "" + value);
469466
}
470467

471468
@Test
469+
@Repeat(10)
472470
public void testInferDataTypeJsonObject42P18(TestContext ctx) {
473471
JsonObject value = new JsonObject().put("foo", "bar");
474472
testInferDataType42P18(ctx, JsonObject.class, value, "" + value, "{\"{\\\"foo\\\":\\\"bar\\\"}\"}");
475473
}
476474

477475
@Test
476+
@Repeat(10)
478477
public void testInferDataTypeJsonArray42P18(TestContext ctx) {
479478
JsonArray value = new JsonArray().add(1).add("foo").add(true);
480479
testInferDataType42P18(ctx, JsonArray.class, value, "" + value, "{\"[1,\\\"foo\\\",true]\"}");
481480
}
482481

483482
@Test
483+
@Repeat(10)
484484
public void testInferDataTypePoint42P18(TestContext ctx) {
485485
Point value = new Point();
486486
testInferDataType42P18(ctx, Point.class, value, "(0,0)", "{\"(0,0)\"}");
487487
}
488488

489489
@Test
490+
@Repeat(10)
490491
public void testInferDataTypeLine42P18(TestContext ctx) {
491492
Line value = new Line(1.0, 0.0, 0.0);
492493
testInferDataType42P18(ctx, Line.class, value, "{1,0,0}", "{\"{1,0,0}\"}");
493494
}
494495

495496
@Test
497+
@Repeat(10)
496498
public void testInferDataTypeLineSegment42P18(TestContext ctx) {
497499
LineSegment value = new LineSegment();
498500
testInferDataType42P18(ctx, LineSegment.class, value, "[(0,0),(0,0)]", "{\"[(0,0),(0,0)]\"}");
499501
}
500502

501503
@Test
504+
@Repeat(10)
502505
public void testInferDataTypeBox42P18(TestContext ctx) {
503506
Box value = new Box();
504507
testInferDataType42P18(ctx, Box.class, value, "(0,0),(0,0)");
505508
}
506509

507510
@Test
511+
@Repeat(10)
508512
public void testInferDataTypePath42P18(TestContext ctx) {
509513
Path value = new Path().addPoint(new Point());
510514
testInferDataType42P18(ctx, Path.class, value, "((0,0))", "{\"((0,0))\"}");
511515
}
512516

513517
@Test
518+
@Repeat(10)
514519
public void testInferDataTypePolygon42P18(TestContext ctx) {
515520
Polygon value = new Polygon().addPoint(new Point()).addPoint(new Point()).addPoint(new Point());
516521
testInferDataType42P18(ctx, Polygon.class, value, "((0,0),(0,0),(0,0))", "{\"((0,0),(0,0),(0,0))\"}");
517522
}
518523

519524
@Test
525+
@Repeat(10)
520526
public void testInferDataTypeCircle42P18(TestContext ctx) {
521527
Circle value = new Circle();
522528
testInferDataType42P18(ctx, Circle.class, value, "<(0,0),0>", "{\"<(0,0),0>\"}");
@@ -548,14 +554,21 @@ private <T> void testInferDataType42P18(TestContext ctx, Class<T> type, T value,
548554
}));
549555
}));
550556
PgConnection.connect(vertx, options()).onComplete(ctx.asyncAssertSuccess(conn -> {
557+
Async async = ctx.async();
551558
conn.begin()
552-
.flatMap(tx -> conn.preparedQuery("SELECT CONCAT('HELLO ', $1)").execute(Tuple.of(value))
553-
.eventually(() -> conn.close())
554-
.onComplete(ctx.asyncAssertFailure(failure -> {
555-
if (!hasSqlstateCode(failure, "42P18")) {
556-
ctx.fail(failure);
557-
}
558-
})));
559+
.compose(tx -> conn.preparedQuery("SELECT CONCAT('HELLO ', $1)").execute(Tuple.of(value)))
560+
.onComplete(ar -> {
561+
if (ar.succeeded()) {
562+
conn.close().onComplete(v -> ctx.fail("Expected failure with SQLSTATE 42P18"));
563+
return;
564+
}
565+
Throwable failure = ar.cause();
566+
if (!hasSqlstateCode(failure, "42P18")) {
567+
conn.close().onComplete(ctx.asyncAssertSuccess(v -> ctx.fail(failure)));
568+
return;
569+
}
570+
conn.close().onComplete(v -> async.complete());
571+
});
559572
}));
560573
}
561574

0 commit comments

Comments
 (0)