Skip to content

Commit f4cbede

Browse files
committed
feat(storage): Parameterized test setup for RCU Integration Testing
1 parent 84b2069 commit f4cbede

11 files changed

Lines changed: 539 additions & 64 deletions

File tree

java-storage/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,26 @@ public HttpStorageRpc(StorageOptions options, JsonFactory jsonFactory) {
158158
initializer = censusHttpModule.getHttpRequestInitializer(initializer);
159159
initializer = new InvocationIdInitializer(initializer, applicationName, tm);
160160
batchRequestInitializer = censusHttpModule.getHttpRequestInitializer(null);
161-
storage =
161+
String host = options.getHost();
162+
Storage.Builder storageBuilder =
162163
new Storage.Builder(transport, jsonFactory, initializer)
163-
.setRootUrl(options.getHost())
164-
.setApplicationName(applicationName)
165-
.build();
164+
.setApplicationName(applicationName);
165+
if (host != null) {
166+
java.net.URI uri = java.net.URI.create(host);
167+
String path = uri.getPath();
168+
if (path != null && !path.isEmpty() && !"/".equals(path)) {
169+
String rootUrl = host.substring(0, host.indexOf(path));
170+
String servicePath = path.startsWith("/") ? path.substring(1) : path;
171+
if (!servicePath.endsWith("/")) {
172+
servicePath += "/";
173+
}
174+
storageBuilder.setRootUrl(rootUrl);
175+
storageBuilder.setServicePath(servicePath);
176+
} else {
177+
storageBuilder.setRootUrl(host);
178+
}
179+
}
180+
storage = storageBuilder.build();
166181
}
167182

