Skip to content

Commit 8a5b80a

Browse files
authored
Separate Cloud Integration Tests (#2283)
Currently, cloud integration tests are part of the regular test suite but require cloud credentials to execute properly. This creates unnecessary overhead for developers who just want to run local builds or for CI jobs that don't have cloud access configured.
1 parent cdfc2d1 commit 8a5b80a

16 files changed

+116
-112
lines changed

build-logic/src/main/kotlin/polaris-runtime.gradle.kts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@ testing {
3131
// See https://github.com/quarkusio/quarkus/issues/22844
3232
systemProperty("junit.jupiter.extensions.autodetection.enabled", "true")
3333
}
34-
35-
if (testTask.name != "test") {
34+
}
35+
}
36+
fun intTestSuiteConfigure(testSuite: JvmTestSuite) =
37+
testSuite.run {
38+
targets.all {
3639
testTask.configure {
3740
// For Quarkus...
3841
//
@@ -42,15 +45,22 @@ testing {
4245
dependsOn(tasks.named("quarkusBuild"))
4346
}
4447
}
45-
}
46-
}
47-
register<JvmTestSuite>("intTest") {
48-
targets.all {
49-
tasks.named("compileIntTestJava").configure {
50-
dependsOn(tasks.named("compileQuarkusTestGeneratedSourcesJava"))
48+
tasks.named(sources.compileJavaTaskName).configure {
49+
dependsOn("compileQuarkusTestGeneratedSourcesJava")
5150
}
51+
configurations.named(sources.runtimeOnlyConfigurationName).configure {
52+
extendsFrom(configurations.getByName("testRuntimeOnly"))
53+
}
54+
configurations.named(sources.implementationConfigurationName).configure {
55+
// Let the test's implementation config extend testImplementation, so it also inherits the
56+
// project's "main" implementation dependencies (not just the "api" configuration)
57+
extendsFrom(configurations.getByName("testImplementation"))
58+
}
59+
sources { java.srcDirs(tasks.named("quarkusGenerateCodeTests")) }
5260
}
53-
sources { java.srcDirs(tasks.named("quarkusGenerateCodeTests")) }
61+
62+
listOf("intTest", "cloudTest").forEach {
63+
register<JvmTestSuite>(it).configure { intTestSuiteConfigure(this) }
5464
}
5565
}
5666
}
@@ -72,14 +82,6 @@ configurations.all {
7282
}
7383
}
7484

75-
// Let the test's implementation config extend testImplementation, so it also inherits the
76-
// project's "main" implementation dependencies (not just the "api" configuration)
77-
configurations.named("intTestImplementation").configure {
78-
extendsFrom(configurations.getByName("testImplementation"))
79-
}
80-
81-
dependencies { add("intTestImplementation", java.sourceSets.getByName("test").output.dirs) }
82-
8385
configurations.named("intTestRuntimeOnly").configure {
8486
extendsFrom(configurations.getByName("testRuntimeOnly"))
8587
}
Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@
2020

2121
import java.util.List;
2222
import java.util.Optional;
23-
import java.util.stream.Stream;
2423
import org.apache.polaris.core.admin.model.AwsStorageConfigInfo;
2524
import org.apache.polaris.core.admin.model.StorageConfigInfo;
26-
import org.assertj.core.util.Strings;
2725

