Skip to content

Commit 79384ac

Browse files
committed
test(showcase): add integration tests for resumable upload
1 parent 0cfb2a7 commit 79384ac

2 files changed

Lines changed: 232 additions & 0 deletions

File tree

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.showcase.v1beta1.it;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
21+
import com.google.api.gax.rpc.ResumableUploadCallSettings;
22+
import com.google.api.gax.rpc.ResumableUploadFuture;
23+
import com.google.showcase.v1beta1.ResumableUploadServiceClient;
24+
import com.google.showcase.v1beta1.ResumableUploadServiceSettings;
25+
import com.google.showcase.v1beta1.UploadMediaRequest;
26+
import com.google.showcase.v1beta1.UploadMediaResponse;
27+
import com.google.showcase.v1beta1.it.util.TestClientInitializer;
28+
import java.io.ByteArrayInputStream;
29+
import java.io.IOException;
30+
import java.io.InputStream;
31+
import java.nio.charset.StandardCharsets;
32+
import java.nio.file.Files;
33+
import java.nio.file.Path;
34+
import java.util.concurrent.TimeUnit;
35+
import org.junit.jupiter.api.AfterAll;
36+
import org.junit.jupiter.api.BeforeAll;
37+
import org.junit.jupiter.api.Test;
38+
import org.junit.jupiter.api.io.TempDir;
39+
40+
/**
41+
* Integration tests for generated {@link ResumableUploadServiceClient} against the Showcase server.
42+
*/
43+
class ITResumableUpload {
44+
45+
private static final int SHOWCASE_CHUNK_SIZE = 256 * 1024; // 256KB
46+
private static ResumableUploadServiceClient client;
47+
48+
@BeforeAll
49+
static void createClients() throws Exception {
50+
client = TestClientInitializer.createHttpJsonResumableUploadClient(SHOWCASE_CHUNK_SIZE);
51+
}
52+
53+
@AfterAll
54+
static void destroyClients() throws InterruptedException {
55+
if (client != null) {
56+
client.close();
57+
client.awaitTermination(TestClientInitializer.AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS);
58+
}
59+
}
60+
61+
@Test
62+
void testGeneratedClient_uploadMedia_synchronousConvenienceMethod(@TempDir Path tempDir)
63+
throws Exception {
64+
Path file =
65+
createTempFile(
66+
tempDir,
67+
"it-client-sync.txt",
68+
"Hello from generated ResumableUploadServiceClient synchronous convenience method!"
69+
.getBytes(StandardCharsets.UTF_8));
70+
UploadMediaRequest request =
71+
UploadMediaRequest.newBuilder().setName("it-client-sync.txt").build();
72+
73+
try (InputStream stream = Files.newInputStream(file)) {
74+
UploadMediaResponse response = client.uploadMedia(request, stream);
75+
assertThat(response.getName()).isEqualTo("it-client-sync.txt");
76+
assertThat(response.getSize()).isEqualTo(Files.size(file));
77+
}
78+
}
79+
80+
@Test
81+
void testGeneratedClient_uploadMediaCallable_asynchronousFutureCall(@TempDir Path tempDir)
82+
throws Exception {
83+
Path file =
84+
createTempFile(
85+
tempDir,
86+
"it-client-callable.txt",
87+
"Hello from generated ResumableUploadServiceClient callable futureCall!"
88+
.getBytes(StandardCharsets.UTF_8));
89+
UploadMediaRequest request =
90+
UploadMediaRequest.newBuilder().setName("it-client-callable.txt").build();
91+
92+
try (InputStream stream = Files.newInputStream(file)) {
93+
ResumableUploadFuture<UploadMediaResponse> future =
94+
client
95+
.uploadMediaCallable()
96+
.futureCall(request, stream, (ResumableUploadCallSettings) null);
97+
98+
UploadMediaResponse response = future.get(10, TimeUnit.SECONDS);
99+
assertThat(future.isDone()).isTrue();
100+
assertThat(future.isCancelled()).isFalse();
101+
assertThat(future.getUploadSessionUrl()).isNotNull();
102+
assertThat(future.getUploadSessionUrl()).contains("/resumable/upload");
103+
assertThat(response.getName()).isEqualTo("it-client-callable.txt");
104+
assertThat(response.getSize()).isEqualTo(Files.size(file));
105+
}
106+
}
107+
108+
@Test
109+
void testGeneratedClient_multiChunkUpload(@TempDir Path tempDir) throws Exception {
110+
// 600KB payload = 2 full 256KB chunks + 1 partial 88KB chunk
111+
int totalBytes = 600 * 1024;
112+
Path file = createTempFile(tempDir, "it-client-multi-chunk.txt", totalBytes);
113+
UploadMediaRequest request =
114+
UploadMediaRequest.newBuilder().setName("it-client-multi-chunk.txt").build();
115+
116+
try (InputStream stream = Files.newInputStream(file)) {
117+
UploadMediaResponse response = client.uploadMedia(request, stream);
118+
assertThat(response.getName()).isEqualTo("it-client-multi-chunk.txt");
119+
assertThat(response.getSize()).isEqualTo(Files.size(file));
120+
}
121+
}
122+
123+
@Test
124+
void testGeneratedClient_zeroByteUpload() throws Exception {
125+
UploadMediaRequest request =
126+
UploadMediaRequest.newBuilder().setName("it-client-zero-byte.txt").build();
127+
128+
try (InputStream stream = new ByteArrayInputStream(new byte[0])) {
129+
UploadMediaResponse response = client.uploadMedia(request, stream);
130+
assertThat(response.getName()).isEqualTo("it-client-zero-byte.txt");
131+
assertThat(response.getSize()).isEqualTo(0);
132+
}
133+
}
134+
135+
@Test
136+
void testGeneratedClient_exactChunkBoundaryUpload(@TempDir Path tempDir) throws Exception {
137+
// Exactly 2 full 256KB chunks (512KB total) -> triggers 0-byte finalize request
138+
int totalBytes = 512 * 1024;
139+
Path file = createTempFile(tempDir, "it-client-exact-chunks.txt", totalBytes);
140+
UploadMediaRequest request =
141+
UploadMediaRequest.newBuilder().setName("it-client-exact-chunks.txt").build();
142+
143+
try (InputStream stream = Files.newInputStream(file)) {
144+
UploadMediaResponse response = client.uploadMedia(request, stream);
145+
assertThat(response.getName()).isEqualTo("it-client-exact-chunks.txt");
146+
assertThat(response.getSize()).isEqualTo(Files.size(file));
147+
}
148+
}
149+
150+
@Test
151+
void testGeneratedClient_grpcClientDelegation_uploadMedia(@TempDir Path tempDir)
152+
throws Exception {
153+
Path file =
154+
createTempFile(
155+
tempDir,
156+
"it-grpc-delegation.txt",
157+
"Hello from generated ResumableUploadServiceClient gRPC delegation!"
158+
.getBytes(StandardCharsets.UTF_8));
159+
UploadMediaRequest request =
160+
UploadMediaRequest.newBuilder().setName("it-grpc-delegation.txt").build();
161+
162+
try (ResumableUploadServiceClient grpcClient =
163+
TestClientInitializer.createGrpcResumableUploadClient(SHOWCASE_CHUNK_SIZE)) {
164+
try (InputStream stream = Files.newInputStream(file)) {
165+
UploadMediaResponse response = grpcClient.uploadMedia(request, stream);
166+
assertThat(response.getName()).isEqualTo("it-grpc-delegation.txt");
167+
assertThat(response.getSize()).isEqualTo(Files.size(file));
168+
}
169+
170+
try (InputStream stream = Files.newInputStream(file)) {
171+
ResumableUploadFuture<UploadMediaResponse> future =
172+
grpcClient
173+
.uploadMediaCallable()
174+
.futureCall(request, stream, (ResumableUploadCallSettings) null);
175+
UploadMediaResponse response = future.get(10, TimeUnit.SECONDS);
176+
assertThat(future.isDone()).isTrue();
177+
assertThat(future.isCancelled()).isFalse();
178+
assertThat(future.getUploadSessionUrl()).isNotNull();
179+
assertThat(future.getUploadSessionUrl()).contains("/resumable/upload");
180+
assertThat(response.getName()).isEqualTo("it-grpc-delegation.txt");
181+
assertThat(response.getSize()).isEqualTo(Files.size(file));
182+
}
183+
}
184+
}
185+
186+
187+
private static Path createTempFile(Path dir, String fileName, byte[] data) throws IOException {
188+
Path path = dir.resolve(fileName);
189+
Files.write(path, data);
190+
return path;
191+
}
192+
193+
private static Path createTempFile(Path dir, String fileName, int size) throws IOException {
194+
byte[] data = new byte[size];
195+
for (int i = 0; i < size; i++) {
196+
data[i] = (byte) (i % 256);
197+
}
198+
return createTempFile(dir, fileName, data);
199+
}
200+
}

