Merge github.com:grpc/grpc into direct-calls

reviewable/pr8008/r20
Craig Tiller 8 years ago
commit 272c8d2ca9
  1. 41
      doc/interop-test-descriptions.md
  2. 5
      src/proto/grpc/testing/test.proto
  3. 4
      test/cpp/interop/client.cc
  4. 44
      test/cpp/interop/interop_client.cc
  5. 1
      test/cpp/interop/interop_client.h
  6. 12
      test/cpp/interop/interop_server.cc

@ -60,6 +60,35 @@ Client asserts:
*It may be possible to use UnaryCall instead of EmptyCall, but it is harder to *It may be possible to use UnaryCall instead of EmptyCall, but it is harder to
ensure that the proto serialized to zero bytes.* 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 ### large_unary
This test verifies unary calls succeed in sending messages, and touches on flow 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 for the `SimpleRequest.response_type`. If the server does not support the
`response_type`, then it should fail the RPC with `INVALID_ARGUMENT`. `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]: #compressedresponse [CompressedResponse]: #compressedresponse

@ -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)

@ -149,6 +149,8 @@ int main(int argc, char** argv) {
client.DoStatusWithMessage(); client.DoStatusWithMessage();
} else if (FLAGS_test_case == "custom_metadata") { } else if (FLAGS_test_case == "custom_metadata") {
client.DoCustomMetadata(); client.DoCustomMetadata();
} else if (FLAGS_test_case == "cacheable_unary") {
client.DoCacheableUnary();
} else if (FLAGS_test_case == "all") { } else if (FLAGS_test_case == "all") {
client.DoEmpty(); client.DoEmpty();
client.DoLargeUnary(); client.DoLargeUnary();
@ -166,6 +168,7 @@ int main(int argc, char** argv) {
client.DoEmptyStream(); client.DoEmptyStream();
client.DoStatusWithMessage(); client.DoStatusWithMessage();
client.DoCustomMetadata(); client.DoCustomMetadata();
client.DoCacheableUnary();
// service_account_creds and jwt_token_creds can only run with ssl. // service_account_creds and jwt_token_creds can only run with ssl.
if (FLAGS_use_tls) { if (FLAGS_use_tls) {
grpc::string json_key = GetServiceAccountJsonKey(); grpc::string json_key = GetServiceAccountJsonKey();
@ -177,6 +180,7 @@ int main(int argc, char** argv) {
// compute_engine_creds only runs in GCE. // compute_engine_creds only runs in GCE.
} else { } else {
const char* testcases[] = {"all", const char* testcases[] = {"all",
"cacheable_unary",
"cancel_after_begin", "cancel_after_begin",
"cancel_after_first_response", "cancel_after_first_response",
"client_compressed_streaming", "client_compressed_streaming",

@ -846,6 +846,50 @@ bool InteropClient::DoStatusWithMessage() {
return true; 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() { bool InteropClient::DoCustomMetadata() {
const grpc::string kEchoInitialMetadataKey("x-grpc-test-echo-initial"); const grpc::string kEchoInitialMetadataKey("x-grpc-test-echo-initial");
const grpc::string kInitialMetadataValue("test_initial_metadata_value"); const grpc::string kInitialMetadataValue("test_initial_metadata_value");

@ -79,6 +79,7 @@ class InteropClient {
bool DoEmptyStream(); bool DoEmptyStream();
bool DoStatusWithMessage(); bool DoStatusWithMessage();
bool DoCustomMetadata(); bool DoCustomMetadata();
bool DoCacheableUnary();
// Auth tests. // Auth tests.
// username is a string containing the user email // username is a string containing the user email
bool DoJwtTokenCreds(const grpc::string& username); bool DoJwtTokenCreds(const grpc::string& username);

@ -47,6 +47,7 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/byte_stream.h"
#include "src/proto/grpc/testing/empty.grpc.pb.h" #include "src/proto/grpc/testing/empty.grpc.pb.h"
#include "src/proto/grpc/testing/messages.grpc.pb.h" #include "src/proto/grpc/testing/messages.grpc.pb.h"
@ -153,6 +154,17 @@ class TestServiceImpl : public TestService::Service {
return Status::OK; 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, Status UnaryCall(ServerContext* context, const SimpleRequest* request,
SimpleResponse* response) { SimpleResponse* response) {
MaybeEchoMetadata(context); MaybeEchoMetadata(context);

Loading…
Cancel
Save