Skip to content

Commit 8720f05

Browse files
authored
test: enable S.7 retry conformance tests (#1839)
Update method mappings to properly exclude retry conformance tests for Bucket#create. Update TestRetryConformance to lazily allocate and fill a temporary file when necessary.
1 parent c0e77f8 commit 8720f05

File tree

5 files changed

+80
-60
lines changed

5 files changed

+80
-60
lines changed

google-cloud-storage/src/test/java/com/google/cloud/storage/conformance/retry/ITRetryConformanceTest.java

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,16 @@
3030
import com.google.cloud.conformance.storage.v1.RetryTests;
3131
import com.google.cloud.storage.CIUtils;
3232
import com.google.cloud.storage.Storage;
33-
import com.google.cloud.storage.TransportCompatibility.Transport;
3433
import com.google.cloud.storage.conformance.retry.Functions.CtxFunction;
3534
import com.google.cloud.storage.conformance.retry.ITRetryConformanceTest.RetryConformanceParameterProvider;
3635
import com.google.cloud.storage.it.runner.StorageITRunner;
3736
import com.google.cloud.storage.it.runner.annotations.Backend;
38-
import com.google.cloud.storage.it.runner.annotations.CrossRun;
3937
import com.google.cloud.storage.it.runner.annotations.Inject;
4038
import com.google.cloud.storage.it.runner.annotations.ParallelFriendly;
4139
import com.google.cloud.storage.it.runner.annotations.Parameterized;
4240
import com.google.cloud.storage.it.runner.annotations.Parameterized.Parameter;
4341
import com.google.cloud.storage.it.runner.annotations.Parameterized.ParametersProvider;
42+
import com.google.cloud.storage.it.runner.annotations.SingleBackend;
4443
import com.google.cloud.storage.it.runner.registry.TestBench;
4544
import com.google.common.base.Charsets;
4645
import com.google.common.base.Joiner;
@@ -78,7 +77,8 @@
7877
* RpcMethodMappings}.
7978
*/
8079
@RunWith(StorageITRunner.class)
81-
@CrossRun(transports = Transport.HTTP, backends = Backend.TEST_BENCH)
80+
// @CrossRun(transports = Transport.HTTP, backends = Backend.TEST_BENCH)
81+
@SingleBackend(Backend.TEST_BENCH)
8282
@Parameterized(RetryConformanceParameterProvider.class)
8383
@ParallelFriendly
8484
public class ITRetryConformanceTest {
@@ -127,11 +127,17 @@ public void tearDown() throws Throwable {
127127
@Test
128128
public void test() throws Throwable {
129129
LOGGER.fine("Running test...");
130-
ctx =
131-
getReplaceStorageInObjectsFromCtx()
132-
.andThen(mapping.getTest())
133-
.apply(ctx, testRetryConformance)
134-
.leftMap(s -> nonTestStorage);
130+
try {
131+
ctx =
132+
getReplaceStorageInObjectsFromCtx()
133+
.andThen(mapping.getTest())
134+
.apply(ctx, testRetryConformance)
135+
.leftMap(s -> nonTestStorage);
136+
retryTestFixture.succeeded(null);
137+
} catch (Throwable e) {
138+
retryTestFixture.failed(e, null);
139+
throw e;
140+
}
135141
LOGGER.fine("Running test complete");
136142
}
137143

@@ -154,14 +160,7 @@ public ImmutableList<?> parameters() {
154160
.setMappings(new RpcMethodMappings())
155161
.setProjectId("conformance-tests")
156162
.setHost(testBench.getBaseUri().replaceAll("https?://", ""))
157-
.setTestAllowFilter(
158-
RetryTestCaseResolver.includeAll()
159-
// .and(RetryTestCaseResolver.specificMappings(44, 45))
160-
.and(
161-
(m, trc) ->
162-
trc.getScenarioId()
163-
!= 7) // Temporarily exclude resumable upload scenarios
164-
)
163+
.setTestAllowFilter(RetryTestCaseResolver.includeAll())
165164
.build();
166165

167166
List<RetryTestCase> retryTestCases;
@@ -384,6 +383,15 @@ static BiPredicate<RpcMethod, TestRetryConformance> specificMappings(int... mapp
384383
return (m, c) -> set.contains(c.getMappingId());
385384
}
386385

386+
static BiPredicate<RpcMethod, TestRetryConformance> instructionsAre(String... instructions) {
387+
return (m, trc) ->
388+
trc.getInstruction().getInstructionsList().equals(ImmutableList.copyOf(instructions));
389+
}
390+
391+
static BiPredicate<RpcMethod, TestRetryConformance> scenarioIdIs(int scenarioId) {
392+
return (m, trc) -> trc.getScenarioId() == scenarioId;
393+
}
394+
387395
static final class Builder {
388396
private String retryTestsJsonResourcePath;
389397
private RpcMethodMappings mappings;

google-cloud-storage/src/test/java/com/google/cloud/storage/conformance/retry/RetryTestFixture.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ protected void succeeded(Description description) {
120120
testSuccess = true;
121121
}
122122

123+
@Override
124+
protected void failed(Throwable e, Description description) {
125+
super.failed(e, description);
126+
}
127+
123128
@Override
124129
protected void skipped(AssumptionViolatedException e, Description description) {
125130
testSkipped = true;

google-cloud-storage/src/test/java/com/google/cloud/storage/conformance/retry/RpcMethodMappings.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,7 +1780,8 @@ private static void insert(ArrayList<RpcMethodMapping> a) {
17801780
.build());
17811781
a.add(
17821782
RpcMethodMapping.newBuilder(118, objects.insert)
1783-
.withApplicable(TestRetryConformance::isPreconditionsProvided)
1783+
.withApplicable(
1784+
and(TestRetryConformance::isPreconditionsProvided, not(groupIsResumableUpload)))
17841785
.withTest(
17851786
(ctx, c) ->
17861787
ctx.map(
@@ -1795,7 +1796,8 @@ private static void insert(ArrayList<RpcMethodMapping> a) {
17951796
.build());
17961797
a.add(
17971798
RpcMethodMapping.newBuilder(119, objects.insert)
1798-
.withApplicable(TestRetryConformance::isPreconditionsProvided)
1799+
.withApplicable(
1800+
and(TestRetryConformance::isPreconditionsProvided, not(groupIsResumableUpload)))
17991801
.withTest(
18001802
(ctx, c) ->
18011803
ctx.map(
@@ -1806,7 +1808,7 @@ private static void insert(ArrayList<RpcMethodMapping> a) {
18061808
.create(
18071809
c.getObjectName(),
18081810
c.getHelloWorldUtf8Bytes(),
1809-
"text/plain);charset=utf-8",
1811+
"text/plain;charset=utf-8",
18101812
Bucket.BlobTargetOption.doesNotExist()))))
18111813
.build());
18121814
a.add(

google-cloud-storage/src/test/java/com/google/cloud/storage/conformance/retry/TestRetryConformance.java

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,33 @@
1616

1717
package com.google.cloud.storage.conformance.retry;
1818

19+
import static com.google.common.truth.Truth.assertThat;
1920
import static java.util.Objects.requireNonNull;
2021
import static org.junit.Assert.assertNotNull;
2122

2223
import com.google.auth.ServiceAccountSigner;
2324
import com.google.auth.oauth2.ServiceAccountCredentials;
2425
import com.google.cloud.conformance.storage.v1.InstructionList;
2526
import com.google.cloud.conformance.storage.v1.Method;
27+
import com.google.cloud.storage.DataGenerator;
2628
import com.google.common.base.Joiner;
2729
import com.google.common.base.Suppliers;
30+
import com.google.common.io.ByteStreams;
2831
import com.google.errorprone.annotations.Immutable;
32+
import java.io.ByteArrayInputStream;
33+
import java.io.File;
34+
import java.io.FileOutputStream;
2935
import java.io.IOException;
3036
import java.io.InputStream;
31-
import java.net.URISyntaxException;
32-
import java.net.URL;
3337
import java.nio.charset.StandardCharsets;
3438
import java.nio.file.Path;
35-
import java.nio.file.Paths;
3639
import java.time.Clock;
3740
import java.time.Instant;
3841
import java.time.ZoneId;
3942
import java.time.ZoneOffset;
4043
import java.time.format.DateTimeFormatter;
4144
import java.util.function.Supplier;
4245
import java.util.stream.Collectors;
43-
import java.util.stream.IntStream;
4446

4547
/**
4648
* An individual resolved test case correlating config from {@link
@@ -72,9 +74,8 @@ final class TestRetryConformance {
7274
private final String topicName;
7375

7476
private final Supplier<byte[]> lazyHelloWorldUtf8Bytes;
75-
private final Path helloWorldFilePath = resolvePathForResource();
76-
private final ServiceAccountCredentials serviceAccountCredentials =
77-
resolveServiceAccountCredentials();
77+
private final Supplier<Path> helloWorldFilePath;
78+
private final ServiceAccountCredentials serviceAccountCredentials;
7879

7980
private final String host;
8081

@@ -137,33 +138,14 @@ final class TestRetryConformance {
137138
String.format(
138139
"%s_s%03d-%s-m%03d_top1",
139140
BASE_ID, scenarioId, instructionsString.toLowerCase(), mappingId);
140-
lazyHelloWorldUtf8Bytes =
141+
this.lazyHelloWorldUtf8Bytes =
141142
Suppliers.memoize(
142143
() -> {
143144
// define a lazy supplier for bytes.
144-
// Not all tests need data for an object, though some tests - resumable upload - needs
145-
// more than 8MiB.
146-
// We want to avoid allocating 8.1MiB for each test unnecessarily, especially since we
147-
// instantiate all permuted test cases. ~1000 * 8.1MiB ~~ > 8GiB.
148-
String helloWorld = "Hello, World!";
149-
int baseDataSize;
150-
switch (method.getName()) {
151-
case "storage.objects.insert":
152-
baseDataSize = _8MiB + 1;
153-
break;
154-
case "storage.objects.get":
155-
baseDataSize = _512KiB;
156-
break;
157-
default:
158-
baseDataSize = helloWorld.length();
159-
break;
160-
}
161-
int endInclusive = (baseDataSize / helloWorld.length());
162-
return IntStream.rangeClosed(1, endInclusive)
163-
.mapToObj(i -> helloWorld)
164-
.collect(Collectors.joining())
165-
.getBytes(StandardCharsets.UTF_8);
145+
return genBytes(method);
166146
});
147+
this.helloWorldFilePath = resolvePathForResource(objectName, method);
148+
this.serviceAccountCredentials = resolveServiceAccountCredentials();
167149
}
168150

169151
public String getProjectId() {
@@ -195,7 +177,7 @@ public byte[] getHelloWorldUtf8Bytes() {
195177
}
196178

197179
public Path getHelloWorldFilePath() {
198-
return helloWorldFilePath;
180+
return helloWorldFilePath.get();
199181
}
200182

201183
public int getScenarioId() {
@@ -238,15 +220,24 @@ public String toString() {
238220
return getTestName();
239221
}
240222

241-
private static Path resolvePathForResource() {
242-
ClassLoader cl = Thread.currentThread().getContextClassLoader();
243-
URL url = cl.getResource("com/google/cloud/storage/conformance/retry/hello-world.txt");
244-
assertNotNull(url);
245-
try {
246-
return Paths.get(url.toURI());
247-
} catch (URISyntaxException e) {
248-
throw new RuntimeException(e);
249-
}
223+
private static Supplier<Path> resolvePathForResource(String objectName, Method method) {
224+
return () -> {
225+
try {
226+
File tempFile = File.createTempFile(objectName, "");
227+
tempFile.deleteOnExit();
228+
229+
byte[] bytes = genBytes(method);
230+
try (ByteArrayInputStream in = new ByteArrayInputStream(bytes);
231+
FileOutputStream out = new FileOutputStream(tempFile)) {
232+
long copy = ByteStreams.copy(in, out);
233+
assertThat(copy).isEqualTo(bytes.length);
234+
}
235+
236+
return tempFile.toPath();
237+
} catch (IOException e) {
238+
throw new RuntimeException(e);
239+
}
240+
};
250241
}
251242

252243
private static ServiceAccountCredentials resolveServiceAccountCredentials() {
@@ -265,4 +256,19 @@ private static ServiceAccountCredentials resolveServiceAccountCredentials() {
265256
public String getTopicName() {
266257
return topicName;
267258
}
259+
260+
private static byte[] genBytes(Method method) {
261+
// Not all tests need data for an object, though some tests - resumable upload - needs
262+
// more than 8MiB.
263+
// We want to avoid allocating 8.1MiB for each test unnecessarily, especially since we
264+
// instantiate all permuted test cases. ~1000 * 8.1MiB ~~ > 8GiB.
265+
switch (method.getName()) {
266+
case "storage.objects.insert":
267+
return DataGenerator.base64Characters().genBytes(_8MiB * 2 + _512KiB);
268+
case "storage.objects.get":
269+
return DataGenerator.base64Characters().genBytes(_512KiB);
270+
default:
271+
return "Hello, World!".getBytes(StandardCharsets.UTF_8);
272+
}
273+
}
268274
}

google-cloud-storage/src/test/resources/com/google/cloud/storage/conformance/retry/hello-world.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)