2826
/** Runs PolarisRestCatalogIntegrationBase test on AWS. */
29-
public class PolarisRestCatalogAwsIntegrationTest extends PolarisRestCatalogIntegrationBase {
27+
public abstract class PolarisRestCatalogAwsIntegrationTestBase
28+
extends PolarisRestCatalogIntegrationBase {
3029
public static final String ROLE_ARN =
3130
Optional.ofNullable(System.getenv("INTEGRATION_TEST_ROLE_ARN"))
3231
.or(() -> Optional.ofNullable(System.getenv("INTEGRATION_TEST_S3_ROLE_ARN")))
@@ -41,9 +40,4 @@ protected StorageConfigInfo getStorageConfigInfo() {
4140
.setAllowedLocations(List.of(BASE_LOCATION))
4241
.build();
4342
}
44-
45-
@Override
46-
protected boolean shouldSkip() {
47-
return Stream.of(BASE_LOCATION, ROLE_ARN).anyMatch(Strings::isNullOrEmpty);
48-
}
4943
}
Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@
1919
package org.apache.polaris.service.it.test;
2020

2121
import java.util.List;
22-
import java.util.stream.Stream;
2322
import org.apache.polaris.core.admin.model.AzureStorageConfigInfo;
2423
import org.apache.polaris.core.admin.model.StorageConfigInfo;
25-
import org.assertj.core.util.Strings;
2624

2725
/** Runs PolarisRestCatalogIntegrationBase test on Azure. */
28-
public class PolarisRestCatalogAzureIntegrationTest extends PolarisRestCatalogIntegrationBase {
26+
public abstract class PolarisRestCatalogAzureIntegrationTestBase
27+
extends PolarisRestCatalogIntegrationBase {
2928
public static final String TENANT_ID = System.getenv("INTEGRATION_TEST_AZURE_TENANT_ID");
3029
public static final String BASE_LOCATION = System.getenv("INTEGRATION_TEST_AZURE_PATH");
3130

@@ -37,9 +36,4 @@ protected StorageConfigInfo getStorageConfigInfo() {
3736
.setAllowedLocations(List.of(BASE_LOCATION))
3837
.build();
3938
}
40-
41-
@Override
42-
protected boolean shouldSkip() {
43-
return Stream.of(BASE_LOCATION, TENANT_ID).anyMatch(Strings::isNullOrEmpty);
44-
}
4539
}

integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogFileIntegrationTest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ protected StorageConfigInfo getStorageConfigInfo() {
4646
.build();
4747
}
4848

49-
@Override
50-
protected boolean shouldSkip() {
51-
return false;
52-
}
53-
5449
private static String stripTrailingSlash(String uri) {
5550
return uri.endsWith("/") && uri.length() > "file:///".length()
5651
? uri.substring(0, uri.length() - 1)
Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@
1919
package org.apache.polaris.service.it.test;
2020

2121
import java.util.List;
22-
import java.util.stream.Stream;
2322
import org.apache.polaris.core.admin.model.GcpStorageConfigInfo;
2423
import org.apache.polaris.core.admin.model.StorageConfigInfo;
25-
import org.assertj.core.util.Strings;
2624

2725
/** Runs PolarisRestCatalogIntegrationBase test on GCP. */
28-
public class PolarisRestCatalogGcpIntegrationTest extends PolarisRestCatalogIntegrationBase {
26+
public abstract class PolarisRestCatalogGcpIntegrationTestBase
27+
extends PolarisRestCatalogIntegrationBase {
2928
public static final String SERVICE_ACCOUNT =
3029
System.getenv("INTEGRATION_TEST_GCS_SERVICE_ACCOUNT");
3130
public static final String BASE_LOCATION = System.getenv("INTEGRATION_TEST_GCS_PATH");
@@ -38,9 +37,4 @@ protected StorageConfigInfo getStorageConfigInfo() {
3837
.setAllowedLocations(List.of(BASE_LOCATION))
3938
.build();
4039
}
41-
42-
@Override
43-
protected boolean shouldSkip() {
44-
return Stream.of(BASE_LOCATION, SERVICE_ACCOUNT).anyMatch(Strings::isNullOrEmpty);
45-
}
4640
}

integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,6 @@ protected void initializeClientFileIO(FileIO fileIO) {
198198
fileIO.initialize(Map.of());
199199
}
200200

201-
/**
202-
* Determine whether the test should be skipped based on the environment or configuration.
203-
*
204-
* @return true if the test should be skipped, false otherwise
205-
*/
206-
protected abstract boolean shouldSkip();
207-
208201
@BeforeAll
209202
static void setup(PolarisApiEndpoints apiEndpoints, ClientCredentials credentials) {
210203
adminCredentials = credentials;
@@ -224,7 +217,6 @@ static void close() throws Exception {
224217

225218
@BeforeEach
226219
public void before(TestInfo testInfo) {
227-
Assumptions.assumeThat(shouldSkip()).isFalse();
228220
String principalName = client.newEntityName("snowman-rest");
229221
String principalRoleName = client.newEntityName("rest-admin");
230222
principalCredentials = managementApi.createPrincipalWithRole(principalName, principalRoleName);

runtime/service/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ For S3:
2727
```shell
2828
export INTEGRATION_TEST_S3_PATH="s3://bucket/subpath"
2929
export INTEGRATION_TEST_S3_ROLE_ARN="your-role-arn"
30-
./gradlew :polaris-runtime-service:intTest
30+
./gradlew :polaris-runtime-service:cloudTest
3131
```
3232
For Azure:
3333
```shell
3434
export INTEGRATION_TEST_AZURE_PATH="abfss://bucket/subpath"
3535
export INTEGRATION_TEST_AZURE_TENANT_ID="your-tenant-id"
36-
./gradlew :polaris-runtime-service:intTest
36+
./gradlew :polaris-runtime-service:cloudTest
3737
```
3838
For GCS:
3939
```shell
4040
export INTEGRATION_TEST_GCS_PATH="gs://bucket/subpath"
4141
export INTEGRATION_TEST_GCS_SERVICE_ACCOUNT="your-service-account"
42-
./gradlew :polaris-runtime-service:intTest
42+
./gradlew :polaris-runtime-service:cloudTest
4343
```

runtime/service/build.gradle.kts

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -212,50 +212,56 @@ tasks.named<Test>("test").configure {
212212
jvmArgs("-Xshare:off")
213213
}
214214

215-
tasks.named<Test>("intTest").configure {
216-
maxParallelForks = 1
217-
218-
val logsDir = project.layout.buildDirectory.get().asFile.resolve("logs")
219-
220-
// JVM arguments provider does not interfere with Gradle's cache keys
221-
jvmArgumentProviders.add(
222-
CommandLineArgumentProvider {
223-
// Same issue as above: allow a java security manager after Java 21
224-
// (this setting is for the application under test, while the setting above is for test code).
225-
val securityManagerAllow = "-Djava.security.manager=allow"
226-
227-
val args = mutableListOf<String>()
228-
229-
// Example: to attach a debugger to the spawned JVM running Quarkus, add
230-
// -Dquarkus.test.arg-line=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
231-
// to your test configuration.
232-
val explicitQuarkusTestArgLine = System.getProperty("quarkus.test.arg-line")
233-
var quarkusTestArgLine =
234-
if (explicitQuarkusTestArgLine != null) "$explicitQuarkusTestArgLine $securityManagerAllow"
235-
else securityManagerAllow
236-
237-
args.add("-Dquarkus.test.arg-line=$quarkusTestArgLine")
238-
// This property is not honored in a per-profile application.properties file,
239-
// so we need to set it here.
240-
args.add("-Dquarkus.log.file.path=${logsDir.resolve("polaris.log").absolutePath}")
241-
242-
// Add `quarkus.*` system properties, other than the ones explicitly set above
243-
System.getProperties()
244-
.filter {
245-
it.key.toString().startsWith("quarkus.") &&
246-
!"quarkus.test.arg-line".equals(it.key) &&
247-
!"quarkus.log.file.path".equals(it.key)
215+
listOf("intTest", "cloudTest")
216+
.map { tasks.named<Test>(it) }
217+
.forEach {
218+
it.configure {
219+
maxParallelForks = 1
220+
221+
val logsDir = project.layout.buildDirectory.get().asFile.resolve("logs")
222+
223+
// JVM arguments provider does not interfere with Gradle's cache keys
224+
jvmArgumentProviders.add(
225+
CommandLineArgumentProvider {
226+
// Same issue as above: allow a java security manager after Java 21
227+
// (this setting is for the application under test, while the setting above is for test
228+
// code).
229+
val securityManagerAllow = "-Djava.security.manager=allow"
230+
231+
val args = mutableListOf<String>()
232+
233+
// Example: to attach a debugger to the spawned JVM running Quarkus, add
234+
// -Dquarkus.test.arg-line=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
235+
// to your test configuration.
236+
val explicitQuarkusTestArgLine = System.getProperty("quarkus.test.arg-line")
237+
var quarkusTestArgLine =
238+
if (explicitQuarkusTestArgLine != null)
239+
"$explicitQuarkusTestArgLine $securityManagerAllow"
240+
else securityManagerAllow
241+
242+
args.add("-Dquarkus.test.arg-line=$quarkusTestArgLine")
243+
// This property is not honored in a per-profile application.properties file,
244+
// so we need to set it here.
245+
args.add("-Dquarkus.log.file.path=${logsDir.resolve("polaris.log").absolutePath}")
246+
247+
// Add `quarkus.*` system properties, other than the ones explicitly set above
248+
System.getProperties()
249+
.filter {
250+
it.key.toString().startsWith("quarkus.") &&
251+
!"quarkus.test.arg-line".equals(it.key) &&
252+
!"quarkus.log.file.path".equals(it.key)
253+
}
254+
.forEach { args.add("${it.key}=${it.value}") }
255+
256+
args
248257
}
249-
.forEach { args.add("${it.key}=${it.value}") }
250-
251-
args
258+
)
259+
// delete files from previous runs
260+
doFirst {
261+
// delete log files written by Polaris
262+
logsDir.deleteRecursively()
263+
// delete quarkus.log file (captured Polaris stdout/stderr)
264+
project.layout.buildDirectory.get().asFile.resolve("quarkus.log").delete()
265+
}
252266
}
253-
)
254-
// delete files from previous runs
255-
doFirst {
256-
// delete log files written by Polaris
257-
logsDir.deleteRecursively()
258-
// delete quarkus.log file (captured Polaris stdout/stderr)
259-
project.layout.buildDirectory.get().asFile.resolve("quarkus.log").delete()
260267
}
261-
}

runtime/service/src/intTest/java/org/apache/polaris/service/it/RestCatalogAwsIT.java renamed to runtime/service/src/cloudTest/java/org/apache/polaris/service/it/RestCatalogAwsIT.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
package org.apache.polaris.service.it;
2020

2121
import io.quarkus.test.junit.QuarkusIntegrationTest;
22-
import org.apache.polaris.service.it.test.PolarisRestCatalogAwsIntegrationTest;
22+
import org.apache.polaris.service.it.test.PolarisRestCatalogAwsIntegrationTestBase;
23+
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
2324

2425
@QuarkusIntegrationTest
25-
public class RestCatalogAwsIT extends PolarisRestCatalogAwsIntegrationTest {}
26+
@EnabledIfEnvironmentVariable(named = "INTEGRATION_TEST_S3_PATH", matches = ".+")
27+
public class RestCatalogAwsIT extends PolarisRestCatalogAwsIntegrationTestBase {}

runtime/service/src/intTest/java/org/apache/polaris/service/it/RestCatalogAzureIT.java renamed to runtime/service/src/cloudTest/java/org/apache/polaris/service/it/RestCatalogAzureIT.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
package org.apache.polaris.service.it;
2020

2121
import io.quarkus.test.junit.QuarkusIntegrationTest;
22-
import org.apache.polaris.service.it.test.PolarisRestCatalogAzureIntegrationTest;
22+
import org.apache.polaris.service.it.test.PolarisRestCatalogAzureIntegrationTestBase;
23+
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
2324

2425
@QuarkusIntegrationTest
25-
public class RestCatalogAzureIT extends PolarisRestCatalogAzureIntegrationTest {}
26+
@EnabledIfEnvironmentVariable(named = "INTEGRATION_TEST_AZURE_PATH", matches = ".+")
27+
public class RestCatalogAzureIT extends PolarisRestCatalogAzureIntegrationTestBase {}

0 commit comments

Comments
 (0)