aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2016-10-13 09:36:37 -0700
committerGravatar Craig Tiller <ctiller@google.com>2016-10-13 09:36:37 -0700
commit272c8d2ca931bf08c3292cbcae7874444d03e3c8 (patch)
tree724525e2b911953f6121579ed74a0feef71919bf
parent9381c00857d0acc4fc034937260f32ee26e836b9 (diff)
parentd44144c3b2112ed61a21c08331bfe9e18664ceb3 (diff)
Merge github.com:grpc/grpc into direct-calls
-rw-r--r--doc/interop-test-descriptions.md41
-rw-r--r--src/proto/grpc/testing/test.proto5
-rw-r--r--test/cpp/interop/client.cc4
-rw-r--r--test/cpp/interop/interop_client.cc44
-rw-r--r--test/cpp/interop/interop_client.h1
-rw-r--r--test/cpp/interop/interop_server.cc12
6 files changed, 107 insertions, 0 deletions
diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md
index 1e04966380..666af185b9 100644
--- a/doc/interop-test-descriptions.md
+++ b/doc/interop-test-descriptions.md
@@ -60,6 +60,35 @@ Client asserts:
*It may be possible to use UnaryCall instead of EmptyCall, but it is harder to
ensure that the proto serialized to zero bytes.*
+### cacheable_unary
+
+This test verifies that gRPC requests marked as cacheable use GET verb instead
+of POST, and that server sets appropriate cache control headers for the response
+to be cached by a proxy. This test requires that the server is behind
+a caching proxy. Use of current timestamp in the request prevents accidental
+cache matches left over from previous tests.
+
+Server features:
+* [CacheableUnaryCall][]
+
+Procedure:
+ 1. Client calls CacheableUnaryCall with `SimpleRequest` request with payload
+ set to current timestamp. Timestamp format is irrelevant, and resolution is
+ in nanoseconds.
+ Client adds a `x-user-ip` header with value `1.2.3.4` to the request.
+ This is done since some proxys such as GFE will not cache requests from
+ localhost.
+ Client marks the request as cacheable by setting the cacheable flag in the
+ request context. Longer term this should be driven by the method option
+ specified in the proto file itself.
+ 2. Client calls CacheableUnaryCall with `SimpleRequest` request again
+ immediately with the same payload as the previous request. Cacheable flag is
+ also set for this request's context.
+
+Client asserts:
+* Both calls were successful
+* The payload body of both responses is the same.
+
### large_unary
This test verifies unary calls succeed in sending messages, and touches on flow
@@ -941,6 +970,18 @@ payload body of size `SimpleRequest.response_size` bytes and type as appropriate
for the `SimpleRequest.response_type`. If the server does not support the
`response_type`, then it should fail the RPC with `INVALID_ARGUMENT`.
+### CacheableUnaryCall
+
+Server gets the default SimpleRequest proto as the request. The content of the
+request is ignored. It returns the SimpleResponse proto with the payload set
+to current timestamp. The timestamp is an integer representing current time
+with nanosecond resolution. This integer is formated as ASCII decimal in the
+response. The format is not really important as long as the response payload
+is different for each request. In addition it adds
+ 1. cache control headers such that the response can be cached by proxies in
+ the response path. Server should be behind a caching proxy for this test
+ to pass. Currently we set the max-age to 60 seconds.
+
### CompressedResponse
[CompressedResponse]: #compressedresponse
diff --git a/src/proto/grpc/testing/test.proto b/src/proto/grpc/testing/test.proto
index 84369db4b8..b52c4cbad6 100644
--- a/src/proto/grpc/testing/test.proto
+++ b/src/proto/grpc/testing/test.proto
@@ -47,6 +47,11 @@ service TestService {
// One request followed by one response.
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).
// The server returns the payload with client desired type and sizes.
rpc StreamingOutputCall(StreamingOutputCallRequest)
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index 032b378b1a..999be9d8a3 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -149,6 +149,8 @@ int main(int argc, char** argv) {
client.DoStatusWithMessage();
} else if (FLAGS_test_case == "custom_metadata") {
client.DoCustomMetadata();
+ } else if (FLAGS_test_case == "cacheable_unary") {
+ client.DoCacheableUnary();
} else if (FLAGS_test_case == "all") {
client.DoEmpty();
client.DoLargeUnary();
@@ -166,6 +168,7 @@ int main(int argc, char** argv) {
client.DoEmptyStream();
client.DoStatusWithMessage();
client.DoCustomMetadata();
+ client.DoCacheableUnary();
// service_account_creds and jwt_token_creds can only run with ssl.
if (FLAGS_use_tls) {
grpc::string json_key = GetServiceAccountJsonKey();
@@ -177,6 +180,7 @@ int main(int argc, char** argv) {
// compute_engine_creds only runs in GCE.
} else {
const char* testcases[] = {"all",
+ "cacheable_unary",
"cancel_after_begin",
"cancel_after_first_response",
"client_compressed_streaming",
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index 6117878a33..e9a804ccae 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -846,6 +846,50 @@ bool InteropClient::DoStatusWithMessage() {
return true;
}
+bool InteropClient::DoCacheableUnary() {
+ gpr_log(GPR_DEBUG, "Sending RPC with cacheable response");
+
+ // Create request with current timestamp
+ gpr_timespec ts = gpr_now(GPR_CLOCK_PRECISE);
+ std::string timestamp = std::to_string((long long unsigned)ts.tv_nsec);
+ SimpleRequest request;
+ request.mutable_payload()->set_body(timestamp.c_str(), timestamp.size());
+
+ // Request 1
+ ClientContext context1;
+ SimpleResponse response1;
+ context1.set_cacheable(true);
+ // Add fake user IP since some proxy's (GFE) won't cache requests from
+ // localhost.
+ context1.AddMetadata("x-user-ip", "1.2.3.4");
+ Status s1 =
+ serviceStub_.Get()->CacheableUnaryCall(&context1, request, &response1);
+ if (!AssertStatusOk(s1)) {
+ return false;
+ }
+ gpr_log(GPR_DEBUG, "response 1 payload: %s",
+ response1.payload().body().c_str());
+
+ // Request 2
+ ClientContext context2;
+ SimpleResponse response2;
+ context2.set_cacheable(true);
+ context2.AddMetadata("x-user-ip", "1.2.3.4");
+ Status s2 =
+ serviceStub_.Get()->CacheableUnaryCall(&context2, request, &response2);
+ if (!AssertStatusOk(s2)) {
+ return false;
+ }
+ gpr_log(GPR_DEBUG, "response 2 payload: %s",
+ response2.payload().body().c_str());
+
+ // Check that the body is same for both requests. It will be the same if the
+ // second response is a cached copy of the first response
+ GPR_ASSERT(response2.payload().body() == response1.payload().body());
+
+ return true;
+}
+
bool InteropClient::DoCustomMetadata() {
const grpc::string kEchoInitialMetadataKey("x-grpc-test-echo-initial");
const grpc::string kInitialMetadataValue("test_initial_metadata_value");
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index eb886fcb7e..1e89f0987d 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -79,6 +79,7 @@ class InteropClient {
bool DoEmptyStream();
bool DoStatusWithMessage();
bool DoCustomMetadata();
+ bool DoCacheableUnary();
// Auth tests.
// username is a string containing the user email
bool DoJwtTokenCreds(const grpc::string& username);
diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc
index c05eb5d146..58f20aa611 100644
--- a/test/cpp/interop/interop_server.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -47,6 +47,7 @@
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
+#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/byte_stream.h"
#include "src/proto/grpc/testing/empty.grpc.pb.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h"
@@ -153,6 +154,17 @@ class TestServiceImpl : public TestService::Service {
return Status::OK;
}
+ // Response contains current timestamp. We ignore everything in the request.
+ Status CacheableUnaryCall(ServerContext* context,
+ const SimpleRequest* request,
+ SimpleResponse* response) {
+ gpr_timespec ts = gpr_now(GPR_CLOCK_PRECISE);
+ std::string timestamp = std::to_string((long long unsigned)ts.tv_nsec);
+ response->mutable_payload()->set_body(timestamp.c_str(), timestamp.size());
+ context->AddInitialMetadata("cache-control", "max-age=60, public");
+ return Status::OK;
+ }
+
Status UnaryCall(ServerContext* context, const SimpleRequest* request,
SimpleResponse* response) {
MaybeEchoMetadata(context);