pgjdbc/pgjdbc GitHub issues and pull requests (mirror)  
help / color / mirror / Atom feed
From: vlsi (@vlsi) <[email protected]>
To: pgjdbc/pgjdbc <[email protected]>
Subject: [pgjdbc/pgjdbc] PR #4125: test: verify custom properties reach socket factory
Date: Tue, 02 Jun 2026 05:48:04 +0000
Message-ID: <[email protected]> (raw)

## Summary
- add a SocketFactory fixture that captures constructor Properties and can participate in real connections
- verify custom properties reach SocketFactory from explicit Properties via SocketFactoryFactory and a real connection
- verify custom URL parameters reach SocketFactory after Driver.parseURL and during a real connection

## Tests
- ./gradlew --quiet :postgresql:checkstyleTest
- ./gradlew --quiet :postgresql:test --tests org.postgresql.test.util.ObjectFactoryTest *(fails locally because PostgreSQL is not listening on localhost:5432; the new real-connection tests and existing invalidAuthenticationPlugin all hit the same connection-refused setup issue)*

diff --git a/pgjdbc/src/test/java/org/postgresql/test/util/CapturingSocketFactory.java b/pgjdbc/src/test/java/org/postgresql/test/util/CapturingSocketFactory.java
new file mode 100644
index 0000000000..4c68e320f0
--- /dev/null
+++ b/pgjdbc/src/test/java/org/postgresql/test/util/CapturingSocketFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2026, PostgreSQL Global Development Group
+ * See the LICENSE file in the project root for more information.
+ */
+
+package org.postgresql.test.util;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.net.SocketFactory;
+
+public class CapturingSocketFactory extends SocketFactory {
+  private static final AtomicReference<Properties> LAST_PROPERTIES = new AtomicReference<>();
+
+  final Properties properties;
+
+  public CapturingSocketFactory(Properties properties) {
+    this.properties = properties;
+    LAST_PROPERTIES.set(properties);
+  }
+
+  static void reset() {
+    LAST_PROPERTIES.set(null);
+  }
+
+  static Properties getLastProperties() {
+    return LAST_PROPERTIES.get();
+  }
+
+  @Override
+  public Socket createSocket() {
+    return new Socket();
+  }
+
+  @Override
+  public Socket createSocket(String host, int port) throws IOException {
+    return new Socket(host, port);
+  }
+
+  @Override
+  public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
+      throws IOException {
+    return new Socket(host, port, localHost, localPort);
+  }
+
+  @Override
+  public Socket createSocket(InetAddress host, int port) throws IOException {
+    return new Socket(host, port);
+  }
+
+  @Override
+  public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
+      int localPort) throws IOException {
+    return new Socket(address, port, localAddress, localPort);
+  }
+}
diff --git a/pgjdbc/src/test/java/org/postgresql/test/util/ObjectFactoryTest.java b/pgjdbc/src/test/java/org/postgresql/test/util/ObjectFactoryTest.java
index a04b8eac04..5c8ef29b8c 100644
--- a/pgjdbc/src/test/java/org/postgresql/test/util/ObjectFactoryTest.java
+++ b/pgjdbc/src/test/java/org/postgresql/test/util/ObjectFactoryTest.java
@@ -8,9 +8,14 @@
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
+import org.postgresql.Driver;
 import org.postgresql.PGProperty;
+import org.postgresql.core.SocketFactoryFactory;
 import org.postgresql.jdbc.SslMode;
 import org.postgresql.test.TestUtil;
 import org.postgresql.util.ObjectFactory;
@@ -19,6 +24,7 @@
 import org.junit.jupiter.api.Test;
 import org.opentest4j.MultipleFailuresError;
 
+import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Properties;
 
@@ -95,6 +101,75 @@ void invalidSslHostnameVerifier() {
     testInvalidInstantiation(PGProperty.SSL_HOSTNAME_VERIFIER, PSQLState.CONNECTION_FAILURE);
   }
 
+  @Test
+  void socketFactoryReceivesCustomProperties() throws SQLException {
+    Properties props = new Properties();
+    PGProperty.SOCKET_FACTORY.set(props, CapturingSocketFactory.class.getName());
+    props.setProperty("x-acme-customfield", "from-properties");
+
+    SocketFactory socketFactory = SocketFactoryFactory.getSocketFactory(props);
+
+    CapturingSocketFactory capturingSocketFactory =
+        assertInstanceOf(CapturingSocketFactory.class, socketFactory);
+    assertSame(props, capturingSocketFactory.properties);
+    assertEquals("from-properties",
+        capturingSocketFactory.properties.getProperty("x-acme-customfield"));
+  }
+
+  @Test
+  void socketFactoryReceivesCustomPropertiesFromUrl() throws SQLException {
+    Properties props = Driver.parseURL(
+        "jdbc:postgresql://localhost/test?socketFactory="
+            + CapturingSocketFactory.class.getName()
+            + "&x-acme-customfield=from-url",
+        null);
+    assertNotNull(props);
+
+    SocketFactory socketFactory = SocketFactoryFactory.getSocketFactory(props);
+
+    CapturingSocketFactory capturingSocketFactory =
+        assertInstanceOf(CapturingSocketFactory.class, socketFactory);
+    assertSame(props, capturingSocketFactory.properties);
+    assertEquals("from-url",
+        capturingSocketFactory.properties.getProperty("x-acme-customfield"));
+  }
+
+  @Test
+  void socketFactoryReceivesCustomPropertiesOnConnection() throws SQLException {
+    CapturingSocketFactory.reset();
+    Properties props = new Properties();
+    PGProperty.SOCKET_FACTORY.set(props, CapturingSocketFactory.class.getName());
+    props.setProperty("x-acme-customfield", "from-properties-connection");
+
+    try (Connection connection = TestUtil.openDB(props)) {
+      assertNotNull(connection);
+    }
+
+    Properties socketFactoryProperties = CapturingSocketFactory.getLastProperties();
+    assertNotNull(socketFactoryProperties);
+    assertEquals("from-properties-connection",
+        socketFactoryProperties.getProperty("x-acme-customfield"));
+  }
+
+  @Test
+  void socketFactoryReceivesCustomUrlPropertiesOnConnection() throws SQLException {
+    CapturingSocketFactory.reset();
+    Properties props = new Properties();
+    TestUtil.setTestUrlProperty(props, PGProperty.SOCKET_FACTORY,
+        CapturingSocketFactory.class.getName());
+    props.setProperty(TestUtil.TEST_URL_PROPERTY_PREFIX + "x-acme-customfield",
+        "from-url-connection");
+
+    try (Connection connection = TestUtil.openDB(props)) {
+      assertNotNull(connection);
+    }
+
+    Properties socketFactoryProperties = CapturingSocketFactory.getLastProperties();
+    assertNotNull(socketFactoryProperties);
+    assertEquals("from-url-connection",
+        socketFactoryProperties.getProperty("x-acme-customfield"));
+  }
+
   @Test
   void instantiateInvalidSocketFactory() {
     Properties props = new Properties();


reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: github://pgjdbc/pgjdbc
  Cc: [email protected], [email protected]
  Subject: Re: [pgjdbc/pgjdbc] PR #4125: test: verify custom properties reach socket factory
  In-Reply-To: <<[email protected]>>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox