Skip to content

Commit 4aa5355

Browse files
authored
test: introduce new StorageITRunner (#1785)
## New StorageITRunner Add two new JUnit runner to provide support for Cross Running test in a class across multiple backends and transports. When a class is annotated `@CrossRun(transports = {HTTP, GRPC}, backends = {PROD, TEST_BENCH})` each test defined in the class will be ran four times, once for each pair from the permutation. Each permutation will add a new entry to the test suite of the form `[Transport][Backend]`. This name form can be thought of as keys to access a location in an adjacency matrix. If only a single backed is needed `@SingleBackend()` can be used to denote the backend. If a class is annotated `@ParallelFriendly` the test suite may attempt to run the tests in parallel. Currently parallelism factor is set to 2 * core count. ### Field `@Inject`ion When defining the test several "globally scoped" items are available for injection to the test class by annotating a public non-final field with `@Inject`. Instances of Storage, along with BucketInfo, TestBench, etc. are registered as injectable values. If a field isn't able to be injected an InitializationError will be raised with details as to why. ### `CrossRun.Ignore` & `CrossRun.Exclude` Not all tests in a class will apply to all intersections, to allow filtering out tests for these cases there are two new annotations which can be used. If a test is both Ignored and Excluded, the Ignore will take precedence. `@Ignore`d functions similar to the standard `@org.junit.Ignore` where the test will be loaded but not ran. `@Exclude`d tests will not be loaded into the suite at all, thereby not being reported at all. ### `@Parameterized` running When a class is annotated `@Parameterized(ParameterProvider)` in addition to and Cross Run previously resolved, each parameter will result in another dimension added to the suite. The name of the suite will be extended with another dimension below any cross name, for example `[HTTP][PROD][myParam]`. ### Runner Registry A new class `Registry` has been added which is responsible for managing "globally scoped" instances of resources associated with running integration tests. All injectable instances are registered with the Registry and will be lazily initialized, reused and cleaned up. Instances like Storage clients, Backend Buckets, standard objects etc are all managed per backend. When a BucketInfo is loaded into the registry it's name is also made available to the provider for Storage instances. If a test attempts to mutate the state of a bucket the operation will be interrupted with a vetoing exception causing the test to fail. ## Refactoring Done 1. TestBench is now a Registry Resource and shouldn't be used outside that context. Since testbench binds ports it is not a multi instance thing anyway. 2. Remove StorageFixture in favor of Registry Field Injection 3. Remove BucketFixture in favor of Registry Field Injection 4. All IT test now use either of the two new runners 5. Remove ParallelParameterized runner, instead annotate your class with `@ParallelFriendly` 6. Move bucket cleanup utility from BucketFixture to new class BucketCleaner * test: add annotations for new Integration tests runners * test: add new Registry subsystem for new Integration Runners * test: add new Integration Runners * chore: add toString to ChecksummedTestContent * test: migrate ITReadMaskTest to use new StorageITParamRunner Split enclosed classes into their own respective classes ITBlobReadMaskTest and ITBucketReadMaskTest * test: migrate ITGrpcTest to use new StorageITRunner * test: migrate ITHmacTest to use new StorageITRunner * test: migrate ITNotificationTest to use new StorageITRunner * test: migrate ITKmsTest to use new StorageITRunner * chore: remove legacy junit fixtures and runner * test: migrate ITStorageLifecycleTest to use new StorageITRunner * test: migrate ITRetryConformanceTest to use new StorageITParamRunner Refactor RetryTestFixture to extend TestWatcher to allow for manual registration * test: migrate ITBatchTest to use new StorageITRunner * test: migrate ITServiceAccountTest to use new StorageITRunner * test: migrate ITSignedUrlTest to use new StorageITRunner * test: migrate ITOptionRegressionTest to use new StorageITRunner * test: migrate ITWriteChannelConnectionPoolTest to use new StorageITRunner * test: migrate ITDownloadBlobWithoutAuth to use new StorageITRunner * test: migrate ITDownloadToTest to use new StorageITRunner * test: migrate ITBlobReadChannelTest to use new StorageITRunner * test: migrate ITBlobWriteChannelTest to use new StorageITRunner * test: migrate ITObjectChecksumSupportTest to use new StorageITParamRunner * test: migrate ITObjectTest to use new StorageITRunner * test: migrate ITBucketTest to use new StorageITRunner * test: migrate ITBucketLifecycleTest to use new StorageITRunner * test: migrate ITBucketLifecycleRulesTest to use new StorageITRunner * test: migrate ITAccessTest to use new StorageITRunner * chore: consolidate StorageITParamRunner and StorageSuite into StorageITRunner
1 parent a338103 commit 4aa5355

File tree

66 files changed

+4246
-2986
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+4246
-2986
lines changed

google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcConversions.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -500,19 +500,18 @@ private Acl bucketAclDecode(com.google.storage.v2.BucketAccessControl from) {
500500
}
501501

502502
private com.google.storage.v2.BucketAccessControl bucketAclEncode(Acl from) {
503-
BucketAccessControl.Builder to =
504-
BucketAccessControl.newBuilder()
505-
.setEntity(from.getEntity().toString())
506-
.setRole(from.getRole().toString())
507-
.setId(from.getId());
503+
BucketAccessControl.Builder to = BucketAccessControl.newBuilder();
504+
ifNonNull(from.getEntity(), entityCodec::encode, to::setEntity);
505+
ifNonNull(from.getRole(), Role::toString, to::setRole);
506+
ifNonNull(from.getId(), to::setId);
508507
ifNonNull(from.getEtag(), to::setEtag);
509508
return to.build();
510509
}
511510

512511
private Bucket.IamConfig.UniformBucketLevelAccess ublaEncode(BucketInfo.IamConfiguration from) {
513512
Bucket.IamConfig.UniformBucketLevelAccess.Builder to =
514513
Bucket.IamConfig.UniformBucketLevelAccess.newBuilder();
515-
to.setEnabled(from.isUniformBucketLevelAccessEnabled());
514+
ifNonNull(from.isUniformBucketLevelAccessEnabled(), to::setEnabled);
516515
if (from.isUniformBucketLevelAccessEnabled() == Boolean.TRUE) {
517516
ifNonNull(
518517
from.getUniformBucketLevelAccessLockedTimeOffsetDateTime(),

google-cloud-storage/src/main/java/com/google/cloud/storage/TransportCompatibility.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
3434
@Documented
3535
@Inherited
36-
@interface TransportCompatibility {
36+
public @interface TransportCompatibility {
3737

3838
Transport[] value();
3939

google-cloud-storage/src/test/java/com/google/cloud/storage/BucketFixture.java

Lines changed: 0 additions & 178 deletions
This file was deleted.

google-cloud-storage/src/test/java/com/google/cloud/storage/GzipReadableByteChannelTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,8 @@ public void readObject(
185185
() -> StorageClient.create(fakeServer.getInstance().storageSettings()));
186186

187187
@ClassRule(order = 3)
188-
public static final StorageFixture storageFixture =
189-
StorageFixture.of(() -> fakeServer.getInstance().getGrpcStorageOptions().getService());
188+
public static final AutoClosableFixture<Storage> storageFixture =
189+
AutoClosableFixture.of(() -> fakeServer.getInstance().getGrpcStorageOptions().getService());
190190

191191
@Test
192192
public void autoGzipDecompress_true() throws IOException {

google-cloud-storage/src/test/java/com/google/cloud/storage/ITStorageLifecycleTest.java

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@
2020

2121
import com.google.cloud.NoCredentials;
2222
import com.google.cloud.storage.conformance.retry.TestBench;
23-
import java.util.List;
23+
import com.google.cloud.storage.it.runner.StorageITRunner;
24+
import com.google.cloud.storage.it.runner.annotations.Backend;
25+
import com.google.cloud.storage.it.runner.annotations.Inject;
26+
import com.google.cloud.storage.it.runner.annotations.SingleBackend;
2427
import java.util.stream.Collectors;
2528
import java.util.stream.StreamSupport;
26-
import org.junit.ClassRule;
2729
import org.junit.Test;
30+
import org.junit.runner.RunWith;
2831

2932
/**
3033
* The interaction of {@link com.google.cloud.ServiceOptions} instance caching has differing
@@ -34,16 +37,17 @@
3437
* <p>Define some tests to ensue we are correctly integrating with the caching lifecycle
3538
*/
3639
// Not in com.google.cloud.storage.it because we're testing package local things
40+
@SuppressWarnings("ResultOfMethodCallIgnored")
41+
@RunWith(StorageITRunner.class)
42+
@SingleBackend(Backend.PROD)
3743
public final class ITStorageLifecycleTest {
38-
@ClassRule(order = 1)
39-
public static final TestBench TEST_BENCH =
40-
TestBench.newBuilder().setContainerName("lifecycle-test").build();
44+
@Inject public TestBench testBench;
4145

4246
@Test
4347
public void grpc() throws Exception {
4448
GrpcStorageOptions options =
4549
StorageOptions.grpc()
46-
.setHost(TEST_BENCH.getGRPCBaseUri())
50+
.setHost(testBench.getGRPCBaseUri())
4751
.setCredentials(NoCredentials.getInstance())
4852
.setProjectId("test-project-id")
4953
.build();
@@ -54,15 +58,9 @@ public void grpc() throws Exception {
5458
// ensure both instances are the same
5559
assertThat(service2).isSameInstanceAs(service1);
5660

57-
// make sure and RPCs can be done
58-
List<Bucket> buckets1 =
59-
StreamSupport.stream(service1.list().iterateAll().spliterator(), false)
60-
.collect(Collectors.toList());
61-
assertThat(buckets1).isEmpty();
62-
List<Bucket> buckets2 =
63-
StreamSupport.stream(service2.list().iterateAll().spliterator(), false)
64-
.collect(Collectors.toList());
65-
assertThat(buckets2).isEmpty();
61+
// make sure an RPC can be done
62+
StreamSupport.stream(service1.list().iterateAll().spliterator(), false)
63+
.collect(Collectors.toList());
6664

6765
// close the instance
6866
service1.close();
@@ -71,18 +69,16 @@ public void grpc() throws Exception {
7169
Storage service3 = options.getService();
7270

7371
assertThat(service3).isNotSameInstanceAs(service1);
74-
// make sure and RPCs can be done
75-
List<Bucket> buckets3 =
76-
StreamSupport.stream(service3.list().iterateAll().spliterator(), false)
77-
.collect(Collectors.toList());
78-
assertThat(buckets3).isEmpty();
72+
// make sure an RPC can be done
73+
StreamSupport.stream(service3.list().iterateAll().spliterator(), false)
74+
.collect(Collectors.toList());
7975
}
8076

8177
@Test
8278
public void http() throws Exception {
8379
HttpStorageOptions options =
8480
StorageOptions.http()
85-
.setHost(TEST_BENCH.getBaseUri())
81+
.setHost(testBench.getBaseUri())
8682
.setCredentials(NoCredentials.getInstance())
8783
.setProjectId("test-project-id")
8884
.build();
@@ -92,26 +88,18 @@ public void http() throws Exception {
9288

9389
// ensure both instances are the same
9490
assertThat(service2).isSameInstanceAs(service1);
95-
// make sure and RPCs can be done
96-
List<Bucket> buckets1 =
97-
StreamSupport.stream(service1.list().iterateAll().spliterator(), false)
98-
.collect(Collectors.toList());
99-
assertThat(buckets1).isEmpty();
100-
List<Bucket> buckets2 =
101-
StreamSupport.stream(service2.list().iterateAll().spliterator(), false)
102-
.collect(Collectors.toList());
103-
assertThat(buckets2).isEmpty();
91+
// make sure an RPC can be done
92+
StreamSupport.stream(service1.list().iterateAll().spliterator(), false)
93+
.collect(Collectors.toList());
10494

10595
service1.close(); // this should be a no-op for http
10696

10797
// expect the original instance to still be returned
10898
Storage service3 = options.getService();
10999

110100
assertThat(service3).isSameInstanceAs(service1);
111-
// make sure and RPCs can be done
112-
List<Bucket> buckets3 =
113-
StreamSupport.stream(service3.list().iterateAll().spliterator(), false)
114-
.collect(Collectors.toList());
115-
assertThat(buckets3).isEmpty();
101+
// make sure an RPC can be done
102+
StreamSupport.stream(service3.list().iterateAll().spliterator(), false)
103+
.collect(Collectors.toList());
116104
}
117105
}

0 commit comments

Comments
 (0)