diff --git a/java-bigquery/.cloudbuild/scripts/jdbc-nightly.sh b/java-bigquery/.cloudbuild/scripts/jdbc-nightly.sh
index 1bccb96f03f7..dea0728cbb7a 100644
--- a/java-bigquery/.cloudbuild/scripts/jdbc-nightly.sh
+++ b/java-bigquery/.cloudbuild/scripts/jdbc-nightly.sh
@@ -5,5 +5,4 @@ source .kokoro/common.sh
install_modules java-bigquery
cd ${ROOT_FOLDER}/java-bigquery/google-cloud-bigquery-jdbc
-make integration-test test=ITBigQueryJDBCTest
-make integration-test test=ITNightlyBigQueryTest
+make integration-test test=ITNightlyTests
diff --git a/java-bigquery/.cloudbuild/scripts/jdbc-presubmit.sh b/java-bigquery/.cloudbuild/scripts/jdbc-presubmit.sh
index 58164962a23f..1fb645b8e3d8 100644
--- a/java-bigquery/.cloudbuild/scripts/jdbc-presubmit.sh
+++ b/java-bigquery/.cloudbuild/scripts/jdbc-presubmit.sh
@@ -5,4 +5,4 @@ source .kokoro/common.sh
install_modules java-bigquery
cd ${ROOT_FOLDER}/java-bigquery/google-cloud-bigquery-jdbc
-make integration-test test=ITBigQueryJDBCTest
+make integration-test test=ITPresubmitTests
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/.gitignore b/java-bigquery/google-cloud-bigquery-jdbc/.gitignore
new file mode 100644
index 000000000000..b023676c0793
--- /dev/null
+++ b/java-bigquery/google-cloud-bigquery-jdbc/.gitignore
@@ -0,0 +1 @@
+drivers/
\ No newline at end of file
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/Makefile b/java-bigquery/google-cloud-bigquery-jdbc/Makefile
index 6adcb7e8a48d..db3a62e4637f 100644
--- a/java-bigquery/google-cloud-bigquery-jdbc/Makefile
+++ b/java-bigquery/google-cloud-bigquery-jdbc/Makefile
@@ -35,7 +35,7 @@ integration-test:
-DskipSurefire=$(skipSurefire) \
-Dclirr.skip=true \
-Denforcer.skip=true \
- -Dit.failIfNoSpecifiedTests=false \
+ -Dit.failIfNoSpecifiedTests=true \
-Dit.test=$(test) \
integration-test
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/pom-it.xml b/java-bigquery/google-cloud-bigquery-jdbc/pom-it.xml
new file mode 100644
index 000000000000..fcf489c17e2c
--- /dev/null
+++ b/java-bigquery/google-cloud-bigquery-jdbc/pom-it.xml
@@ -0,0 +1,138 @@
+
+
+ 4.0.0
+ com.google.cloud
+ google-cloud-bigquery-jdbc-it-standalone
+
+ 1.0-SNAPSHOT
+ jar
+ BigQuery JDBC Standalone IT Tests
+
+
+ UTF-8
+ 8
+ 8
+
+
+
+
+
+ com.google.cloud
+ google-cloud-bigquery-jdbc
+ 0.4.1-SNAPSHOT
+ test-jar
+ compile
+
+
+
+
+ org.junit.platform
+ junit-platform-console-standalone
+ 1.11.4
+ compile
+
+
+
+
+ com.google.truth
+ truth
+ 1.4.4
+ compile
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.11.4
+ compile
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.11.4
+ compile
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.11.4
+ compile
+
+
+ org.mockito
+ mockito-core
+ 4.11.0
+ compile
+
+
+ org.mockito
+ mockito-junit-jupiter
+ 4.11.0
+ compile
+
+
+ org.junit.platform
+ junit-platform-suite-api
+ 1.11.4
+ compile
+
+
+ org.junit.platform
+ junit-platform-suite-engine
+ 1.11.4
+ compile
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.2
+
+
+ package
+
+ shade
+
+
+
+ false
+
+
+ com.google.cloud:google-cloud-bigquery
+ com.google.cloud:google-cloud-bigquerystorage
+ io.grpc:*
+ com.google.protobuf:*
+
+
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+ META-INF/services/java.sql.Driver
+
+
+
+
+
+ org.junit.platform.console.ConsoleLauncher
+
+
+
+
+
+
+
+
+
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/pom.xml b/java-bigquery/google-cloud-bigquery-jdbc/pom.xml
index 11cfa93e59e9..fdba762cbb32 100644
--- a/java-bigquery/google-cloud-bigquery-jdbc/pom.xml
+++ b/java-bigquery/google-cloud-bigquery-jdbc/pom.xml
@@ -61,6 +61,13 @@
true
+
+
+ org.apache.maven.surefire
+ surefire-junit-platform
+ 3.5.2
+
+
org.jacoco
@@ -78,9 +85,9 @@
io.grpc:*
-
-
- org.apache.maven.plugins
+
+
+ org.apache.maven.plugins
maven-shade-plugin
3.5.2
@@ -300,6 +307,17 @@
mockito-junit-jupiter
test
+
+ org.junit.platform
+ junit-platform-suite-api
+ 1.11.4
+ test
+
+
+ org.junit.platform
+ junit-platform-suite-engine
+ test
+
@@ -324,6 +342,13 @@
--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+ --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED
+
+
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITAuthTests.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITAuthTests.java
new file mode 100644
index 000000000000..f57493a997de
--- /dev/null
+++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITAuthTests.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.bigquery.jdbc.it;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import com.google.cloud.ServiceOptions;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+public class ITAuthTests extends ITBase {
+ static final String PROJECT_ID = ServiceOptions.getDefaultProjectId();
+
+ private JsonObject getAuthJson() throws IOException {
+ final String secret = requireEnvVar("SA_SECRET");
+ JsonObject authJson;
+ // Supporting both formats of SA_SECRET:
+ // - Local runs can point to a json file
+ // - Cloud Build has JSON value
+ try {
+ InputStream stream = Files.newInputStream(Paths.get(secret));
+ InputStreamReader reader = new InputStreamReader(stream);
+ authJson = JsonParser.parseReader(reader).getAsJsonObject();
+ } catch (IOException e) {
+ authJson = JsonParser.parseString(secret).getAsJsonObject();
+ }
+ assertTrue(authJson.has("client_email"));
+ assertTrue(authJson.has("private_key"));
+ assertTrue(authJson.has("project_id"));
+ return authJson;
+ }
+
+ private void validateConnection(String connection_uri) throws SQLException {
+ Connection connection = DriverManager.getConnection(connection_uri);
+ assertNotNull(connection);
+ assertFalse(connection.isClosed());
+ String query =
+ "SELECT DISTINCT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT"
+ + " 850";
+ Statement statement = connection.createStatement();
+ ResultSet jsonResultSet = statement.executeQuery(query);
+ int totalRows = 0;
+ while (jsonResultSet.next()) {
+ totalRows += 1;
+ }
+ assertEquals(totalRows, 850);
+ connection.close();
+ }
+
+ @Test
+ public void testValidServiceAccountAuthentication() throws SQLException, IOException {
+ final JsonObject authJson = getAuthJson();
+ File tempFile = File.createTempFile("auth", ".json");
+ tempFile.deleteOnExit();
+ Files.write(tempFile.toPath(), authJson.toString().getBytes());
+
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
+ + "ProjectId="
+ + authJson.get("project_id").getAsString()
+ + ";OAuthType=0;"
+ + ";OAuthServiceAcctEmail=;"
+ + "OAuthPvtKeyPath="
+ + tempFile.toPath()
+ + ";";
+
+ validateConnection(connection_uri);
+ }
+
+ @Test
+ public void testServiceAccountAuthenticationMissingOAuthPvtKeyPath() throws SQLException {
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
+ + "ProjectId="
+ + PROJECT_ID
+ + ";OAuthType=0;";
+
+ try {
+ DriverManager.getConnection(connection_uri);
+ Assertions.fail();
+ } catch (Exception ex) {
+ assertTrue(ex.getMessage() != null);
+ }
+ }
+
+ @Test
+ public void testValidServiceAccountAuthenticationOAuthPvtKeyAsPath()
+ throws SQLException, IOException {
+ final JsonObject authJson = getAuthJson();
+ File tempFile = File.createTempFile("auth", ".json");
+ tempFile.deleteOnExit();
+ Files.write(tempFile.toPath(), authJson.toString().getBytes());
+
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
+ + "ProjectId="
+ + authJson.get("project_id").getAsString()
+ + ";OAuthType=0;"
+ + "OAuthServiceAcctEmail=;"
+ + ";OAuthPvtKey="
+ + tempFile.toPath()
+ + ";";
+ validateConnection(connection_uri);
+ }
+
+ @Test
+ public void testValidServiceAccountAuthenticationViaEmailAndPkcs8Key()
+ throws SQLException, IOException {
+ final JsonObject authJson = getAuthJson();
+
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
+ + "ProjectId="
+ + authJson.get("project_id").getAsString()
+ + ";OAuthType=0;"
+ + "OAuthServiceAcctEmail="
+ + authJson.get("client_email").getAsString()
+ + ";OAuthPvtKey="
+ + authJson.get("private_key").getAsString()
+ + ";";
+ validateConnection(connection_uri);
+ }
+
+ @Test
+ public void testValidServiceAccountAuthenticationOAuthPvtKeyAsJson()
+ throws SQLException, IOException {
+ final JsonObject authJson = getAuthJson();
+
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
+ + "ProjectId="
+ + authJson.get("project_id").getAsString()
+ + ";OAuthType=0;"
+ + "OAuthServiceAcctEmail=;"
+ + ";OAuthPvtKey="
+ + authJson.toString()
+ + ";";
+ validateConnection(connection_uri);
+ }
+
+ // TODO(kirl): Enable this test when pipeline has p12 secret available.
+ @Test
+ @Disabled
+ public void testValidServiceAccountAuthenticationP12() throws SQLException, IOException {
+ final JsonObject authJson = getAuthJson();
+ final String p12_file = requireEnvVar("SA_SECRET_P12");
+
+ final String connectionUri =
+ getBaseUri(0, authJson.get("project_id").getAsString())
+ .append("OAuthServiceAcctEmail", authJson.get("client_email").getAsString())
+ .append("OAuthPvtKeyPath", p12_file)
+ .toString();
+ validateConnection(connectionUri);
+ }
+
+ @Test
+ @Disabled
+ public void testValidGoogleUserAccountAuthentication() throws SQLException {
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
+ + PROJECT_ID
+ + ";OAuthType=1;OAuthClientId=client_id;OAuthClientSecret=client_secret;";
+
+ Connection connection = DriverManager.getConnection(connection_uri);
+ assertNotNull(connection);
+ assertFalse(connection.isClosed());
+
+ Statement statement = connection.createStatement();
+ ResultSet resultSet =
+ statement.executeQuery(
+ "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
+
+ assertEquals(50, resultSetRowCount(resultSet));
+ connection.close();
+ }
+
+ @Test
+ @Disabled
+ public void testValidExternalAccountAuthentication() throws SQLException {
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
+ + PROJECT_ID
+ + ";OAUTHTYPE=4;"
+ + "BYOID_AudienceUri=//iam.googleapis.com/projects//locations//workloadIdentityPools//providers/;"
+ + "BYOID_SubjectTokenType=;BYOID_CredentialSource={\"file\":\"/path/to/file\"};"
+ + "BYOID_SA_Impersonation_Uri=;BYOID_TokenUri=;";
+
+ Connection connection = DriverManager.getConnection(connection_uri);
+ assertNotNull(connection);
+ assertFalse(connection.isClosed());
+
+ Statement statement = connection.createStatement();
+ ResultSet resultSet =
+ statement.executeQuery(
+ "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
+
+ assertEquals(50, resultSetRowCount(resultSet));
+ connection.close();
+ }
+
+ @Test
+ @Disabled
+ public void testValidExternalAccountAuthenticationFromFile() throws SQLException {
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
+ + PROJECT_ID
+ + ";OAUTHTYPE=4;"
+ + "OAuthPvtKeyPath=/path/to/file;";
+
+ Connection connection = DriverManager.getConnection(connection_uri);
+ assertNotNull(connection);
+ assertFalse(connection.isClosed());
+
+ Statement statement = connection.createStatement();
+ ResultSet resultSet =
+ statement.executeQuery(
+ "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
+
+ assertEquals(50, resultSetRowCount(resultSet));
+ connection.close();
+ }
+
+ @Test
+ @Disabled
+ public void testValidExternalAccountAuthenticationRawJson() throws SQLException {
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
+ + PROJECT_ID
+ + ";OAUTHTYPE=4;OAuthPvtKey={\n"
+ + " \"universe_domain\": \"googleapis.com\",\n"
+ + " \"type\": \"external_account\",\n"
+ + " \"audience\":"
+ + " \"//iam.googleapis.com/projects//locations//workloadIdentityPools//providers/\",\n"
+ + " \"subject_token_type\": \"\",\n"
+ + " \"token_url\": \"\",\n"
+ + " \"credential_source\": {\n"
+ + " \"file\": \"/path/to/file\"\n"
+ + " },\n"
+ + " \"service_account_impersonation_url\": \"\"\n"
+ + "};";
+
+ Connection connection = DriverManager.getConnection(connection_uri);
+ assertNotNull(connection);
+ assertFalse(connection.isClosed());
+
+ Statement statement = connection.createStatement();
+ ResultSet resultSet =
+ statement.executeQuery(
+ "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
+
+ assertEquals(50, resultSetRowCount(resultSet));
+ connection.close();
+ }
+
+ // TODO(farhan): figure out how to programmatically generate an access token and test
+ @Test
+ @Disabled
+ public void testValidPreGeneratedAccessTokenAuthentication() throws SQLException {
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
+ + PROJECT_ID
+ + ";OAUTHTYPE=2;OAuthAccessToken=access_token;";
+
+ Connection connection = DriverManager.getConnection(connection_uri);
+ assertNotNull(connection);
+ assertFalse(connection.isClosed());
+
+ Statement statement = connection.createStatement();
+ ResultSet resultSet =
+ statement.executeQuery(
+ "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
+
+ assertEquals(50, resultSetRowCount(resultSet));
+ connection.close();
+ }
+
+ // TODO(obada): figure out how to programmatically generate a refresh token and test
+ @Test
+ @Disabled
+ public void testValidRefreshTokenAuthentication() throws SQLException {
+ String connection_uri =
+ "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
+ + PROJECT_ID
+ + ";OAUTHTYPE=2;OAuthRefreshToken=refresh_token;"
+ + ";OAuthClientId=client;OAuthClientSecret=secret;";
+
+ Connection connection = DriverManager.getConnection(connection_uri);
+ assertNotNull(connection);
+ assertFalse(connection.isClosed());
+
+ Statement statement = connection.createStatement();
+ ResultSet resultSet =
+ statement.executeQuery(
+ "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
+
+ assertEquals(50, resultSetRowCount(resultSet));
+ connection.close();
+ }
+
+ @Test
+ public void testValidApplicationDefaultCredentialsAuthentication() throws SQLException {
+ String connection_uri = getBaseUri(3, PROJECT_ID).toString();
+
+ Connection connection = DriverManager.getConnection(connection_uri);
+ assertNotNull(connection);
+ assertFalse(connection.isClosed());
+ connection.close();
+ }
+
+ // This test is useing the same client email as a main authorization & impersonation.
+ // It requires account to have 'tokenCreator' permission, see
+ // https://cloud.google.com/docs/authentication/use-service-account-impersonation#required-roles
+ @Test
+ public void testServiceAccountAuthenticationWithImpersonation() throws IOException, SQLException {
+ final JsonObject authJson = getAuthJson();
+
+ String connection_uri =
+ getBaseUri(0, authJson.get("project_id").getAsString())
+ .append("OAuthServiceAcctEmail", authJson.get("client_email").getAsString())
+ .append("OAuthPvtKey", authJson.get("private_key").getAsString())
+ .append("ServiceAccountImpersonationEmail", authJson.get("client_email").getAsString())
+ .toString();
+ validateConnection(connection_uri);
+ }
+
+ // This test uses the same client email for the main authorization and a chain of impersonations.
+ // It requires the account to have 'tokenCreator' permission on itself.
+ @Test
+ public void testServiceAccountAuthenticationWithChainedImpersonation()
+ throws IOException, SQLException {
+ final JsonObject authJson = getAuthJson();
+ String clientEmail = authJson.get("client_email").getAsString();
+
+ String connection_uri =
+ getBaseUri(0, authJson.get("project_id").getAsString())
+ .append("OAuthServiceAcctEmail", clientEmail)
+ .append("OAuthPvtKey", authJson.get("private_key").getAsString())
+ .append("ServiceAccountImpersonationEmail", clientEmail)
+ .append("ServiceAccountImpersonationChain", clientEmail + "," + clientEmail)
+ .toString();
+ validateConnection(connection_uri);
+ }
+}
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBase.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBase.java
index 5aa41b297512..ba92e2d70aec 100644
--- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBase.java
+++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBase.java
@@ -16,6 +16,27 @@
package com.google.cloud.bigquery.jdbc.it;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
import com.google.cloud.bigquery.jdbc.BigQueryJdbcBaseTest;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class ITBase extends BigQueryJdbcBaseTest {
+
+ protected static String requireEnvVar(String varName) {
+ String value = System.getenv(varName);
+ assertNotNull(
+ System.getenv(varName),
+ "Environment variable " + varName + " is required to perform these tests.");
+ return value;
+ }
-public class ITBase extends BigQueryJdbcBaseTest {}
+ protected int resultSetRowCount(ResultSet resultSet) throws SQLException {
+ int rowCount = 0;
+ while (resultSet.next()) {
+ rowCount++;
+ }
+ return rowCount;
+ }
+}
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBigQueryJDBCTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBigQueryJDBCTest.java
index 184b4d3d45d6..6cd75a49ecf5 100644
--- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBigQueryJDBCTest.java
+++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBigQueryJDBCTest.java
@@ -33,7 +33,6 @@
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.exception.BigQueryJdbcException;
-import com.google.cloud.bigquery.exception.BigQueryJdbcRuntimeException;
import com.google.cloud.bigquery.exception.BigQueryJdbcSqlFeatureNotSupportedException;
import com.google.cloud.bigquery.exception.BigQueryJdbcSqlSyntaxErrorException;
import com.google.cloud.bigquery.jdbc.BigQueryConnection;
@@ -43,15 +42,9 @@
import com.google.cloud.bigquery.jdbc.PooledConnectionListener;
import com.google.cloud.bigquery.jdbc.utils.TestUtilities.TestConnectionListener;
import com.google.common.collect.ImmutableMap;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.math.BigDecimal;
-import java.nio.file.Files;
-import java.nio.file.Paths;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
@@ -81,7 +74,6 @@
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
public class ITBigQueryJDBCTest extends ITBase {
@@ -124,49 +116,6 @@ public class ITBigQueryJDBCTest extends ITBase {
private static final Long CUSTOM_CONN_POOL_SIZE = 5L;
private static final Object EXCEPTION_REPLACEMENT = "EXCEPTION-WAS-RAISED";
- private static String requireEnvVar(String varName) {
- String value = System.getenv(varName);
- assertNotNull(
- System.getenv(varName),
- "Environment variable " + varName + " is required to perform these tests.");
- return value;
- }
-
- private JsonObject getAuthJson() throws IOException {
- final String secret = requireEnvVar("SA_SECRET");
- JsonObject authJson;
- // Supporting both formats of SA_SECRET:
- // - Local runs can point to a json file
- // - Cloud Build has JSON value
- try {
- InputStream stream = Files.newInputStream(Paths.get(secret));
- InputStreamReader reader = new InputStreamReader(stream);
- authJson = JsonParser.parseReader(reader).getAsJsonObject();
- } catch (IOException e) {
- authJson = JsonParser.parseString(secret).getAsJsonObject();
- }
- assertTrue(authJson.has("client_email"));
- assertTrue(authJson.has("private_key"));
- assertTrue(authJson.has("project_id"));
- return authJson;
- }
-
- private void validateConnection(String connection_uri) throws SQLException {
- Connection connection = DriverManager.getConnection(connection_uri);
- assertNotNull(connection);
- assertFalse(connection.isClosed());
- assertEquals(
- "GOOGLE_SERVICE_ACCOUNT",
- ((BigQueryConnection) connection).getAuthProperties().get("OAuthType"));
- String query =
- "SELECT DISTINCT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT"
- + " 850";
- Statement statement = connection.createStatement();
- ResultSet jsonResultSet = statement.executeQuery(query);
- assertTrue(jsonResultSet.getClass().getName().contains("BigQueryJsonResultSet"));
- connection.close();
- }
-
@BeforeAll
public static void beforeClass() throws SQLException {
bigQueryConnection = DriverManager.getConnection(connection_uri, new Properties());
@@ -187,320 +136,6 @@ public static void afterClass() throws SQLException {
bigQueryConnectionNoReadApi.close();
}
- @Test
- public void testValidServiceAccountAuthentication() throws SQLException, IOException {
- final JsonObject authJson = getAuthJson();
- File tempFile = File.createTempFile("auth", ".json");
- tempFile.deleteOnExit();
- Files.write(tempFile.toPath(), authJson.toString().getBytes());
-
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
- + "ProjectId="
- + authJson.get("project_id").getAsString()
- + ";OAuthType=0;"
- + "OAuthPvtKeyPath="
- + tempFile.toPath()
- + ";";
-
- validateConnection(connection_uri);
- }
-
- @Test
- public void testServiceAccountAuthenticationMissingOAuthPvtKeyPath() throws SQLException {
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
- + "ProjectId="
- + PROJECT_ID
- + ";OAuthType=0;";
-
- try {
- DriverManager.getConnection(connection_uri);
- Assertions.fail();
- } catch (BigQueryJdbcRuntimeException ex) {
- assertTrue(ex.getMessage().contains("No valid credentials provided."));
- }
- }
-
- @Test
- public void testValidServiceAccountAuthenticationOAuthPvtKeyAsPath()
- throws SQLException, IOException {
- final JsonObject authJson = getAuthJson();
- File tempFile = File.createTempFile("auth", ".json");
- tempFile.deleteOnExit();
- Files.write(tempFile.toPath(), authJson.toString().getBytes());
-
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
- + "ProjectId="
- + authJson.get("project_id").getAsString()
- + ";OAuthType=0;"
- + "OAuthServiceAcctEmail=;"
- + ";OAuthPvtKey="
- + tempFile.toPath()
- + ";";
- validateConnection(connection_uri);
- }
-
- @Test
- public void testValidServiceAccountAuthenticationViaEmailAndPkcs8Key()
- throws SQLException, IOException {
- final JsonObject authJson = getAuthJson();
-
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
- + "ProjectId="
- + authJson.get("project_id").getAsString()
- + ";OAuthType=0;"
- + "OAuthServiceAcctEmail="
- + authJson.get("client_email").getAsString()
- + ";OAuthPvtKey="
- + authJson.get("private_key").getAsString()
- + ";";
- validateConnection(connection_uri);
- }
-
- @Test
- public void testValidServiceAccountAuthenticationOAuthPvtKeyAsJson()
- throws SQLException, IOException {
- final JsonObject authJson = getAuthJson();
-
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;"
- + "ProjectId="
- + authJson.get("project_id").getAsString()
- + ";OAuthType=0;"
- + "OAuthServiceAcctEmail=;"
- + ";OAuthPvtKey="
- + authJson.toString()
- + ";";
- validateConnection(connection_uri);
- }
-
- // TODO(kirl): Enable this test when pipeline has p12 secret available.
- @Test
- @Disabled
- public void testValidServiceAccountAuthenticationP12() throws SQLException, IOException {
- final JsonObject authJson = getAuthJson();
- final String p12_file = requireEnvVar("SA_SECRET_P12");
-
- final String connectionUri =
- getBaseUri(0, authJson.get("project_id").getAsString())
- .append("OAuthServiceAcctEmail", authJson.get("client_email").getAsString())
- .append("OAuthPvtKeyPath", p12_file)
- .toString();
- validateConnection(connectionUri);
- }
-
- @Test
- @Disabled
- public void testValidGoogleUserAccountAuthentication() throws SQLException {
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
- + PROJECT_ID
- + ";OAuthType=1;OAuthClientId=client_id;OAuthClientSecret=client_secret;";
-
- Connection connection = DriverManager.getConnection(connection_uri);
- assertNotNull(connection);
- assertFalse(connection.isClosed());
- assertEquals(
- "GOOGLE_USER_ACCOUNT",
- ((BigQueryConnection) connection).getAuthProperties().get("OAuthType"));
-
- Statement statement = connection.createStatement();
- ResultSet resultSet =
- statement.executeQuery(
- "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
-
- assertEquals(50, resultSetRowCount(resultSet));
- connection.close();
- }
-
- @Test
- @Disabled
- public void testValidExternalAccountAuthentication() throws SQLException {
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
- + PROJECT_ID
- + ";OAUTHTYPE=4;"
- + "BYOID_AudienceUri=//iam.googleapis.com/projects//locations//workloadIdentityPools//providers/;"
- + "BYOID_SubjectTokenType=;BYOID_CredentialSource={\"file\":\"/path/to/file\"};"
- + "BYOID_SA_Impersonation_Uri=;BYOID_TokenUri=;";
-
- Connection connection = DriverManager.getConnection(connection_uri);
- assertNotNull(connection);
- assertFalse(connection.isClosed());
- assertEquals(
- "EXTERNAL_ACCOUNT_AUTH",
- ((BigQueryConnection) connection).getAuthProperties().get("OAuthType"));
-
- Statement statement = connection.createStatement();
- ResultSet resultSet =
- statement.executeQuery(
- "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
-
- assertEquals(50, resultSetRowCount(resultSet));
- connection.close();
- }
-
- @Test
- @Disabled
- public void testValidExternalAccountAuthenticationFromFile() throws SQLException {
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
- + PROJECT_ID
- + ";OAUTHTYPE=4;"
- + "OAuthPvtKeyPath=/path/to/file;";
-
- Connection connection = DriverManager.getConnection(connection_uri);
- assertNotNull(connection);
- assertFalse(connection.isClosed());
- assertEquals(
- "EXTERNAL_ACCOUNT_AUTH",
- ((BigQueryConnection) connection).getAuthProperties().get("OAuthType"));
-
- Statement statement = connection.createStatement();
- ResultSet resultSet =
- statement.executeQuery(
- "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
-
- assertEquals(50, resultSetRowCount(resultSet));
- connection.close();
- }
-
- @Test
- @Disabled
- public void testValidExternalAccountAuthenticationRawJson() throws SQLException {
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
- + PROJECT_ID
- + ";OAUTHTYPE=4;OAuthPvtKey={\n"
- + " \"universe_domain\": \"googleapis.com\",\n"
- + " \"type\": \"external_account\",\n"
- + " \"audience\":"
- + " \"//iam.googleapis.com/projects//locations//workloadIdentityPools//providers/\",\n"
- + " \"subject_token_type\": \"\",\n"
- + " \"token_url\": \"\",\n"
- + " \"credential_source\": {\n"
- + " \"file\": \"/path/to/file\"\n"
- + " },\n"
- + " \"service_account_impersonation_url\": \"\"\n"
- + "};";
-
- Connection connection = DriverManager.getConnection(connection_uri);
- assertNotNull(connection);
- assertFalse(connection.isClosed());
- assertEquals(
- "EXTERNAL_ACCOUNT_AUTH",
- ((BigQueryConnection) connection).getAuthProperties().get("OAuthType"));
-
- Statement statement = connection.createStatement();
- ResultSet resultSet =
- statement.executeQuery(
- "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
-
- assertEquals(50, resultSetRowCount(resultSet));
- connection.close();
- }
-
- // TODO(farhan): figure out how to programmatically generate an access token and test
- @Test
- @Disabled
- public void testValidPreGeneratedAccessTokenAuthentication() throws SQLException {
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
- + PROJECT_ID
- + ";OAUTHTYPE=2;OAuthAccessToken=access_token;";
-
- Connection connection = DriverManager.getConnection(connection_uri);
- assertNotNull(connection);
- assertFalse(connection.isClosed());
- assertEquals(
- "PRE_GENERATED_TOKEN",
- ((BigQueryConnection) connection).getAuthProperties().get("OAuthType"));
-
- Statement statement = connection.createStatement();
- ResultSet resultSet =
- statement.executeQuery(
- "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
-
- assertEquals(50, resultSetRowCount(resultSet));
- connection.close();
- }
-
- // TODO(obada): figure out how to programmatically generate a refresh token and test
- @Test
- @Disabled
- public void testValidRefreshTokenAuthentication() throws SQLException {
- String connection_uri =
- "jdbc:bigquery://https://www.googleapis.com/bigquery/v2:443;PROJECTID="
- + PROJECT_ID
- + ";OAUTHTYPE=2;OAuthRefreshToken=refresh_token;"
- + ";OAuthClientId=client;OAuthClientSecret=secret;";
-
- Connection connection = DriverManager.getConnection(connection_uri);
- assertNotNull(connection);
- assertFalse(connection.isClosed());
- assertEquals(
- "PRE_GENERATED_TOKEN",
- ((BigQueryConnection) connection).getAuthProperties().get("OAuthType"));
-
- Statement statement = connection.createStatement();
- ResultSet resultSet =
- statement.executeQuery(
- "SELECT repository_name FROM `bigquery-public-data.samples.github_timeline` LIMIT 50");
-
- assertEquals(50, resultSetRowCount(resultSet));
- connection.close();
- }
-
- @Test
- public void testValidApplicationDefaultCredentialsAuthentication() throws SQLException {
- String connection_uri = getBaseUri(3, PROJECT_ID).toString();
-
- Connection connection = DriverManager.getConnection(connection_uri);
- assertNotNull(connection);
- assertFalse(connection.isClosed());
- assertEquals(
- "APPLICATION_DEFAULT_CREDENTIALS",
- ((BigQueryConnection) connection).getAuthProperties().get("OAuthType"));
- connection.close();
- }
-
- // This test is useing the same client email as a main authorization & impersonation.
- // It requires account to have 'tokenCreator' permission, see
- // https://cloud.google.com/docs/authentication/use-service-account-impersonation#required-roles
- @Test
- public void testServiceAccountAuthenticationWithImpersonation() throws IOException, SQLException {
- final JsonObject authJson = getAuthJson();
-
- String connection_uri =
- getBaseUri(0, authJson.get("project_id").getAsString())
- .append("OAuthServiceAcctEmail", authJson.get("client_email").getAsString())
- .append("OAuthPvtKey", authJson.get("private_key").getAsString())
- .append("ServiceAccountImpersonationEmail", authJson.get("client_email").getAsString())
- .toString();
- validateConnection(connection_uri);
- }
-
- // This test uses the same client email for the main authorization and a chain of impersonations.
- // It requires the account to have 'tokenCreator' permission on itself.
- @Test
- public void testServiceAccountAuthenticationWithChainedImpersonation()
- throws IOException, SQLException {
- final JsonObject authJson = getAuthJson();
- String clientEmail = authJson.get("client_email").getAsString();
-
- String connection_uri =
- getBaseUri(0, authJson.get("project_id").getAsString())
- .append("OAuthServiceAcctEmail", clientEmail)
- .append("OAuthPvtKey", authJson.get("private_key").getAsString())
- .append("ServiceAccountImpersonationEmail", clientEmail)
- .append("ServiceAccountImpersonationChain", clientEmail + "," + clientEmail)
- .toString();
- validateConnection(connection_uri);
- }
-
@Test
public void testFastQueryPathSmall() throws SQLException {
String query =
@@ -4428,12 +4063,4 @@ public void validateGetObjectNullValues() throws Exception {
}
}
}
-
- private int resultSetRowCount(ResultSet resultSet) throws SQLException {
- int rowCount = 0;
- while (resultSet.next()) {
- rowCount++;
- }
- return rowCount;
- }
}
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITDriverAgnosticTests.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITDriverAgnosticTests.java
new file mode 100644
index 000000000000..fe20abcbb2c3
--- /dev/null
+++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITDriverAgnosticTests.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.bigquery.jdbc.it.suites;
+
+import com.google.cloud.bigquery.jdbc.it.ITAuthTests;
+import org.junit.platform.suite.api.SelectClasses;
+import org.junit.platform.suite.api.Suite;
+
+@Suite
+@SelectClasses({ITAuthTests.class})
+public class ITDriverAgnosticTests {}
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITNightlyTests.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITNightlyTests.java
new file mode 100644
index 000000000000..2700c18adbbd
--- /dev/null
+++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITNightlyTests.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.bigquery.jdbc.it.suites;
+
+import com.google.cloud.bigquery.jdbc.it.ITAuthTests;
+import com.google.cloud.bigquery.jdbc.it.ITBigQueryJDBCTest;
+import com.google.cloud.bigquery.jdbc.it.ITNightlyBigQueryTest;
+import org.junit.platform.suite.api.SelectClasses;
+import org.junit.platform.suite.api.Suite;
+
+@Suite
+@SelectClasses({ITAuthTests.class, ITBigQueryJDBCTest.class, ITNightlyBigQueryTest.class})
+public class ITNightlyTests {}
diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITPresubmitTests.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITPresubmitTests.java
new file mode 100644
index 000000000000..5f0517f17399
--- /dev/null
+++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/suites/ITPresubmitTests.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.bigquery.jdbc.it.suites;
+
+import com.google.cloud.bigquery.jdbc.it.ITAuthTests;
+import com.google.cloud.bigquery.jdbc.it.ITBigQueryJDBCTest;
+import org.junit.platform.suite.api.SelectClasses;
+import org.junit.platform.suite.api.Suite;
+
+@Suite
+@SelectClasses({ITAuthTests.class, ITBigQueryJDBCTest.class})
+public class ITPresubmitTests {}
diff --git a/java-bigquery/pom.xml b/java-bigquery/pom.xml
index c512c269c1a7..b65f6b7a3e35 100644
--- a/java-bigquery/pom.xml
+++ b/java-bigquery/pom.xml
@@ -133,6 +133,8 @@
com.google.api:gax
org.junit.jupiter:junit-jupiter-engine
+
+ org.junit.platform:junit-platform-suite-engine
javax.annotation:javax.annotation-api