java-showcase/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/util/TestClientInitializer.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import com.google.showcase.v1beta1.EchoSettings;
3434
import com.google.showcase.v1beta1.IdentityClient;
3535
import com.google.showcase.v1beta1.IdentitySettings;
36+
import com.google.showcase.v1beta1.ResumableUploadServiceClient;
37+
import com.google.showcase.v1beta1.ResumableUploadServiceSettings;
3638
import com.google.showcase.v1beta1.SequenceServiceClient;
3739
import com.google.showcase.v1beta1.SequenceServiceSettings;
3840
import com.google.showcase.v1beta1.WaitRequest;
@@ -539,4 +541,34 @@ public static SequenceServiceClient createHttpJsonSequenceClientWithRetrySetting
539541
.build());
540542
return SequenceServiceClient.create(settingsBuilder.build());
541543
}
544+
545+
public static ResumableUploadServiceClient createHttpJsonResumableUploadClient(int chunkSize)
546+
throws Exception {
547+
ResumableUploadServiceSettings.Builder settingsBuilder =
548+
ResumableUploadServiceSettings.newHttpJsonBuilder();
549+
settingsBuilder
550+
.setCredentialsProvider(NoCredentialsProvider.create())
551+
.setTransportChannelProvider(
552+
ResumableUploadServiceSettings.defaultHttpJsonTransportProviderBuilder()
553+
.setHttpTransport(new NetHttpTransport.Builder().doNotValidateCertificate().build())
554+
.setEndpoint(DEFAULT_HTTPJSON_ENDPOINT)
555+
.build());
556+
settingsBuilder.uploadMediaSettings().setChunkSize(chunkSize);
557+
return ResumableUploadServiceClient.create(settingsBuilder.build());
558+
}
559+
560+
public static ResumableUploadServiceClient createGrpcResumableUploadClient(int chunkSize)
561+
throws Exception {
562+
ResumableUploadServiceSettings.Builder settingsBuilder =
563+
ResumableUploadServiceSettings.newBuilder()
564+
.setCredentialsProvider(NoCredentialsProvider.create())
565+
.setTransportChannelProvider(
566+
ResumableUploadServiceSettings.defaultGrpcTransportProviderBuilder()
567+
.setEndpoint(DEFAULT_GRPC_ENDPOINT)
568+
.setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
569+
.build())
570+
.setEndpoint(DEFAULT_HTTPJSON_ENDPOINT);
571+
settingsBuilder.uploadMediaSettings().setChunkSize(chunkSize);
572+
return ResumableUploadServiceClient.create(settingsBuilder.build());
573+
}
542574
}

0 commit comments

Comments
 (0)