interop-testing: add cacheable_unary test

This commit is contained in:
Eric Gribkoff 2017-04-20 12:37:36 -07:00
parent e36d229dc2
commit b6bf252566
8 changed files with 175 additions and 29 deletions

View File

@ -35,6 +35,7 @@ import static com.google.common.truth.Truth.assertThat;
import static io.grpc.testing.integration.Messages.PayloadType.COMPRESSABLE; import static io.grpc.testing.integration.Messages.PayloadType.COMPRESSABLE;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -65,6 +66,7 @@ import io.grpc.CallOptions;
import io.grpc.Channel; import io.grpc.Channel;
import io.grpc.ClientCall; import io.grpc.ClientCall;
import io.grpc.ClientInterceptor; import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.ClientStreamTracer; import io.grpc.ClientStreamTracer;
import io.grpc.Context; import io.grpc.Context;
import io.grpc.Grpc; import io.grpc.Grpc;
@ -85,6 +87,7 @@ import io.grpc.internal.GrpcUtil;
import io.grpc.internal.testing.StatsTestUtils.FakeStatsContextFactory; import io.grpc.internal.testing.StatsTestUtils.FakeStatsContextFactory;
import io.grpc.internal.testing.StatsTestUtils.MetricsRecord; import io.grpc.internal.testing.StatsTestUtils.MetricsRecord;
import io.grpc.protobuf.ProtoUtils; import io.grpc.protobuf.ProtoUtils;
import io.grpc.stub.ClientCalls;
import io.grpc.stub.MetadataUtils; import io.grpc.stub.MetadataUtils;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
import io.grpc.testing.StreamRecorder; import io.grpc.testing.StreamRecorder;
@ -270,6 +273,44 @@ public abstract class AbstractInteropTest {
assertEquals(EMPTY, blockingStub.emptyCall(EMPTY)); assertEquals(EMPTY, blockingStub.emptyCall(EMPTY));
} }
/** Sends a cacheable unary rpc using GET. Requires that the server is behind a caching proxy. */
public void cacheableUnary() {
// Set safe to true.
MethodDescriptor<SimpleRequest, SimpleResponse> safeCacheableUnaryCallMethod =
TestServiceGrpc.METHOD_CACHEABLE_UNARY_CALL.toBuilder().setSafe(true).build();
// Set fake user IP since some proxies (GFE) won't cache requests from localhost.
Metadata.Key<String> userIpKey = Metadata.Key.of("x-user-ip", Metadata.ASCII_STRING_MARSHALLER);
Metadata metadata = new Metadata();
metadata.put(userIpKey, "1.2.3.4");
Channel channelWithUserIpKey =
ClientInterceptors.intercept(channel, MetadataUtils.newAttachHeadersInterceptor(metadata));
SimpleRequest requests1And2 =
SimpleRequest.newBuilder()
.setPayload(
Payload.newBuilder()
.setBody(ByteString.copyFromUtf8(String.valueOf(System.nanoTime()))))
.build();
SimpleRequest request3 =
SimpleRequest.newBuilder()
.setPayload(
Payload.newBuilder()
.setBody(ByteString.copyFromUtf8(String.valueOf(System.nanoTime()))))
.build();
SimpleResponse response1 =
ClientCalls.blockingUnaryCall(
channelWithUserIpKey, safeCacheableUnaryCallMethod, CallOptions.DEFAULT, requests1And2);
SimpleResponse response2 =
ClientCalls.blockingUnaryCall(
channelWithUserIpKey, safeCacheableUnaryCallMethod, CallOptions.DEFAULT, requests1And2);
SimpleResponse response3 =
ClientCalls.blockingUnaryCall(
channelWithUserIpKey, safeCacheableUnaryCallMethod, CallOptions.DEFAULT, request3);
assertEquals(response1, response2);
assertNotEquals(response1, response3);
}
@Test(timeout = 10000) @Test(timeout = 10000)
public void largeUnary() throws Exception { public void largeUnary() throws Exception {
assumeEnoughMemory(); assumeEnoughMemory();

View File

@ -38,6 +38,7 @@ import com.google.common.base.Preconditions;
*/ */
public enum TestCases { public enum TestCases {
EMPTY_UNARY("empty (zero bytes) request and response"), EMPTY_UNARY("empty (zero bytes) request and response"),
CACHEABLE_UNARY("cacheable unary rpc sent using GET"),
LARGE_UNARY("single request and (large) response"), LARGE_UNARY("single request and (large) response"),
CLIENT_STREAMING("request streaming with single response"), CLIENT_STREAMING("request streaming with single response"),
SERVER_STREAMING("single request with response streaming"), SERVER_STREAMING("single request with response streaming"),

View File

@ -209,6 +209,11 @@ public class TestServiceClient {
tester.emptyUnary(); tester.emptyUnary();
break; break;
case CACHEABLE_UNARY: {
tester.cacheableUnary();
break;
}
case LARGE_UNARY: case LARGE_UNARY:
tester.largeUnary(); tester.largeUnary();
break; break;

View File

@ -54,11 +54,27 @@ public class TestCasesTest {
@Test @Test
public void testCaseNamesShouldMapToEnums() { public void testCaseNamesShouldMapToEnums() {
// names of testcases as defined in the interop spec // names of testcases as defined in the interop spec
String[] testCases = {"empty_unary", "large_unary", "client_streaming", "server_streaming", String[] testCases = {
"ping_pong", "empty_stream", "compute_engine_creds", "service_account_creds", "empty_unary",
"jwt_token_creds", "oauth2_auth_token", "per_rpc_creds", "custom_metadata", "cacheable_unary",
"status_code_and_message", "unimplemented_method", "unimplemented_service", "large_unary",
"cancel_after_begin", "cancel_after_first_response", "timeout_on_sleeping_server"}; "client_streaming",
"server_streaming",
"ping_pong",
"empty_stream",
"compute_engine_creds",
"service_account_creds",
"jwt_token_creds",
"oauth2_auth_token",
"per_rpc_creds",
"custom_metadata",
"status_code_and_message",
"unimplemented_method",
"unimplemented_service",
"cancel_after_begin",
"cancel_after_first_response",
"timeout_on_sleeping_server"
};
assertEquals(testCases.length, TestCases.values().length); assertEquals(testCases.length, TestCases.values().length);

View File

@ -128,6 +128,7 @@ class NettyClientStream extends AbstractClientStream2 {
AsciiString httpMethod; AsciiString httpMethod;
if (get) { if (get) {
// Forge the query string // Forge the query string
// TODO(ericgribkoff) Add the key back to the query string
defaultPath = defaultPath =
new AsciiString(defaultPath + "?" + BaseEncoding.base64().encode(requestPayload)); new AsciiString(defaultPath + "?" + BaseEncoding.base64().encode(requestPayload));
httpMethod = Utils.HTTP_GET_METHOD; httpMethod = Utils.HTTP_GET_METHOD;

View File

@ -56,6 +56,18 @@ public final class TestServiceGrpc {
io.grpc.testing.integration.Messages.SimpleResponse.getDefaultInstance())) io.grpc.testing.integration.Messages.SimpleResponse.getDefaultInstance()))
.build(); .build();
@io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901") @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901")
public static final io.grpc.MethodDescriptor<io.grpc.testing.integration.Messages.SimpleRequest,
io.grpc.testing.integration.Messages.SimpleResponse> METHOD_CACHEABLE_UNARY_CALL =
io.grpc.MethodDescriptor.<io.grpc.testing.integration.Messages.SimpleRequest, io.grpc.testing.integration.Messages.SimpleResponse>newBuilder()
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
.setFullMethodName(generateFullMethodName(
"grpc.testing.TestService", "CacheableUnaryCall"))
.setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
io.grpc.testing.integration.Messages.SimpleRequest.getDefaultInstance()))
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
io.grpc.testing.integration.Messages.SimpleResponse.getDefaultInstance()))
.build();
@io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901")
public static final io.grpc.MethodDescriptor<io.grpc.testing.integration.Messages.StreamingOutputCallRequest, public static final io.grpc.MethodDescriptor<io.grpc.testing.integration.Messages.StreamingOutputCallRequest,
io.grpc.testing.integration.Messages.StreamingOutputCallResponse> METHOD_STREAMING_OUTPUT_CALL = io.grpc.testing.integration.Messages.StreamingOutputCallResponse> METHOD_STREAMING_OUTPUT_CALL =
io.grpc.MethodDescriptor.<io.grpc.testing.integration.Messages.StreamingOutputCallRequest, io.grpc.testing.integration.Messages.StreamingOutputCallResponse>newBuilder() io.grpc.MethodDescriptor.<io.grpc.testing.integration.Messages.StreamingOutputCallRequest, io.grpc.testing.integration.Messages.StreamingOutputCallResponse>newBuilder()
@ -167,6 +179,18 @@ public final class TestServiceGrpc {
asyncUnimplementedUnaryCall(METHOD_UNARY_CALL, responseObserver); asyncUnimplementedUnaryCall(METHOD_UNARY_CALL, responseObserver);
} }
/**
* <pre>
* One request followed by one response. Response has cache control
* headers set such that a caching HTTP proxy (such as GFE) can
* satisfy subsequent requests.
* </pre>
*/
public void cacheableUnaryCall(io.grpc.testing.integration.Messages.SimpleRequest request,
io.grpc.stub.StreamObserver<io.grpc.testing.integration.Messages.SimpleResponse> responseObserver) {
asyncUnimplementedUnaryCall(METHOD_CACHEABLE_UNARY_CALL, responseObserver);
}
/** /**
* <pre> * <pre>
* One request followed by a sequence of responses (streamed download). * One request followed by a sequence of responses (streamed download).
@ -241,6 +265,13 @@ public final class TestServiceGrpc {
io.grpc.testing.integration.Messages.SimpleRequest, io.grpc.testing.integration.Messages.SimpleRequest,
io.grpc.testing.integration.Messages.SimpleResponse>( io.grpc.testing.integration.Messages.SimpleResponse>(
this, METHODID_UNARY_CALL))) this, METHODID_UNARY_CALL)))
.addMethod(
METHOD_CACHEABLE_UNARY_CALL,
asyncUnaryCall(
new MethodHandlers<
io.grpc.testing.integration.Messages.SimpleRequest,
io.grpc.testing.integration.Messages.SimpleResponse>(
this, METHODID_CACHEABLE_UNARY_CALL)))
.addMethod( .addMethod(
METHOD_STREAMING_OUTPUT_CALL, METHOD_STREAMING_OUTPUT_CALL,
asyncServerStreamingCall( asyncServerStreamingCall(
@ -324,6 +355,19 @@ public final class TestServiceGrpc {
getChannel().newCall(METHOD_UNARY_CALL, getCallOptions()), request, responseObserver); getChannel().newCall(METHOD_UNARY_CALL, getCallOptions()), request, responseObserver);
} }
/**
* <pre>
* One request followed by one response. Response has cache control
* headers set such that a caching HTTP proxy (such as GFE) can
* satisfy subsequent requests.
* </pre>
*/
public void cacheableUnaryCall(io.grpc.testing.integration.Messages.SimpleRequest request,
io.grpc.stub.StreamObserver<io.grpc.testing.integration.Messages.SimpleResponse> responseObserver) {
asyncUnaryCall(
getChannel().newCall(METHOD_CACHEABLE_UNARY_CALL, getCallOptions()), request, responseObserver);
}
/** /**
* <pre> * <pre>
* One request followed by a sequence of responses (streamed download). * One request followed by a sequence of responses (streamed download).
@ -430,6 +474,18 @@ public final class TestServiceGrpc {
getChannel(), METHOD_UNARY_CALL, getCallOptions(), request); getChannel(), METHOD_UNARY_CALL, getCallOptions(), request);
} }
/**
* <pre>
* One request followed by one response. Response has cache control
* headers set such that a caching HTTP proxy (such as GFE) can
* satisfy subsequent requests.
* </pre>
*/
public io.grpc.testing.integration.Messages.SimpleResponse cacheableUnaryCall(io.grpc.testing.integration.Messages.SimpleRequest request) {
return blockingUnaryCall(
getChannel(), METHOD_CACHEABLE_UNARY_CALL, getCallOptions(), request);
}
/** /**
* <pre> * <pre>
* One request followed by a sequence of responses (streamed download). * One request followed by a sequence of responses (streamed download).
@ -498,6 +554,19 @@ public final class TestServiceGrpc {
getChannel().newCall(METHOD_UNARY_CALL, getCallOptions()), request); getChannel().newCall(METHOD_UNARY_CALL, getCallOptions()), request);
} }
/**
* <pre>
* One request followed by one response. Response has cache control
* headers set such that a caching HTTP proxy (such as GFE) can
* satisfy subsequent requests.
* </pre>
*/
public com.google.common.util.concurrent.ListenableFuture<io.grpc.testing.integration.Messages.SimpleResponse> cacheableUnaryCall(
io.grpc.testing.integration.Messages.SimpleRequest request) {
return futureUnaryCall(
getChannel().newCall(METHOD_CACHEABLE_UNARY_CALL, getCallOptions()), request);
}
/** /**
* <pre> * <pre>
* The test server will not implement this method. It will be used * The test server will not implement this method. It will be used
@ -513,11 +582,12 @@ public final class TestServiceGrpc {
private static final int METHODID_EMPTY_CALL = 0; private static final int METHODID_EMPTY_CALL = 0;
private static final int METHODID_UNARY_CALL = 1; private static final int METHODID_UNARY_CALL = 1;
private static final int METHODID_STREAMING_OUTPUT_CALL = 2; private static final int METHODID_CACHEABLE_UNARY_CALL = 2;
private static final int METHODID_UNIMPLEMENTED_CALL = 3; private static final int METHODID_STREAMING_OUTPUT_CALL = 3;
private static final int METHODID_STREAMING_INPUT_CALL = 4; private static final int METHODID_UNIMPLEMENTED_CALL = 4;
private static final int METHODID_FULL_DUPLEX_CALL = 5; private static final int METHODID_STREAMING_INPUT_CALL = 5;
private static final int METHODID_HALF_DUPLEX_CALL = 6; private static final int METHODID_FULL_DUPLEX_CALL = 6;
private static final int METHODID_HALF_DUPLEX_CALL = 7;
private static final class MethodHandlers<Req, Resp> implements private static final class MethodHandlers<Req, Resp> implements
io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>, io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
@ -544,6 +614,10 @@ public final class TestServiceGrpc {
serviceImpl.unaryCall((io.grpc.testing.integration.Messages.SimpleRequest) request, serviceImpl.unaryCall((io.grpc.testing.integration.Messages.SimpleRequest) request,
(io.grpc.stub.StreamObserver<io.grpc.testing.integration.Messages.SimpleResponse>) responseObserver); (io.grpc.stub.StreamObserver<io.grpc.testing.integration.Messages.SimpleResponse>) responseObserver);
break; break;
case METHODID_CACHEABLE_UNARY_CALL:
serviceImpl.cacheableUnaryCall((io.grpc.testing.integration.Messages.SimpleRequest) request,
(io.grpc.stub.StreamObserver<io.grpc.testing.integration.Messages.SimpleResponse>) responseObserver);
break;
case METHODID_STREAMING_OUTPUT_CALL: case METHODID_STREAMING_OUTPUT_CALL:
serviceImpl.streamingOutputCall((io.grpc.testing.integration.Messages.StreamingOutputCallRequest) request, serviceImpl.streamingOutputCall((io.grpc.testing.integration.Messages.StreamingOutputCallRequest) request,
(io.grpc.stub.StreamObserver<io.grpc.testing.integration.Messages.StreamingOutputCallResponse>) responseObserver); (io.grpc.stub.StreamObserver<io.grpc.testing.integration.Messages.StreamingOutputCallResponse>) responseObserver);
@ -596,6 +670,7 @@ public final class TestServiceGrpc {
.setSchemaDescriptor(new TestServiceDescriptorSupplier()) .setSchemaDescriptor(new TestServiceDescriptorSupplier())
.addMethod(METHOD_EMPTY_CALL) .addMethod(METHOD_EMPTY_CALL)
.addMethod(METHOD_UNARY_CALL) .addMethod(METHOD_UNARY_CALL)
.addMethod(METHOD_CACHEABLE_UNARY_CALL)
.addMethod(METHOD_STREAMING_OUTPUT_CALL) .addMethod(METHOD_STREAMING_OUTPUT_CALL)
.addMethod(METHOD_STREAMING_INPUT_CALL) .addMethod(METHOD_STREAMING_INPUT_CALL)
.addMethod(METHOD_FULL_DUPLEX_CALL) .addMethod(METHOD_FULL_DUPLEX_CALL)

View File

@ -26,29 +26,31 @@ public final class Test {
"\n&io/grpc/testing/integration/test.proto" + "\n&io/grpc/testing/integration/test.proto" +
"\022\014grpc.testing\032\'io/grpc/testing/integrat" + "\022\014grpc.testing\032\'io/grpc/testing/integrat" +
"ion/empty.proto\032*io/grpc/testing/integra" + "ion/empty.proto\032*io/grpc/testing/integra" +
"tion/messages.proto2\372\004\n\013TestService\0225\n\tE" + "tion/messages.proto2\313\005\n\013TestService\0225\n\tE" +
"mptyCall\022\023.grpc.testing.Empty\032\023.grpc.tes" + "mptyCall\022\023.grpc.testing.Empty\032\023.grpc.tes" +
"ting.Empty\022F\n\tUnaryCall\022\033.grpc.testing.S" + "ting.Empty\022F\n\tUnaryCall\022\033.grpc.testing.S" +
"impleRequest\032\034.grpc.testing.SimpleRespon" + "impleRequest\032\034.grpc.testing.SimpleRespon" +
"se\022l\n\023StreamingOutputCall\022(.grpc.testing" + "se\022O\n\022CacheableUnaryCall\022\033.grpc.testing." +
"SimpleRequest\032\034.grpc.testing.SimpleRespo" +
"nse\022l\n\023StreamingOutputCall\022(.grpc.testin",
"g.StreamingOutputCallRequest\032).grpc.test" +
"ing.StreamingOutputCallResponse0\001\022i\n\022Str" +
"eamingInputCall\022\'.grpc.testing.Streaming" +
"InputCallRequest\032(.grpc.testing.Streamin" +
"gInputCallResponse(\001\022i\n\016FullDuplexCall\022(" +
".grpc.testing.StreamingOutputCallRequest" +
"\032).grpc.testing.StreamingOutputCallRespo" +
"nse(\0010\001\022i\n\016HalfDuplexCall\022(.grpc.testing" +
".StreamingOutputCallRequest\032).grpc.testi" + ".StreamingOutputCallRequest\032).grpc.testi" +
"ng.StreamingOutputCallResponse0\001\022i\n\022Stre", "ng.StreamingOutputCallResponse(\0010\001\022=\n\021Un",
"amingInputCall\022\'.grpc.testing.StreamingI" + "implementedCall\022\023.grpc.testing.Empty\032\023.g" +
"nputCallRequest\032(.grpc.testing.Streaming" + "rpc.testing.Empty2U\n\024UnimplementedServic" +
"InputCallResponse(\001\022i\n\016FullDuplexCall\022(." + "e\022=\n\021UnimplementedCall\022\023.grpc.testing.Em" +
"grpc.testing.StreamingOutputCallRequest\032" + "pty\032\023.grpc.testing.Empty2\177\n\020ReconnectSer" +
").grpc.testing.StreamingOutputCallRespon" + "vice\0221\n\005Start\022\023.grpc.testing.Empty\032\023.grp" +
"se(\0010\001\022i\n\016HalfDuplexCall\022(.grpc.testing." + "c.testing.Empty\0228\n\004Stop\022\023.grpc.testing.E" +
"StreamingOutputCallRequest\032).grpc.testin" + "mpty\032\033.grpc.testing.ReconnectInfoB\035\n\033io." +
"g.StreamingOutputCallResponse(\0010\001\022=\n\021Uni" + "grpc.testing.integrationb\006proto3"
"mplementedCall\022\023.grpc.testing.Empty\032\023.gr" +
"pc.testing.Empty2U\n\024UnimplementedService",
"\022=\n\021UnimplementedCall\022\023.grpc.testing.Emp" +
"ty\032\023.grpc.testing.Empty2\177\n\020ReconnectServ" +
"ice\0221\n\005Start\022\023.grpc.testing.Empty\032\023.grpc" +
".testing.Empty\0228\n\004Stop\022\023.grpc.testing.Em" +
"pty\032\033.grpc.testing.ReconnectInfoB\035\n\033io.g" +
"rpc.testing.integrationb\006proto3"
}; };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {

View File

@ -47,6 +47,11 @@ service TestService {
// One request followed by one response. // One request followed by one response.
rpc UnaryCall(SimpleRequest) returns (SimpleResponse); rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
// One request followed by one response. Response has cache control
// headers set such that a caching HTTP proxy (such as GFE) can
// satisfy subsequent requests.
rpc CacheableUnaryCall(SimpleRequest) returns (SimpleResponse);
// One request followed by a sequence of responses (streamed download). // One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes. // The server returns the payload with client desired type and sizes.
rpc StreamingOutputCall(StreamingOutputCallRequest) rpc StreamingOutputCall(StreamingOutputCallRequest)