Skip to content

Commit 44d7d8c

Browse files
committed
Improve test isolation for pg_stat_activity queries (#1670)
Use unique application_name per test to avoid counting connections left opened by other tests. In PgConnectionTest, capture the backend PID directly instead of searching pg_stat_activity by query text. Some portions of this content were created with the assistance of Claude Code. Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
1 parent daa0ff7 commit 44d7d8c

4 files changed

Lines changed: 39 additions & 55 deletions

File tree

vertx-pg-client/src/test/java/io/vertx/pgclient/PgConnectionTest.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
import io.vertx.ext.unit.Async;
2121
import io.vertx.ext.unit.TestContext;
2222
import io.vertx.sqlclient.ClosedConnectionException;
23-
import io.vertx.sqlclient.Row;
2423
import io.vertx.sqlclient.SqlResult;
2524
import io.vertx.sqlclient.Tuple;
26-
import org.junit.Ignore;
2725
import org.junit.Test;
2826

2927
import java.util.ArrayList;
@@ -125,17 +123,22 @@ public void testCancelRequest(TestContext ctx) {
125123
@Test
126124
public void testInflightCommandsFailWhenConnectionClosed(TestContext ctx) {
127125
connector.accept(ctx.asyncAssertSuccess(conn1 -> {
128-
conn1.query("SELECT pg_sleep(20)").execute(ctx.asyncAssertFailure(t -> {
129-
ctx.assertTrue(t instanceof ClosedConnectionException);
130-
}));
131-
connector.accept(ctx.asyncAssertSuccess(conn2 -> {
132-
conn2.query("SELECT * FROM pg_stat_activity WHERE state = 'active' AND query = 'SELECT pg_sleep(20)'").execute(ctx.asyncAssertSuccess(statRes -> {
133-
for (Row row : statRes) {
134-
Integer id = row.getInteger("pid");
135-
// kill the connection
136-
conn2.query(String.format("SELECT pg_terminate_backend(%d);", id)).execute(ctx.asyncAssertSuccess(v -> conn2.close()));
137-
break;
138-
}
126+
conn1
127+
.query("SELECT pg_backend_pid()")
128+
.execute()
129+
.onComplete(ctx.asyncAssertSuccess(pidRes -> {
130+
int pid = pidRes.iterator().next().getInteger(0);
131+
conn1
132+
.query("SELECT pg_sleep(20)")
133+
.execute()
134+
.onComplete(ctx.asyncAssertFailure(t -> {
135+
ctx.assertTrue(t instanceof ClosedConnectionException);
136+
}));
137+
connector.accept(ctx.asyncAssertSuccess(conn2 -> {
138+
conn2
139+
.query(String.format("SELECT pg_terminate_backend(%d)", pid))
140+
.execute()
141+
.onComplete(ctx.asyncAssertSuccess(v -> conn2.close()));
139142
}));
140143
}));
141144
}));

vertx-pg-client/src/test/java/io/vertx/pgclient/PgConnectionTestBase.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ public void testProtocolError(TestContext ctx) {
6464
CompletableFuture<Void> connected = new CompletableFuture<>();
6565
proxy.proxyHandler(conn -> {
6666
connected.thenAccept(v -> {
67-
System.out.println("send bogus");
6867
Buffer bogusMsg = Buffer.buffer();
6968
bogusMsg.appendByte((byte) 'R'); // Authentication
7069
bogusMsg.appendInt(0);

vertx-pg-client/src/test/java/io/vertx/pgclient/PgPoolTest.java

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ public void testConcurrentMultipleConnection(TestContext ctx) {
204204

205205
@Test
206206
public void testUseAvailableResources(TestContext ctx) {
207+
String appName = "test-" + UUID.randomUUID();
208+
options.addProperty("application_name", appName);
207209
int poolSize = 10;
208210
Async async = ctx.async(poolSize + 1);
209211
PgPool pool = PgPool.pool(options, new PoolOptions().setMaxSize(poolSize));
@@ -216,7 +218,10 @@ public void testUseAvailableResources(TestContext ctx) {
216218
});
217219
}
218220
vertx.setTimer(10 * poolSize + 50, event -> {
219-
ctrlConn.query("select count(*) as cnt from pg_stat_activity where application_name like '%vertx%'").execute(ctx.asyncAssertSuccess(rows -> {
221+
ctrlConn
222+
.query("select count(*) as cnt from pg_stat_activity where application_name = '" + appName + "'")
223+
.execute()
224+
.onComplete(ctx.asyncAssertSuccess(rows -> {
220225
Integer count = rows.iterator().next().getInteger("cnt");
221226
ctx.assertEquals(poolSize + 1, count);
222227
async.countDown();
@@ -305,32 +310,6 @@ public void testCannotAcquireConnectionOnPipelinedPool(TestContext ctx) {
305310
pool.getConnection(ctx.asyncAssertFailure());
306311
}
307312

308-
/* @Test
309-
public void testPipeliningDistribution(TestContext ctx) {
310-
int num = 10;
311-
SqlClient pool = PgPool.client(options.setPipeliningLimit(512), new PoolOptions().setMaxSize(num));
312-
Async async = ctx.async(num);
313-
for (int i = 0;i < num;i++) {
314-
pool.query("select 1").execute(ctx.asyncAssertSuccess(res1 -> {
315-
async.countDown();
316-
}));
317-
}
318-
async.awaitSuccess(20_000);
319-
int s = ((PoolBase)pool).size();
320-
System.out.println("s = " + s);
321-
int count = 1000;
322-
Async async2 = ctx.async(num * count);
323-
for (int i = 0;i < count * num;i++) {
324-
pool.query("select 1").execute(ctx.asyncAssertSuccess(res1 -> {
325-
async2.countDown();
326-
}));
327-
}
328-
async2.awaitSuccess(20_000);
329-
((PoolBase)pool).check(ctx.asyncAssertSuccess(list -> {
330-
System.out.println("list = " + list);
331-
}));
332-
}*/
333-
334313
@Test
335314
public void testPoolIdleTimeout(TestContext ctx) {
336315
ProxyServer proxy = ProxyServer.create(vertx, options.getPort(), options.getHost());
@@ -455,6 +434,8 @@ public void testPoolConnectTimeout(TestContext ctx) {
455434
@Test
456435
@Repeat(50)
457436
public void testNoConnectionLeaks(TestContext ctx) {
437+
String appName = "test-" + UUID.randomUUID();
438+
options.addProperty("application_name", appName);
458439
Async killConnections = ctx.async();
459440
PgConnection.connect(vertx, options, ctx.asyncAssertSuccess(conn -> {
460441
Collector<Row, ?, List<Boolean>> collector = mapping(row -> row.getBoolean(0), toList());
@@ -465,7 +446,7 @@ public void testNoConnectionLeaks(TestContext ctx) {
465446
}));
466447
killConnections.awaitSuccess();
467448

468-
String sql = "SELECT pg_backend_pid() AS pid, (SELECT count(*) FROM pg_stat_activity WHERE application_name LIKE '%vertx%') AS cnt";
449+
String sql = "SELECT pg_backend_pid() AS pid, (SELECT count(*) FROM pg_stat_activity WHERE application_name = '" + appName + "') AS cnt";
469450

470451
int idleTimeout = 50;
471452
poolOptions

vertx-pg-client/src/test/java/io/vertx/pgclient/SharedPoolTest.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@
1111

1212
package io.vertx.pgclient;
1313

14-
import io.vertx.core.AbstractVerticle;
15-
import io.vertx.core.DeploymentOptions;
16-
import io.vertx.core.Future;
17-
import io.vertx.core.Promise;
18-
import io.vertx.core.Vertx;
14+
import io.vertx.core.*;
1915
import io.vertx.ext.unit.Async;
2016
import io.vertx.ext.unit.TestContext;
2117
import io.vertx.ext.unit.junit.VertxUnitRunner;
@@ -26,18 +22,21 @@
2622
import org.junit.Test;
2723
import org.junit.runner.RunWith;
2824

25+
import java.util.UUID;
2926
import java.util.concurrent.atomic.AtomicReference;
3027

3128
@RunWith(VertxUnitRunner.class)
3229
public class SharedPoolTest extends PgTestBase {
3330

34-
private static final String COUNT_CONNECTIONS_QUERY = "SELECT count(*) FROM pg_stat_activity WHERE application_name LIKE '%vertx%'";
35-
3631
Vertx vertx;
32+
String countConnectionsQuery;
3733

3834
@Before
3935
public void setup() throws Exception {
4036
super.setup();
37+
String applicationName = "test-" + UUID.randomUUID();
38+
options.addProperty("application_name", applicationName);
39+
countConnectionsQuery = "SELECT count(*) FROM pg_stat_activity WHERE application_name = '" + applicationName + "'";
4140
vertx = Vertx.vertx();
4241
}
4342

@@ -56,8 +55,9 @@ public void testUseSamePool(TestContext ctx) {
5655
public void start() {
5756
pool = PgPool.pool(vertx, options, new PoolOptions().setMaxSize(maxSize).setShared(true));
5857
pool
59-
.query("SELECT pg_sleep(0.5);SELECT count(*) FROM pg_stat_activity WHERE application_name LIKE '%vertx%'")
60-
.execute(ctx.asyncAssertSuccess(rows -> {
58+
.query("SELECT pg_sleep(0.5);" + countConnectionsQuery)
59+
.execute()
60+
.onComplete(ctx.asyncAssertSuccess(rows -> {
6161
ctx.assertTrue(rows.next().iterator().next().getInteger(0) <= maxSize);
6262
}));
6363
}
@@ -93,7 +93,7 @@ public void start() {
9393

9494
private Future<Void> waitUntilConnCountIs(SqlConnection conn, int remaining, int expectedCount) {
9595
if (remaining > 0) {
96-
return conn.query(COUNT_CONNECTIONS_QUERY).execute().compose(res -> {
96+
return conn.query(countConnectionsQuery).execute().compose(res -> {
9797
int num = res.iterator().next().getInteger(0);
9898
if (num == expectedCount) {
9999
return Future.succeededFuture();
@@ -126,12 +126,13 @@ public void start(Promise<Void> startPromise) {
126126
}
127127
}, new DeploymentOptions().setInstances(instances), ctx.asyncAssertSuccess(id -> {
128128
pool
129-
.query(COUNT_CONNECTIONS_QUERY)
130-
.execute(ctx.asyncAssertSuccess(res1 -> {
129+
.query(countConnectionsQuery)
130+
.execute()
131+
.onComplete(ctx.asyncAssertSuccess(res1 -> {
131132
int num1 = res1.iterator().next().getInteger(0);
132133
ctx.assertTrue(num1 <= maxSize);
133134
vertx.undeploy(id)
134-
.compose(v -> pool.query(COUNT_CONNECTIONS_QUERY).execute())
135+
.compose(v -> pool.query(countConnectionsQuery).execute())
135136
.onComplete(ctx.asyncAssertSuccess(res2 -> {
136137
int num2 = res1.iterator().next().getInteger(0);
137138
ctx.assertEquals(num1, num2);

0 commit comments

Comments
 (0)