168183
public Storage getStorage() {

java-storage/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/CrossRunIntersection.java

Lines changed: 134 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020

2121
import com.google.cloud.storage.TransportCompatibility.Transport;
2222
import com.google.cloud.storage.it.runner.annotations.Backend;
23+
import com.google.cloud.storage.it.runner.annotations.Colocation;
2324
import com.google.cloud.storage.it.runner.annotations.CrossRun;
25+
import com.google.cloud.storage.it.runner.annotations.LocationType;
2426
import com.google.common.base.MoreObjects;
2527
import com.google.common.collect.ImmutableSet;
28+
import java.util.Collections;
2629
import java.util.Locale;
30+
import java.util.Set;
2731
import java.util.Objects;
2832
import javax.annotation.concurrent.Immutable;
2933
import javax.annotation.concurrent.ThreadSafe;
@@ -39,10 +43,18 @@ public final class CrossRunIntersection {
3943

4044
private final @Nullable Backend backend;
4145
private final @Nullable Transport transport;
46+
private final @Nullable LocationType locationType;
47+
private final @Nullable Colocation colocation;
4248

43-
private CrossRunIntersection(@Nullable Backend backend, @Nullable Transport transport) {
49+
private CrossRunIntersection(
50+
@Nullable Backend backend,
51+
@Nullable Transport transport,
52+
@Nullable LocationType locationType,
53+
@Nullable Colocation colocation) {
4454
this.backend = backend;
4555
this.transport = transport;
56+
this.locationType = locationType;
57+
this.colocation = colocation;
4658
}
4759

4860
@Nullable
@@ -55,19 +67,45 @@ public Transport getTransport() {
5567
return transport;
5668
}
5769

70+
@Nullable
71+
public LocationType getLocationType() {
72+
return locationType;
73+
}
74+
75+
@Nullable
76+
public Colocation getColocation() {
77+
return colocation;
78+
}
79+
5880
public CrossRunIntersection clearBackend() {
5981
if (backend == null) {
6082
return this;
6183
} else {
62-
return new CrossRunIntersection(null, transport);
84+
return new CrossRunIntersection(null, transport, locationType, colocation);
6385
}
6486
}
6587

6688
public CrossRunIntersection clearTransport() {
6789
if (transport == null) {
6890
return this;
6991
} else {
70-
return new CrossRunIntersection(backend, null);
92+
return new CrossRunIntersection(backend, null, locationType, colocation);
93+
}
94+
}
95+
96+
public CrossRunIntersection clearLocationType() {
97+
if (locationType == null) {
98+
return this;
99+
} else {
100+
return new CrossRunIntersection(backend, transport, null, colocation);
101+
}
102+
}
103+
104+
public CrossRunIntersection clearColocation() {
105+
if (colocation == null) {
106+
return this;
107+
} else {
108+
return new CrossRunIntersection(backend, transport, locationType, null);
71109
}
72110
}
73111

@@ -76,7 +114,7 @@ public CrossRunIntersection withBackend(Backend backend) {
76114
if (this.backend == backend) {
77115
return this;
78116
} else {
79-
return new CrossRunIntersection(backend, transport);
117+
return new CrossRunIntersection(backend, transport, locationType, colocation);
80118
}
81119
}
82120

@@ -85,7 +123,25 @@ public CrossRunIntersection withTransport(Transport transport) {
85123
if (this.transport == transport) {
86124
return this;
87125
} else {
88-
return new CrossRunIntersection(backend, transport);
126+
return new CrossRunIntersection(backend, transport, locationType, colocation);
127+
}
128+
}
129+
130+
public CrossRunIntersection withLocationType(LocationType locationType) {
131+
requireNonNull(locationType, "locationType must be non null");
132+
if (this.locationType == locationType) {
133+
return this;
134+
} else {
135+
return new CrossRunIntersection(backend, transport, locationType, colocation);
136+
}
137+
}
138+
139+
public CrossRunIntersection withColocation(Colocation colocation) {
140+
requireNonNull(colocation, "colocation must be non null");
141+
if (this.colocation == colocation) {
142+
return this;
143+
} else {
144+
return new CrossRunIntersection(backend, transport, locationType, colocation);
89145
}
90146
}
91147

@@ -107,6 +163,20 @@ public boolean anyMatch(CrossRunIntersection other) {
107163
l = l.clearTransport();
108164
}
109165

166+
if (l.locationType == null) {
167+
r = r.clearLocationType();
168+
}
169+
if (r.locationType == null) {
170+
l = l.clearLocationType();
171+
}
172+
173+
if (l.colocation == null) {
174+
r = r.clearColocation();
175+
}
176+
if (r.colocation == null) {
177+
l = l.clearColocation();
178+
}
179+
110180
return l.equals(r);
111181
}
112182

@@ -119,7 +189,9 @@ public boolean anyMatch(CrossRunIntersection other) {
119189
public String fmtSuiteName() {
120190
String t = transport != null ? transport.toString() : "NULL_TRANSPORT";
121191
String b = backend != null ? backend.toString() : "NULL_BACKEND";
122-
return String.format(Locale.US, "[%s][%s]", t, b);
192+
String lt = locationType != null ? locationType.toString() : "NULL_LOCATION";
193+
String c = colocation != null ? colocation.toString() : "NULL_COLOCATION";
194+
return String.format(Locale.US, "[%s][%s][%s][%s]", t, b, lt, c);
123195
}
124196

125197
@Override
@@ -131,54 +203,90 @@ public boolean equals(Object o) {
131203
return false;
132204
}
133205
CrossRunIntersection crossRunIntersection = (CrossRunIntersection) o;
134-
return backend == crossRunIntersection.backend && transport == crossRunIntersection.transport;
206+
return backend == crossRunIntersection.backend
207+
&& transport == crossRunIntersection.transport
208+
&& locationType == crossRunIntersection.locationType
209+
&& colocation == crossRunIntersection.colocation;
135210
}
136211

137212
@Override
138213
public int hashCode() {
139-
return Objects.hash(backend, transport);
214+
return Objects.hash(backend, transport, locationType, colocation);
140215
}
141216

142217
@Override
143218
public String toString() {
144219
return MoreObjects.toStringHelper(this)
145220
.add("backend", backend)
146221
.add("transport", transport)
222+
.add("locationType", locationType)
223+
.add("colocation", colocation)
147224
.toString();
148225
}
149226

150-
public static CrossRunIntersection of(@Nullable Backend t, @Nullable Transport s) {
151-
return new CrossRunIntersection(t, s);
227+
public static CrossRunIntersection of(@Nullable Backend b, @Nullable Transport t) {
228+
return new CrossRunIntersection(b, t, null, null);
229+
}
230+
231+
public static CrossRunIntersection of(
232+
@Nullable Backend b,
233+
@Nullable Transport t,
234+
@Nullable LocationType lt,
235+
@Nullable Colocation c) {
236+
return new CrossRunIntersection(b, t, lt, c);
152237
}
153238

154239
public static ImmutableSet<CrossRunIntersection> expand(CrossRun.Ignore i) {
155240
ImmutableSet<Backend> backends = ImmutableSet.copyOf(i.backends());
156241
ImmutableSet<Transport> transports = ImmutableSet.copyOf(i.transports());
157-
return expand(backends, transports);
242+
ImmutableSet<LocationType> locations = ImmutableSet.copyOf(i.locations());
243+
ImmutableSet<Colocation> colocations = ImmutableSet.copyOf(i.colocations());
244+
return expand(backends, transports, locations, colocations);
158245
}
159246

160247
public static ImmutableSet<CrossRunIntersection> expand(CrossRun.Exclude i) {
161248
ImmutableSet<Backend> backends = ImmutableSet.copyOf(i.backends());
162249
ImmutableSet<Transport> transports = ImmutableSet.copyOf(i.transports());
163-
return expand(backends, transports);
250+
ImmutableSet<LocationType> locations = ImmutableSet.copyOf(i.locations());
251+
ImmutableSet<Colocation> colocations = ImmutableSet.copyOf(i.colocations());
252+
return expand(backends, transports, locations, colocations);
164253
}
165254

166255
public static ImmutableSet<CrossRunIntersection> expand(
167-
ImmutableSet<Backend> backends, ImmutableSet<@Nullable Transport> transports) {
168-
if (backends.isEmpty() && transports.isEmpty()) {
256+
ImmutableSet<Backend> backends,
257+
ImmutableSet<@Nullable Transport> transports,
258+
ImmutableSet<@Nullable LocationType> locations,
259+
ImmutableSet<@Nullable Colocation> colocations) {
260+
if (backends.isEmpty() && transports.isEmpty() && locations.isEmpty() && colocations.isEmpty()) {
169261
return ImmutableSet.of();
170-
} else if (!backends.isEmpty() && !transports.isEmpty()) {
171-
return backends.stream()
172-
.flatMap(t -> transports.stream().map(s -> new CrossRunIntersection(t, s)))
173-
.collect(ImmutableSet.toImmutableSet());
174-
} else if (!backends.isEmpty()) {
175-
return backends.stream()
176-
.map(t -> new CrossRunIntersection(t, null))
177-
.collect(ImmutableSet.toImmutableSet());
178-
} else {
179-
return transports.stream()
180-
.map(s -> new CrossRunIntersection(null, s))
181-
.collect(ImmutableSet.toImmutableSet());
182262
}
263+
264+
Set<@Nullable Backend> bSet =
265+
backends.isEmpty() ? Collections.singleton((Backend) null) : backends;
266+
Set<@Nullable Transport> tSet =
267+
transports.isEmpty() ? Collections.singleton((Transport) null) : transports;
268+
Set<@Nullable LocationType> lSet =
269+
locations.isEmpty() ? Collections.singleton((LocationType) null) : locations;
270+
Set<@Nullable Colocation> cSet =
271+
colocations.isEmpty() ? Collections.singleton((Colocation) null) : colocations;
272+
273+
return bSet.stream()
274+
.flatMap(
275+
b ->
276+
tSet.stream()
277+
.flatMap(
278+
t ->
279+
lSet.stream()
280+
.flatMap(
281+
l ->
282+
cSet.stream()
283+
.map(c -> new CrossRunIntersection(b, t, l, c)))))
284+
.filter(
285+
i ->
286+
!(i.backend == null
287+
&& i.transport == null
288+
&& i.locationType == null
289+
&& i.colocation == null))
290+
.collect(ImmutableSet.toImmutableSet());
183291
}
184292
}

java-storage/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/StorageITRunner.java

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import com.google.cloud.storage.it.runner.annotations.Parameterized;
2424
import com.google.cloud.storage.it.runner.annotations.Parameterized.Parameter;
2525
import com.google.cloud.storage.it.runner.annotations.Parameterized.ParametersProvider;
26+
import com.google.cloud.storage.it.runner.annotations.Colocation;
27+
import com.google.cloud.storage.it.runner.annotations.LocationType;
2628
import com.google.cloud.storage.it.runner.annotations.SingleBackend;
2729
import com.google.cloud.storage.it.runner.registry.Registry;
2830
import com.google.common.collect.ImmutableList;
@@ -166,7 +168,16 @@ private static List<Runner> computeRunners(Class<?> klass, Registry registry)
166168
.flatMap(
167169
b ->
168170
ImmutableSet.copyOf(crossRun.transports()).stream()
169-
.map(t -> CrossRunIntersection.of(b, t)))
171+
.flatMap(
172+
t ->
173+
ImmutableSet.copyOf(crossRun.locations()).stream()
174+
.flatMap(
175+
l ->
176+
ImmutableSet.copyOf(crossRun.colocations()).stream()
177+
.map(
178+
c ->
179+
CrossRunIntersection.of(
180+
b, t, l, c)))))
170181
.flatMap(
171182
c -> {
172183
TestInitializer ti = registry.newTestInitializerForCell(c);
@@ -187,23 +198,38 @@ private static List<Runner> computeRunners(Class<?> klass, Registry registry)
187198
.collect(ImmutableList.toImmutableList()));
188199
} else {
189200
Backend backend = singleBackend.value();
190-
CrossRunIntersection crossRunIntersection = CrossRunIntersection.of(backend, null);
191-
TestInitializer ti = registry.newTestInitializerForCell(crossRunIntersection);
192-
if (parameters != null) {
193-
return SneakyException.unwrap(
194-
() ->
195-
parameters.stream()
196-
.map(
197-
param ->
198-
StorageITLeafRunner.unsafeOf(
199-
testClass,
200-
crossRunIntersection,
201-
fmtParam(param),
202-
ti.andThen(setFieldTo(testClass, param))))
203-
.collect(ImmutableList.toImmutableList()));
204-
} else {
205-
return ImmutableList.of(StorageITLeafRunner.of(testClass, crossRunIntersection, null, ti));
206-
}
201+
boolean isDefault =
202+
singleBackend.locations().length == 1
203+
&& singleBackend.locations()[0] == LocationType.REGIONAL_STANDARD
204+
&& singleBackend.colocations().length == 1
205+
&& singleBackend.colocations()[0] == Colocation.CO_LOCATED;
206+
207+
return SneakyException.unwrap(
208+
() ->
209+
ImmutableSet.copyOf(singleBackend.locations()).stream()
210+
.flatMap(
211+
l ->
212+
ImmutableSet.copyOf(singleBackend.colocations()).stream()
213+
.map(c -> CrossRunIntersection.of(backend, null, l, c)))
214+
.flatMap(
215+
c -> {
216+
TestInitializer ti = registry.newTestInitializerForCell(c);
217+
if (parameters != null) {
218+
return parameters.stream()
219+
.map(
220+
param ->
221+
StorageITLeafRunner.unsafeOf(
222+
testClass,
223+
c,
224+
isDefault ? fmtParam(param) : fmtParam(c, param),
225+
ti.andThen(setFieldTo(testClass, param))));
226+
} else {
227+
return Stream.of(
228+
StorageITLeafRunner.unsafeOf(
229+
testClass, c, isDefault ? null : c.fmtSuiteName(), ti));
230+
}
231+
})
232+
.collect(ImmutableList.toImmutableList()));
207233
}
208234
}
209235

java-storage/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/annotations/Backend.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
public enum Backend {
2121
/** Use the "Production" GCS endpoints */
2222
PROD,
23+
/** Use the GCS Pre-prod (Staging) endpoints */
24+
PREPROD,
2325
/** Use the test bench as a backend */
2426
TEST_BENCH
2527
}

0 commit comments

Comments
 (0)