postgresql-jdbc.git / summary / log / commit / refs
commit cf2d89ecd0eb2634c43a91be14a4c2e020cd33ae
Author: Vladimir Sitnikov <sitnikov.vladimir@gmail.com>
Date: Tue May 26 12:00:36 2026 +0000
test: make message assertions locale-independent
Several tests hard-coded the English form of exception messages
that are run through GT.tr in production code (see
pgjdbc/src/main/java/org/postgresql/translation), so the
assertions failed on a JVM whose default locale ships a
translation (for example ru_RU).
Compare against GT.tr(...) of the same template instead of the
raw English literal. The runtime substitution lines the test
up with whatever locale the JVM happens to pick, while keeping
the readable English template visible in source.
For ScramTest.rejectIterationCountAboveDefaultCap, drop the
contains("exceeds") check; the remaining assertions (the
scramMaxIterations property name and the locale-formatted
iteration count) already pin the test to the iteration-cap
error path.
For the binary-mode branch of ResultSetTest.testBadBoolean, the
"Cannot convert the column of type {0} to requested type {1}."
template is split into prefix/middle/suffix by formatting it
with placeholder markers, so the structural startsWith/endsWith
check now works under any locale.
Refs: https://github.com/pgjdbc/pgjdbc/actions/runs/26416335971
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
.../test/java/org/postgresql/jdbc/ScramTest.java | 13 ++++++-----
.../test/jdbc2/PreparedStatementTest.java | 18 +++++++--------
.../org/postgresql/test/jdbc2/ResultSetTest.java | 26 ++++++++++++++++------
.../test/jdbc2/UpdateableResultTest.java | 13 ++++++++---
4 files changed, 46 insertions(+), 24 deletions(-)
diff --git a/pgjdbc/src/test/java/org/postgresql/jdbc/ScramTest.java b/pgjdbc/src/test/java/org/postgresql/jdbc/ScramTest.java
index c20168eb..b221a0d3 100644
--- a/pgjdbc/src/test/java/org/postgresql/jdbc/ScramTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/jdbc/ScramTest.java
@@ -15,6 +15,7 @@ import org.postgresql.PGProperty;
import org.postgresql.core.ServerVersion;
import org.postgresql.test.TestUtil;
import org.postgresql.test.annotations.EnabledForServerVersionRange;
+import org.postgresql.util.GT;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;
@@ -120,7 +121,9 @@ class ScramTest {
() -> DriverManager.getConnection(TestUtil.getURL(), ROLE_NAME, password),
"SCRAM connection attempt with invalid password should fail");
- assertEquals(expectedMessage, e.getMessage());
+ // The driver localises messages via GT.tr, so compare against the translated form
+ // rather than the English source to keep the test locale-independent.
+ assertEquals(GT.tr(expectedMessage), e.getMessage());
}
private PSQLException scramAuthExpectingFailure(String scramMaxIterations, int serverScramIterations, String password) throws SQLException {
@@ -138,15 +141,15 @@ class ScramTest {
void rejectIterationCountAboveDefaultCap() throws SQLException {
int serverScramIterations = 789_123_456;
PSQLException ex = scramAuthExpectingFailure(null, serverScramIterations, "does-not-matter");
- assertTrue(ex.getMessage().contains("exceeds"),
- "expected iteration-cap error, got: " + ex.getMessage());
+ // The iteration-cap message is the only SCRAM error that references the property name,
+ // so checking for it pins the test to the right error path without depending on locale.
assertTrue(ex.getMessage().contains("scramMaxIterations"),
- "error should reference the connection property name, got: " + ex.getMessage());
+ "expected iteration-cap error referencing the connection property name, got: " + ex.getMessage());
// The message is formatted through MessageFormat, which applies locale-aware grouping
// to integer arguments; format the expected numbers the same way.
NumberFormat nf = NumberFormat.getNumberInstance();
assertTrue(ex.getMessage().contains(nf.format(serverScramIterations)),
- "error should include the configured cap, got: " + ex.getMessage());
+ "error should include the server-supplied iteration count, got: " + ex.getMessage());
}
@Test
diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PreparedStatementTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PreparedStatementTest.java
index 7d67114d..82f494c3 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PreparedStatementTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/PreparedStatementTest.java
@@ -1018,14 +1018,14 @@ public class PreparedStatementTest extends BaseTest4 {
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"this is not boolean\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "this is not boolean"), e.getMessage());
}
try {
pstmt.setObject(1, 'X', Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"X\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "X"), e.getMessage());
}
try {
java.io.File obj = new java.io.File("");
@@ -1040,35 +1040,35 @@ public class PreparedStatementTest extends BaseTest4 {
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"1.0\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "1.0"), e.getMessage());
}
try {
pstmt.setObject(1, "-1", Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"-1\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "-1"), e.getMessage());
}
try {
pstmt.setObject(1, "ok", Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"ok\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "ok"), e.getMessage());
}
try {
pstmt.setObject(1, 0.99f, Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"0.99\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "0.99"), e.getMessage());
}
try {
pstmt.setObject(1, -0.01d, Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"-0.01\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "-0.01"), e.getMessage());
}
try {
pstmt.setObject(1, new java.sql.Date(0), Types.BOOLEAN);
@@ -1082,14 +1082,14 @@ public class PreparedStatementTest extends BaseTest4 {
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"1000\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "1000"), e.getMessage());
}
try {
pstmt.setObject(1, Math.PI, Types.BOOLEAN);
fail();
} catch (SQLException e) {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"3.141592653589793\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "3.141592653589793"), e.getMessage());
}
pstmt.close();
}
diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/ResultSetTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/ResultSetTest.java
index f9dd6dcf..f4c7e175 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/ResultSetTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/ResultSetTest.java
@@ -19,6 +19,7 @@ import org.postgresql.PGConnection;
import org.postgresql.core.ServerVersion;
import org.postgresql.jdbc.PreferQueryMode;
import org.postgresql.test.TestUtil;
+import org.postgresql.util.GT;
import org.postgresql.util.PGobject;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;
@@ -426,8 +427,8 @@ public class ResultSetTest extends BaseTest4 {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
// message can be 2 or 2.0 depending on whether binary or text
final String message = e.getMessage();
- if (!"Cannot cast to boolean: \"2.0\"".equals(message)) {
- assertEquals("Cannot cast to boolean: \"2\"", message);
+ if (!GT.tr("Cannot cast to boolean: \"{0}\"", "2.0").equals(message)) {
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", "2"), message);
}
}
rs.close();
@@ -459,16 +460,27 @@ public class ResultSetTest extends BaseTest4 {
} catch (SQLException e) {
//binary transfer gets different error code and message
if (org.postgresql.util.PSQLState.DATA_TYPE_MISMATCH.getState().equals(e.getSQLState())) {
+ // The driver's "Cannot convert the column of type {0} to requested type {1}." message
+ // is localised via GT.tr. Derive the locale-specific prefix/middle/suffix by formatting
+ // the same template with placeholder markers and verify the actual message lines up.
final String message = e.getMessage();
- if (!message.startsWith("Cannot convert the column of type ")) {
- fail(message);
- }
- if (!message.endsWith(" to requested type boolean.")) {
+ final String marker0 = "@@COLTYPE@@";
+ final String marker1 = "@@REQTYPE@@";
+ final String localized = GT.tr(
+ "Cannot convert the column of type {0} to requested type {1}.", marker0, marker1);
+ final int idx0 = localized.indexOf(marker0);
+ final int idx1 = localized.indexOf(marker1);
+ final String prefix = localized.substring(0, idx0);
+ final String middle = localized.substring(idx0 + marker0.length(), idx1);
+ final String suffix = localized.substring(idx1 + marker1.length());
+ if (!message.startsWith(prefix)
+ || !message.contains(middle)
+ || !message.endsWith("boolean" + suffix)) {
fail(message);
}
} else {
assertEquals(PSQLState.CANNOT_COERCE.getState(), e.getSQLState());
- assertEquals("Cannot cast to boolean: \"" + value + "\"", e.getMessage());
+ assertEquals(GT.tr("Cannot cast to boolean: \"{0}\"", value), e.getMessage());
}
}
rs.close();
diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/UpdateableResultTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/UpdateableResultTest.java
index 902373df..1a42410b 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/jdbc2/UpdateableResultTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc2/UpdateableResultTest.java
@@ -16,6 +16,7 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
import org.postgresql.PGConnection;
import org.postgresql.test.TestUtil;
+import org.postgresql.util.GT;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@@ -796,7 +797,9 @@ public class UpdateableResultTest extends BaseTest4 {
rs.updateString("name1", "bob");
fail("Should have failed since unique column u1 is nullable");
} catch (SQLException ex) {
- assertEquals("No eligible primary or unique key found for table unique_null_constraint.", ex.getMessage());
+ assertEquals(
+ GT.tr("No eligible primary or unique key found for table {0}.", "unique_null_constraint"),
+ ex.getMessage());
}
rs.close();
st.close();
@@ -893,7 +896,9 @@ public class UpdateableResultTest extends BaseTest4 {
rs.updateDate("dt", Date.valueOf("1999-01-01"));
fail("Should have failed since id2 is nullable column");
} catch (SQLException ex) {
- assertEquals("No eligible primary or unique key found for table uniquekeys.", ex.getMessage());
+ assertEquals(
+ GT.tr("No eligible primary or unique key found for table {0}.", "uniquekeys"),
+ ex.getMessage());
}
rs.close();
st.close();
@@ -910,7 +915,9 @@ public class UpdateableResultTest extends BaseTest4 {
rs.updateDate("dt", Date.valueOf("1999-01-01"));
fail("Should have failed since no UK/PK are in the select statement");
} catch (SQLException ex) {
- assertEquals("No eligible primary or unique key found for table uniquekeys.", ex.getMessage());
+ assertEquals(
+ GT.tr("No eligible primary or unique key found for table {0}.", "uniquekeys"),
+ ex.getMessage());
}
rs.close();
st.close();
[parent: f0fbea821359]