-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add showcase test for api-version (#2737)
This pr updates gapic-showcase version to 0.35.0 and adds showcase tests to verify behavior of api version headers being emitted (changes in #2630 and #2671).
- Loading branch information
Showing
3 changed files
with
326 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
324 changes: 324 additions & 0 deletions
324
...case/gapic-showcase/src/test/java/com/google/showcase/v1beta1/it/ITApiVersionHeaders.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,324 @@ | ||
/* | ||
* Copyright 2024 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.google.showcase.v1beta1.it; | ||
|
||
import static com.google.common.truth.Truth.assertThat; | ||
import static org.junit.Assert.assertThrows; | ||
|
||
import com.google.api.gax.httpjson.*; | ||
import com.google.api.gax.rpc.ApiClientHeaderProvider; | ||
import com.google.api.gax.rpc.FixedHeaderProvider; | ||
import com.google.api.gax.rpc.StubSettings; | ||
import com.google.common.collect.ImmutableList; | ||
import com.google.showcase.v1beta1.*; | ||
import com.google.showcase.v1beta1.it.util.TestClientInitializer; | ||
import com.google.showcase.v1beta1.stub.ComplianceStubSettings; | ||
import com.google.showcase.v1beta1.stub.EchoStubSettings; | ||
import io.grpc.*; | ||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.concurrent.TimeUnit; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
// TODO: add testing on error responses once feat is implemented in showcase. | ||
// https://github.com/googleapis/gapic-showcase/pull/1456 | ||
// TODO: watch for showcase gRPC trailer changes suggested in | ||
// https://github.com/googleapis/gapic-showcase/pull/1509#issuecomment-2089147103 | ||
public class ITApiVersionHeaders { | ||
private static final String HTTP_RESPONSE_HEADER_STRING = | ||
"x-showcase-request-" + ApiClientHeaderProvider.API_VERSION_HEADER_KEY; | ||
private static final Metadata.Key<String> API_VERSION_HEADER_KEY = | ||
Metadata.Key.of( | ||
ApiClientHeaderProvider.API_VERSION_HEADER_KEY, Metadata.ASCII_STRING_MARSHALLER); | ||
|
||
private static final String EXPECTED_ECHO_API_VERSION = "v1_20240408"; | ||
private static final String CUSTOM_API_VERSION = "user-supplied-version"; | ||
private static final String EXPECTED_EXCEPTION_MESSAGE = | ||
"Header provider can't override the header: " | ||
+ ApiClientHeaderProvider.API_VERSION_HEADER_KEY; | ||
private static final int DEFAULT_AWAIT_TERMINATION_SEC = 10; | ||
|
||
// Implement a client interceptor to retrieve the trailing metadata from response. | ||
private static class GrpcCapturingClientInterceptor implements ClientInterceptor { | ||
private Metadata metadata; | ||
|
||
@Override | ||
public <RequestT, ResponseT> ClientCall<RequestT, ResponseT> interceptCall( | ||
MethodDescriptor<RequestT, ResponseT> method, final CallOptions callOptions, Channel next) { | ||
ClientCall<RequestT, ResponseT> call = next.newCall(method, callOptions); | ||
return new ForwardingClientCall.SimpleForwardingClientCall<RequestT, ResponseT>(call) { | ||
@Override | ||
public void start(Listener<ResponseT> responseListener, Metadata headers) { | ||
Listener<ResponseT> wrappedListener = | ||
new SimpleForwardingClientCallListener<ResponseT>(responseListener) { | ||
@Override | ||
public void onClose(Status status, Metadata trailers) { | ||
if (status.isOk()) { | ||
metadata = trailers; | ||
} | ||
super.onClose(status, trailers); | ||
} | ||
}; | ||
|
||
super.start(wrappedListener, headers); | ||
} | ||
}; | ||
} | ||
} | ||
|
||
private static class SimpleForwardingClientCallListener<RespT> | ||
extends ClientCall.Listener<RespT> { | ||
private final ClientCall.Listener<RespT> delegate; | ||
|
||
SimpleForwardingClientCallListener(ClientCall.Listener<RespT> delegate) { | ||
this.delegate = delegate; | ||
} | ||
|
||
@Override | ||
public void onHeaders(Metadata headers) { | ||
delegate.onHeaders(headers); | ||
} | ||
|
||
@Override | ||
public void onMessage(RespT message) { | ||
delegate.onMessage(message); | ||
} | ||
|
||
@Override | ||
public void onClose(Status status, Metadata trailers) { | ||
delegate.onClose(status, trailers); | ||
} | ||
|
||
@Override | ||
public void onReady() { | ||
delegate.onReady(); | ||
} | ||
} | ||
// Implement a client interceptor to retrieve the response headers | ||
private static class HttpJsonCapturingClientInterceptor implements HttpJsonClientInterceptor { | ||
private HttpJsonMetadata metadata; | ||
|
||
@Override | ||
public <RequestT, ResponseT> HttpJsonClientCall<RequestT, ResponseT> interceptCall( | ||
ApiMethodDescriptor<RequestT, ResponseT> method, | ||
HttpJsonCallOptions callOptions, | ||
HttpJsonChannel next) { | ||
HttpJsonClientCall<RequestT, ResponseT> call = next.newCall(method, callOptions); | ||
return new ForwardingHttpJsonClientCall.SimpleForwardingHttpJsonClientCall< | ||
RequestT, ResponseT>(call) { | ||
@Override | ||
public void start(Listener<ResponseT> responseListener, HttpJsonMetadata requestHeaders) { | ||
Listener<ResponseT> forwardingResponseListener = | ||
new ForwardingHttpJsonClientCallListener.SimpleForwardingHttpJsonClientCallListener< | ||
ResponseT>(responseListener) { | ||
@Override | ||
public void onHeaders(HttpJsonMetadata responseHeaders) { | ||
metadata = responseHeaders; | ||
super.onHeaders(responseHeaders); | ||
} | ||
|
||
@Override | ||
public void onMessage(ResponseT message) { | ||
super.onMessage(message); | ||
} | ||
|
||
@Override | ||
public void onClose(int statusCode, HttpJsonMetadata trailers) { | ||
super.onClose(statusCode, trailers); | ||
} | ||
}; | ||
|
||
super.start(forwardingResponseListener, requestHeaders); | ||
} | ||
}; | ||
} | ||
} | ||
|
||
private HttpJsonCapturingClientInterceptor httpJsonInterceptor; | ||
private GrpcCapturingClientInterceptor grpcInterceptor; | ||
private HttpJsonCapturingClientInterceptor httpJsonComplianceInterceptor; | ||
private GrpcCapturingClientInterceptor grpcComplianceInterceptor; | ||
private EchoClient grpcClient; | ||
private EchoClient httpJsonClient; | ||
private ComplianceClient grpcComplianceClient; | ||
private ComplianceClient httpJsonComplianceClient; | ||
|
||
@Before | ||
public void createClients() throws Exception { | ||
// Create gRPC Interceptor and Client | ||
grpcInterceptor = new GrpcCapturingClientInterceptor(); | ||
grpcClient = TestClientInitializer.createGrpcEchoClient(ImmutableList.of(grpcInterceptor)); | ||
|
||
// Create HttpJson Interceptor and Client | ||
httpJsonInterceptor = new HttpJsonCapturingClientInterceptor(); | ||
httpJsonClient = | ||
TestClientInitializer.createHttpJsonEchoClient(ImmutableList.of(httpJsonInterceptor)); | ||
|
||
// Create gRPC ComplianceClient and Interceptor | ||
// Creating a compliance client to test case where api version is not set | ||
grpcComplianceInterceptor = new GrpcCapturingClientInterceptor(); | ||
grpcComplianceClient = | ||
TestClientInitializer.createGrpcComplianceClient( | ||
ImmutableList.of(grpcComplianceInterceptor)); | ||
|
||
// Create HttpJson ComplianceClient and Interceptor | ||
httpJsonComplianceInterceptor = new HttpJsonCapturingClientInterceptor(); | ||
httpJsonComplianceClient = | ||
TestClientInitializer.createHttpJsonComplianceClient( | ||
ImmutableList.of(httpJsonComplianceInterceptor)); | ||
} | ||
|
||
@After | ||
public void destroyClient() throws InterruptedException { | ||
grpcClient.close(); | ||
httpJsonClient.close(); | ||
grpcComplianceClient.close(); | ||
httpJsonComplianceClient.close(); | ||
|
||
grpcClient.awaitTermination(DEFAULT_AWAIT_TERMINATION_SEC, TimeUnit.SECONDS); | ||
httpJsonClient.awaitTermination(DEFAULT_AWAIT_TERMINATION_SEC, TimeUnit.SECONDS); | ||
grpcComplianceClient.awaitTermination(DEFAULT_AWAIT_TERMINATION_SEC, TimeUnit.SECONDS); | ||
httpJsonComplianceClient.awaitTermination(DEFAULT_AWAIT_TERMINATION_SEC, TimeUnit.SECONDS); | ||
} | ||
|
||
@Test | ||
public void testGrpc_matchesApiVersion() { | ||
grpcClient.echo(EchoRequest.newBuilder().build()); | ||
String headerValue = grpcInterceptor.metadata.get(API_VERSION_HEADER_KEY); | ||
assertThat(headerValue).isEqualTo(EXPECTED_ECHO_API_VERSION); | ||
} | ||
|
||
@Test | ||
public void testHttpJson_matchesHeaderName() { | ||
httpJsonClient.echo(EchoRequest.newBuilder().build()); | ||
ArrayList headerValues = | ||
(ArrayList) httpJsonInterceptor.metadata.getHeaders().get(HTTP_RESPONSE_HEADER_STRING); | ||
String headerValue = (String) headerValues.get(0); | ||
assertThat(headerValue).isEqualTo(EXPECTED_ECHO_API_VERSION); | ||
} | ||
|
||
@Test | ||
public void testGrpc_noApiVersion() { | ||
RepeatRequest request = | ||
RepeatRequest.newBuilder().setInfo(ComplianceData.newBuilder().setFString("test")).build(); | ||
grpcComplianceClient.repeatDataSimplePath(request); | ||
assertThat(API_VERSION_HEADER_KEY).isNotIn(grpcComplianceInterceptor.metadata.keys()); | ||
} | ||
|
||
@Test | ||
public void testHttpJson_noApiVersion() { | ||
RepeatRequest request = | ||
RepeatRequest.newBuilder().setInfo(ComplianceData.newBuilder().setFString("test")).build(); | ||
httpJsonComplianceClient.repeatDataSimplePath(request); | ||
assertThat(API_VERSION_HEADER_KEY) | ||
.isNotIn(httpJsonComplianceInterceptor.metadata.getHeaders().keySet()); | ||
} | ||
|
||
@Test | ||
public void testGrpcEcho_userApiVersionThrowsException() throws IOException { | ||
StubSettings stubSettings = | ||
grpcClient | ||
.getSettings() | ||
.getStubSettings() | ||
.toBuilder() | ||
.setHeaderProvider( | ||
FixedHeaderProvider.create( | ||
ApiClientHeaderProvider.API_VERSION_HEADER_KEY, CUSTOM_API_VERSION)) | ||
.build(); | ||
|
||
IllegalArgumentException exception = | ||
assertThrows( | ||
IllegalArgumentException.class, | ||
() -> EchoClient.create(EchoSettings.create((EchoStubSettings) stubSettings))); | ||
assertThat(exception.getMessage()).isEqualTo(EXPECTED_EXCEPTION_MESSAGE); | ||
} | ||
|
||
@Test | ||
public void testHttpJsonEcho_userApiVersionThrowsException() throws IOException { | ||
StubSettings stubSettings = | ||
httpJsonClient | ||
.getSettings() | ||
.getStubSettings() | ||
.toBuilder() | ||
.setHeaderProvider( | ||
FixedHeaderProvider.create( | ||
ApiClientHeaderProvider.API_VERSION_HEADER_KEY, CUSTOM_API_VERSION)) | ||
.build(); | ||
|
||
IllegalArgumentException exception = | ||
assertThrows( | ||
IllegalArgumentException.class, | ||
() -> EchoClient.create(EchoSettings.create((EchoStubSettings) stubSettings))); | ||
assertThat(exception.getMessage()).isEqualTo(EXPECTED_EXCEPTION_MESSAGE); | ||
} | ||
|
||
@Test | ||
public void testGrpcCompliance_userApiVersionSetSuccess() throws IOException { | ||
StubSettings stubSettingsWithApiVersionHeader = | ||
grpcComplianceClient | ||
.getSettings() | ||
.getStubSettings() | ||
.toBuilder() | ||
.setHeaderProvider( | ||
FixedHeaderProvider.create( | ||
ApiClientHeaderProvider.API_VERSION_HEADER_KEY, CUSTOM_API_VERSION)) | ||
.build(); | ||
try (ComplianceClient customComplianceClient = | ||
ComplianceClient.create( | ||
ComplianceSettings.create((ComplianceStubSettings) stubSettingsWithApiVersionHeader))) { | ||
|
||
RepeatRequest request = | ||
RepeatRequest.newBuilder() | ||
.setInfo(ComplianceData.newBuilder().setFString("test")) | ||
.build(); | ||
customComplianceClient.repeatDataSimplePath(request); | ||
String headerValue = grpcComplianceInterceptor.metadata.get(API_VERSION_HEADER_KEY); | ||
assertThat(headerValue).isEqualTo(CUSTOM_API_VERSION); | ||
} | ||
} | ||
|
||
@Test | ||
public void testHttpJsonCompliance_userApiVersionSetSuccess() throws IOException { | ||
StubSettings httpJsonStubSettingsWithApiVersionHeader = | ||
httpJsonComplianceClient | ||
.getSettings() | ||
.getStubSettings() | ||
.toBuilder() | ||
.setHeaderProvider( | ||
FixedHeaderProvider.create( | ||
ApiClientHeaderProvider.API_VERSION_HEADER_KEY, CUSTOM_API_VERSION)) | ||
.build(); | ||
try (ComplianceClient customComplianceClient = | ||
ComplianceClient.create( | ||
ComplianceSettings.create( | ||
(ComplianceStubSettings) httpJsonStubSettingsWithApiVersionHeader))) { | ||
|
||
RepeatRequest request = | ||
RepeatRequest.newBuilder() | ||
.setInfo(ComplianceData.newBuilder().setFString("test")) | ||
.build(); | ||
customComplianceClient.repeatDataSimplePath(request); | ||
|
||
ArrayList headerValues = | ||
(ArrayList) | ||
httpJsonComplianceInterceptor.metadata.getHeaders().get(HTTP_RESPONSE_HEADER_STRING); | ||
String headerValue = (String) headerValues.get(0); | ||
assertThat(headerValue).isEqualTo(CUSTOM_API_VERSION); | ||
} | ||
} | ||
} |