diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index adfdd54fb..e58261fcd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -256,11 +256,24 @@ jobs: EOF - name: Install Java client run: mvn --also-make --batch-mode --no-transfer-progress -DskipTests=true -Dmaven.javadoc.skip=true install + - name: Generate Database Name + run: | + RANDOM_DB="clickhouse_java_test_${GITHUB_RUN_ID}_${RANDOM}" + echo "TEST_DB_NAME=$RANDOM_DB" >> $GITHUB_ENV + echo "Generated database name: $RANDOM_DB" + - name: Create Temporary Database + env: + CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} + run: | + echo "Creating database: \`$TEST_DB_NAME\`" + curl --fail-with-body -s -u "default:$CLICKHOUSE_CLOUD_PASSWORD" "https://$CLICKHOUSE_CLOUD_HOST:8443" --data-binary "CREATE DATABASE IF NOT EXISTS $TEST_DB_NAME" - name: Test http client env: - CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT }} - CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT }} + CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} CLIENT_JWT: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_JWT_DESERT_VM_43 }} + JWT_TEST_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT }} run: | mvn --batch-mode --no-transfer-progress --projects ${{ matrix.project }} -DclickhouseVersion=${{ matrix.clickhouse }} -Dprotocol=http -Dmaven.javadoc.skip=true verify - name: Upload test results @@ -271,6 +284,20 @@ jobs: path: | **/target/failsafe-reports **/target/surefire-reports + - name: Cleanup Database Unconditionally + if: always() # CRITICAL: This ensures the step runs regardless of previous success/failure + env: + CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT_PROD }} + CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT_PROD }} + run: | + # Verify we actually generated a DB name to avoid dropping something accidentally + if [ -n "$TEST_DB_NAME" ]; then + DROP_STMT="DROP DATABASE IF EXISTS \`$TEST_DB_NAME\`" + echo "Cleaning up database: \`$TEST_DB_NAME\` with statement '$DROP_STMT'"; + curl --fail-with-body -s -u "default:$CLICKHOUSE_CLOUD_PASSWORD" "https://$CLICKHOUSE_CLOUD_HOST:8443" --data-binary "$DROP_STMT"; + else + echo "No database name was generated; skipping cleanup."; + fi; test-jdbc-driver: runs-on: ubuntu-latest @@ -321,9 +348,6 @@ jobs: - name: Install Java client run: mvn --also-make --batch-mode --no-transfer-progress --projects clickhouse-http-client,client-v2 -DskipTests=true -Dmaven.javadoc.skip=true install - name: Test JDBC driver - env: - CLICKHOUSE_CLOUD_HOST: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_HOST_SMT }} - CLICKHOUSE_CLOUD_PASSWORD: ${{ secrets.INTEGRATIONS_TEAM_TESTS_CLOUD_PASSWORD_SMT }} run: | mvn --batch-mode --no-transfer-progress --projects clickhouse-jdbc,jdbc-v2 -DclickhouseVersion=${{ matrix.clickhouse }} -Dprotocol=${{ matrix.protocol }} -Dmaven.javadoc.skip=true verify - name: Upload test results diff --git a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java index d3a32515e..fc4f5f26c 100644 --- a/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java +++ b/clickhouse-client/src/test/java/com/clickhouse/client/ClickHouseServerForTest.java @@ -62,10 +62,23 @@ public class ClickHouseServerForTest { private static boolean isCloud = false; private static final String database; + private static final boolean localDatabase; static { properties = new Properties(System.getProperties()); - database = "clickhouse_java_" + UUID.randomUUID().toString().substring(0, 8) + "_test_" + System.currentTimeMillis(); + String externalDatabase = System.getenv("TEST_DB_NAME"); // see build.yaml workflow + if (externalDatabase != null && !externalDatabase.trim().isEmpty()) { + if (!externalDatabase.startsWith("clickhouse_java_test_")) { + throw new RuntimeException("external database for tests should start with 'clickhouse_java_test_'"); + } + localDatabase = false; + database = externalDatabase; + } else { + localDatabase = true; + database = "clickhouse_java_" + UUID.randomUUID().toString().substring(0, 8) + "_test_" + System.currentTimeMillis(); + } + + LOGGER.info("Local database: {}", localDatabase); String proxy = properties.getProperty("proxyAddress"); if (proxy != null && !proxy.isEmpty()) { // use external proxy @@ -320,10 +333,11 @@ public static boolean isCloud() { @BeforeSuite(groups = {"integration"}) public static void beforeSuite() { if (isCloud) { - if (!runQuery("CREATE DATABASE IF NOT EXISTS " + database)) { - throw new RuntimeException("Failed to create database for testing."); + if (localDatabase) { + if (!runQuery("CREATE DATABASE IF NOT EXISTS " + database)) { + throw new RuntimeException("Failed to create database for testing."); + } } - return; } @@ -358,8 +372,10 @@ public static void afterSuite() { } if (isCloud) { - if (!runQuery("DROP DATABASE IF EXISTS `" + database + "`")) { - LOGGER.warn("Failed to drop database for testing."); + if (localDatabase) { + if (!runQuery("DROP DATABASE IF EXISTS `" + database + "`")) { + LOGGER.warn("Failed to drop database for testing."); + } } } } @@ -391,16 +407,17 @@ public static boolean runQuery(String sql) { try { URL serverURL = new URL(uri); LOGGER.info("sending request to {} (uri={})", serverURL, uri); - + byte[] postData = sql.getBytes(StandardCharsets.UTF_8); for (int attempts = 0; attempts < 10; attempts++) { HttpURLConnection httpConn = (HttpURLConnection) serverURL.openConnection(); try { httpConn.setRequestMethod("POST"); httpConn.setDoOutput(true); httpConn.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(("default:" + getPassword()).getBytes())); + httpConn.setFixedLengthStreamingMode(postData.length); try (OutputStream out = httpConn.getOutputStream()) { - out.write(sql.getBytes(StandardCharsets.UTF_8)); + out.write(postData, 0, postData.length); out.flush(); } diff --git a/client-v2/src/test/java/com/clickhouse/client/HttpTransportTests.java b/client-v2/src/test/java/com/clickhouse/client/HttpTransportTests.java index a909afbc0..4c67ae3af 100644 --- a/client-v2/src/test/java/com/clickhouse/client/HttpTransportTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/HttpTransportTests.java @@ -1218,10 +1218,18 @@ public void testJWTWithCloud() throws Exception { if (!isCloud()) { return; // only for cloud } - String jwt = System.getenv("CLIENT_JWT"); - Assert.assertTrue(jwt != null && !jwt.trim().isEmpty(), "JWT is missing"); + final String jwt = System.getenv("CLIENT_JWT"); + final String host = System.getenv("JWT_TEST_HOST"); + Assert.assertTrue(jwt != null && !jwt.trim().isEmpty(), "CLIENT_JWT is not set."); + Assert.assertTrue(host != null && !host.trim().isEmpty(), "JWT_TEST_HOST is not set"); Assert.assertFalse(jwt.contains("\n") || jwt.contains("-----"), "JWT should be single string ready for HTTP header"); - try (Client client = newClient().useBearerTokenAuth(jwt).build()) { + try (Client client = new Client.Builder() + .addEndpoint(Protocol.HTTP, host, 8443, true) + .setUsername("default") + .compressClientRequest(false) + .setDefaultDatabase("default") + .serverSetting(ServerSettings.WAIT_END_OF_QUERY, "1") + .useBearerTokenAuth(jwt).build()) { try { List response = client.queryAll("SELECT user(), now()"); System.out.println("response: " + response.get(0).getString(1) + " time: " + response.get(0).getString(2));