Skip to content

Commit 5869727

Browse files
authored
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 73e9265 commit 5869727

4 files changed

Lines changed: 27 additions & 55 deletions

File tree

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

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -136,25 +136,21 @@ public void testCancelRequest(TestContext ctx) {
136136
public void testInflightCommandsFailWhenConnectionClosed(TestContext ctx) {
137137
connector.accept(ctx.asyncAssertSuccess(conn1 -> {
138138
conn1
139-
.query("SELECT pg_sleep(20)")
139+
.query("SELECT pg_backend_pid()")
140140
.execute()
141-
.onComplete(ctx.asyncAssertFailure(t -> {
142-
ctx.assertTrue(t instanceof ClosedConnectionException);
143-
}));
144-
connector.accept(ctx.asyncAssertSuccess(conn2 -> {
145-
conn2
146-
.query("SELECT * FROM pg_stat_activity WHERE state = 'active' AND query = 'SELECT pg_sleep(20)'")
147-
.execute()
148-
.onComplete(ctx.asyncAssertSuccess(statRes -> {
149-
for (Row row : statRes) {
150-
Integer id = row.getInteger("pid");
151-
// kill the connection
141+
.onComplete(ctx.asyncAssertSuccess(pidRes -> {
142+
int pid = pidRes.iterator().next().getInteger(0);
143+
conn1
144+
.query("SELECT pg_sleep(20)")
145+
.execute()
146+
.onComplete(ctx.asyncAssertFailure(t -> {
147+
ctx.assertTrue(t instanceof ClosedConnectionException);
148+
}));
149+
connector.accept(ctx.asyncAssertSuccess(conn2 -> {
152150
conn2
153-
.query(String.format("SELECT pg_terminate_backend(%d);", id))
151+
.query(String.format("SELECT pg_terminate_backend(%d)", pid))
154152
.execute()
155153
.onComplete(ctx.asyncAssertSuccess(v -> conn2.close()));
156-
break;
157-
}
158154
}));
159155
}));
160156
}));

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

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

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

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

241241
@Test
242242
public void testUseAvailableResources(TestContext ctx) {
243+
String appName = "test-" + UUID.randomUUID();
244+
options.addProperty("application_name", appName);
243245
int poolSize = 10;
244246
Async async = ctx.async(poolSize + 1);
245247
Pool pool = PgBuilder.pool(b -> b.connectingTo(options).with(new PoolOptions().setMaxSize(poolSize)));
@@ -256,7 +258,7 @@ public void testUseAvailableResources(TestContext ctx) {
256258
}
257259
vertx.setTimer(10 * poolSize + 50, event -> {
258260
ctrlConn
259-
.query("select count(*) as cnt from pg_stat_activity where application_name like '%vertx%'")
261+
.query("select count(*) as cnt from pg_stat_activity where application_name = '" + appName + "'")
260262
.execute()
261263
.onComplete(ctx.asyncAssertSuccess(rows -> {
262264
Integer count = rows.iterator().next().getInteger("cnt");
@@ -357,32 +359,6 @@ public void testCannotAcquireConnectionOnPipelinedPool(TestContext ctx) {
357359
.onComplete(ctx.asyncAssertFailure());
358360
}
359361

360-
/* @Test
361-
public void testPipeliningDistribution(TestContext ctx) {
362-
int num = 10;
363-
SqlClient pool = PgPool.client(options.setPipeliningLimit(512), new PoolOptions().setMaxSize(num));
364-
Async async = ctx.async(num);
365-
for (int i = 0;i < num;i++) {
366-
pool.query("select 1").execute(ctx.asyncAssertSuccess(res1 -> {
367-
async.countDown();
368-
}));
369-
}
370-
async.awaitSuccess(20_000);
371-
int s = ((PoolBase)pool).size();
372-
System.out.println("s = " + s);
373-
int count = 1000;
374-
Async async2 = ctx.async(num * count);
375-
for (int i = 0;i < count * num;i++) {
376-
pool.query("select 1").execute(ctx.asyncAssertSuccess(res1 -> {
377-
async2.countDown();
378-
}));
379-
}
380-
async2.awaitSuccess(20_000);
381-
((PoolBase)pool).check(ctx.asyncAssertSuccess(list -> {
382-
System.out.println("list = " + list);
383-
}));
384-
}*/
385-
386362
@Test
387363
public void testPoolIdleTimeout(TestContext ctx) {
388364
ProxyServer proxy = ProxyServer.create(vertx, options.getPort(), options.getHost());
@@ -508,6 +484,8 @@ public void testPoolConnectTimeout(TestContext ctx) {
508484
@Test
509485
@Repeat(50)
510486
public void testNoConnectionLeaks(TestContext ctx) {
487+
String appName = "test-" + UUID.randomUUID();
488+
options.addProperty("application_name", appName);
511489
Async killConnections = ctx.async();
512490
PgConnection.connect(vertx, options).onComplete(ctx.asyncAssertSuccess(conn -> {
513491
Collector<Row, ?, List<Boolean>> collector = mapping(row -> row.getBoolean(0), toList());
@@ -518,7 +496,7 @@ public void testNoConnectionLeaks(TestContext ctx) {
518496
}));
519497
killConnections.awaitSuccess();
520498

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

523501
int idleTimeout = 50;
524502
poolOptions

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

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

1212
package io.vertx.tests.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;
@@ -29,18 +25,21 @@
2925
import org.junit.Test;
3026
import org.junit.runner.RunWith;
3127

28+
import java.util.UUID;
3229
import java.util.concurrent.atomic.AtomicReference;
3330

3431
@RunWith(VertxUnitRunner.class)
3532
public class SharedPoolTest extends PgTestBase {
3633

37-
private static final String COUNT_CONNECTIONS_QUERY = "SELECT count(*) FROM pg_stat_activity WHERE application_name LIKE '%vertx%'";
38-
3934
Vertx vertx;
35+
String countConnectionsQuery;
4036

4137
@Before
4238
public void setup() throws Exception {
4339
super.setup();
40+
String applicationName = "test-" + UUID.randomUUID();
41+
options.addProperty("application_name", applicationName);
42+
countConnectionsQuery = "SELECT count(*) FROM pg_stat_activity WHERE application_name = '" + applicationName + "'";
4443
vertx = Vertx.vertx();
4544
}
4645

@@ -59,7 +58,7 @@ public void testUseSamePool(TestContext ctx) {
5958
public void start() {
6059
pool = PgBuilder.pool().connectingTo(options).with(new PoolOptions().setMaxSize(maxSize).setShared(true)).using(vertx).build();
6160
pool
62-
.query("SELECT pg_sleep(0.5);SELECT count(*) FROM pg_stat_activity WHERE application_name LIKE '%vertx%'")
61+
.query("SELECT pg_sleep(0.5);" + countConnectionsQuery)
6362
.execute()
6463
.onComplete(ctx.asyncAssertSuccess(rows -> {
6564
ctx.assertTrue(rows.next().iterator().next().getInteger(0) <= maxSize);
@@ -102,7 +101,7 @@ public void start() {
102101

103102
private Future<Void> waitUntilConnCountIs(SqlConnection conn, int remaining, int expectedCount) {
104103
if (remaining > 0) {
105-
return conn.query(COUNT_CONNECTIONS_QUERY).execute().compose(res -> {
104+
return conn.query(countConnectionsQuery).execute().compose(res -> {
106105
int num = res.iterator().next().getInteger(0);
107106
if (num == expectedCount) {
108107
return Future.succeededFuture();
@@ -135,13 +134,13 @@ public void start(Promise<Void> startPromise) {
135134
}
136135
}, new DeploymentOptions().setInstances(instances)).onComplete(ctx.asyncAssertSuccess(id -> {
137136
pool
138-
.query(COUNT_CONNECTIONS_QUERY)
137+
.query(countConnectionsQuery)
139138
.execute()
140139
.onComplete(ctx.asyncAssertSuccess(res1 -> {
141140
int num1 = res1.iterator().next().getInteger(0);
142141
ctx.assertTrue(num1 <= maxSize);
143142
vertx.undeploy(id)
144-
.compose(v -> pool.query(COUNT_CONNECTIONS_QUERY).execute())
143+
.compose(v -> pool.query(countConnectionsQuery).execute())
145144
.onComplete(ctx.asyncAssertSuccess(res2 -> {
146145
int num2 = res1.iterator().next().getInteger(0);
147146
ctx.assertEquals(num1, num2);

0 commit comments

Comments
 (0)