Skip to content

Commit

Permalink
test: Handle cleanup of connection creation in StatementTest
Browse files Browse the repository at this point in the history
  • Loading branch information
sehrope committed Sep 11, 2021
1 parent bb1f728 commit 1c5f527
Showing 1 changed file with 48 additions and 47 deletions.
95 changes: 48 additions & 47 deletions pgjdbc/src/test/java/org/postgresql/test/jdbc2/StatementTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -474,57 +474,58 @@ public void testWarningsAreCleared() throws SQLException {
@Test
public void testWarningsAreAvailableAsap()
throws Exception {
final Connection outerLockCon = TestUtil.openDB();
outerLockCon.setAutoCommit(false);
//Acquire an exclusive lock so we can block the notice generating statement
outerLockCon.createStatement().execute("LOCK TABLE test_lock IN ACCESS EXCLUSIVE MODE;");
con.createStatement()
.execute("CREATE OR REPLACE FUNCTION notify_then_sleep() RETURNS VOID AS "
+ "$BODY$ "
+ "BEGIN "
+ "RAISE NOTICE 'Test 1'; "
+ "RAISE NOTICE 'Test 2'; "
+ "LOCK TABLE test_lock IN ACCESS EXCLUSIVE MODE; "
+ "END "
+ "$BODY$ "
+ "LANGUAGE plpgsql;");
con.createStatement().execute("SET SESSION client_min_messages = 'NOTICE'");
//If we never receive the two warnings the statement will just hang, so set a low timeout
con.createStatement().execute("SET SESSION statement_timeout = 1000");
final PreparedStatement preparedStatement = con.prepareStatement("SELECT notify_then_sleep()");
final Callable<Void> warningReader = new Callable<Void>() {
@Override
public Void call() throws SQLException, InterruptedException {
while (true) {
SQLWarning warning = preparedStatement.getWarnings();
if (warning != null) {
assertEquals("First warning received not first notice raised",
"Test 1", warning.getMessage());
SQLWarning next = warning.getNextWarning();
if (next != null) {
assertEquals("Second warning received not second notice raised",
"Test 2", next.getMessage());
//Release the lock so that the notice generating statement can end.
outerLockCon.commit();
return null;
try (Connection outerLockCon = TestUtil.openDB()) {
outerLockCon.setAutoCommit(false);
//Acquire an exclusive lock so we can block the notice generating statement
outerLockCon.createStatement().execute("LOCK TABLE test_lock IN ACCESS EXCLUSIVE MODE;");
con.createStatement()
.execute("CREATE OR REPLACE FUNCTION notify_then_sleep() RETURNS VOID AS "
+ "$BODY$ "
+ "BEGIN "
+ "RAISE NOTICE 'Test 1'; "
+ "RAISE NOTICE 'Test 2'; "
+ "LOCK TABLE test_lock IN ACCESS EXCLUSIVE MODE; "
+ "END "
+ "$BODY$ "
+ "LANGUAGE plpgsql;");
con.createStatement().execute("SET SESSION client_min_messages = 'NOTICE'");
//If we never receive the two warnings the statement will just hang, so set a low timeout
con.createStatement().execute("SET SESSION statement_timeout = 1000");
final PreparedStatement preparedStatement = con.prepareStatement("SELECT notify_then_sleep()");
final Callable<Void> warningReader = new Callable<Void>() {
@Override
public Void call() throws SQLException, InterruptedException {
while (true) {
SQLWarning warning = preparedStatement.getWarnings();
if (warning != null) {
assertEquals("First warning received not first notice raised",
"Test 1", warning.getMessage());
SQLWarning next = warning.getNextWarning();
if (next != null) {
assertEquals("Second warning received not second notice raised",
"Test 2", next.getMessage());
//Release the lock so that the notice generating statement can end.
outerLockCon.commit();
return null;
}
}
//Break the loop on InterruptedException
Thread.sleep(0);
}
//Break the loop on InterruptedException
Thread.sleep(0);
}
}
};
ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
Future<Void> future = executorService.submit(warningReader);
//Statement should only finish executing once we have
//received the two notices and released the outer lock.
preparedStatement.execute();
};
ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
Future<Void> future = executorService.submit(warningReader);
//Statement should only finish executing once we have
//received the two notices and released the outer lock.
preparedStatement.execute();

//If test takes longer than 2 seconds its a failure.
future.get(2, TimeUnit.SECONDS);
} finally {
executorService.shutdownNow();
//If test takes longer than 2 seconds its a failure.
future.get(2, TimeUnit.SECONDS);
} finally {
executorService.shutdownNow();
}
}
}

Expand Down

0 comments on commit 1c5f527

Please sign in to comment.