Merge branch 'grpclb_resolver_changes2' into service_config

pull/8303/head
Mark D. Roth 9 years ago
commit bdd146d117
  1. 192
      doc/server_reflection_tutorial.md
  2. 2
      src/core/ext/client_config/client_channel.c
  3. 2
      src/core/ext/client_config/client_channel.h
  4. 2
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  5. 2
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  6. 25
      src/core/lib/security/credentials/plugin/plugin_credentials.c
  7. 4
      src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
  8. 102
      src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
  9. 31
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  10. 40
      src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
  11. 6
      src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
  12. 63
      test/cpp/end2end/end2end_test.cc

@ -0,0 +1,192 @@
# gRPC Server Reflection Tutorial
gRPC Server Reflection provides information about publicly-accessible gRPC
services on a server, and assists clients at runtime to construct RPC
requests and responses without precompiled service information. It is used by
gRPC CLI, which can be used to introspect server protos and send/receive test
RPCs.
## Enable Server Reflection
### Enable server reflection in C++ servers
C++ Server Reflection is an add-on library, `libgrpc++_reflction`. To enable C++
server reflection, you can link this library to your server binary.
Some platforms (e.g. Ubuntu 11.10 onwards) only link in libraries that directly
contain symbols used by the application. On these platforms, LD flag
`--no-as-needed` is needed for for dynamic linking and `--whole-archive` is
needed for for static linking.
This [Makefile](../examples/cpp/helloworld/Makefile#L37#L45) demonstrates
enabling c++ server reflection on Linux and MacOS.
## Test services using Server Reflection
After enabling Server Reflection in a server application, you can use gRPC CLI
to test its services.
Instructions on how to use gRPC CLI can be found at
[command_line_tool.md](command_line_tool.md), or using `grpc_cli help` command.
Here we use `examples/cpp/helloworld` as an example to show the use of gRPC
Server Reflection and gRPC CLI. First, we need to build gRPC CLI and setup an
example server with Server Reflection enabled.
- Setup an example server
Server Reflection has already been enabled in the
[Makefile](../examples/cpp/helloworld/Makefile) of the helloworld example. We
can simply make it and run the greeter_server.
```sh
$ make -C examples/cpp/helloworld
$ examples/cpp/helloworld/greeter_server &
```
- Build gRPC CLI
```sh
make grpc_cli
cd bins/opt
```
gRPC CLI binary `grpc_cli` can be found at `bins/opt/` folder. This tool is
still new and does not have a `make install` target yet.
### List services
`grpc_cli ls` command lists services and methods exposed at a given port
- List all the services exposed at a given port
```sh
$ grpc_cli ls localhost:50051
```
output:
```sh
helloworld.Greeter
grpc.reflection.v1alpha.ServerReflection
```
- List one service with details
`grpc_cli ls` command inspects a service given its full name (in the format of
\<package\>.\<service\>). It can print information with a long listing format
when `-l` flag is set. This flag can be used to get more details about a
service.
```sh
$ grpc_cli ls localhost:50051 helloworld.Greeter -l
```
output:
```sh
filename: helloworld.proto
package: helloworld;
service Greeter {
rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
}
```
### List methods
- List one method with details
`grpc_cli ls` command also inspects a method given its full name (in the
format of \<package\>.\<service\>.\<method\>).
```sh
$ grpc_cli ls localhost:50051 helloworld.Greeter.SayHello -l
```
output:
```sh
rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
```
### Inspect message types
We can use`grpc_cli type` command to inspect request/response types given the
full name of the type (in the format of \<package\>.\<type\>).
- Get information about the request type
```sh
$ grpc_cli type localhost:50051 helloworld.HelloRequest
```
output:
```sh
message HelloRequest {
optional string name = 1;
}
```
### Call a remote method
We can send RPCs to a server and get responses using `grpc_cli call` command.
- Call a unary method
```sh
$ grpc_cli call localhost:50051 SayHello "name: 'gRPC CLI'"
```
output:
```sh
message: "Hello gRPC CLI"
```
## Use Server Reflection in a C++ client
Server Reflection can be used by clients to get information about gRPC services
at runtime. We've provided a descriptor database called
[grpc::ProtoReflectionDescriptorDatabase](../test/cpp/util/proto_reflection_descriptor_database.h)
which implements the
[google::protobuf::DescriptorDatabase](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor_database#DescriptorDatabase)
interface. It manages the communication between clients and reflection services
and the storage of received information. Clients can use it as using a local
descriptor database.
- To use Server Reflection with grpc::ProtoReflectionDescriptorDatabase, first
initialize an instance with a grpc::Channel.
```c++
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(server_address, server_cred);
grpc::ProtoReflectionDescriptorDatabase reflection_db(channel);
```
- Then use this instance to feed a
[google::protobuf::DescriptorPool](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor#DescriptorPool).
```c++
google::protobuf::DescriptorPool desc_pool(&reflection_db);
```
- Example usage of this descriptor pool
* Get Service/method descriptors.
```c++
const google::protobuf::ServiceDescriptor* service_desc =
desc_pool->FindServiceByName("helloworld.Greeter");
const google::protobuf::MethodDescriptor* method_desc =
desc_pool->FindMethodByName("helloworld.Greeter.SayHello");
```
* Get message type descriptors.
```c++
const google::protobuf::Descriptor* request_desc =
desc_pool->FindMessageTypeByName("helloworld.HelloRequest");
```
* Feed [google::protobuf::DynamicMessageFactory](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.dynamic_message#DynamicMessageFactory).
```c++
google::protobuf::DynamicMessageFactory(&desc_pool);
```

@ -813,7 +813,7 @@ const grpc_channel_filter grpc_client_channel_filter = {
"client-channel",
};
void grpc_client_channel_set_resolver_and_client_channel_factory(
void grpc_client_channel_finish_initialization(
grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
grpc_resolver *resolver,
grpc_client_channel_factory *client_channel_factory) {

@ -49,7 +49,7 @@ extern const grpc_channel_filter grpc_client_channel_filter;
/* Post-construction initializer to give the client channel its resolver
and factory. */
void grpc_client_channel_set_resolver_and_client_channel_factory(
void grpc_client_channel_finish_initialization(
grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
grpc_resolver *resolver,
grpc_client_channel_factory *client_channel_factory);

@ -212,7 +212,7 @@ static grpc_channel *client_channel_factory_create_channel(
return NULL;
}
grpc_client_channel_set_resolver_and_client_channel_factory(
grpc_client_channel_finish_initialization(
exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel");

@ -273,7 +273,7 @@ static grpc_channel *client_channel_factory_create_channel(
grpc_resolver *resolver = grpc_resolver_create(target);
if (resolver != NULL) {
grpc_client_channel_set_resolver_and_client_channel_factory(
grpc_client_channel_finish_initialization(
exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create");
} else {

@ -37,6 +37,7 @@
#include "src/core/lib/surface/api_trace.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -71,17 +72,33 @@ static void plugin_md_request_metadata_ready(void *request,
error_details);
} else {
size_t i;
bool seen_illegal_header = false;
grpc_credentials_md *md_array = NULL;
if (num_md > 0) {
for (i = 0; i < num_md; i++) {
if (!grpc_header_key_is_legal(md[i].key, strlen(md[i].key))) {
gpr_log(GPR_ERROR, "Plugin added invalid metadata key: %s", md[i].key);
seen_illegal_header = true;
break;
} else if (!grpc_is_binary_header(md[i].key, strlen(md[i].key)) &&
!grpc_header_nonbin_value_is_legal(md[i].value,
md[i].value_length)) {
gpr_log(GPR_ERROR, "Plugin added invalid metadata value.");
seen_illegal_header = true;
break;
}
}
if (seen_illegal_header) {
r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
"Illegal metadata");
} else if (num_md > 0) {
md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
for (i = 0; i < num_md; i++) {
md_array[i].key = gpr_slice_from_copied_string(md[i].key);
md_array[i].value =
gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
}
}
r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK, NULL);
if (md_array != NULL) {
r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK,
NULL);
for (i = 0; i < num_md; i++) {
gpr_slice_unref(md_array[i].key);
gpr_slice_unref(md_array[i].value);

@ -33,6 +33,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@ -149,8 +150,7 @@ namespace Grpc.Core.Internal.Tests
var writeTask = responseStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// TODO(jtattermusch): should we throw a different exception type instead?
Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await writeTask);
Assert.ThrowsAsync(typeof(IOException), async () => await writeTask);
fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
AssertFinished(asyncCallServer, fakeCall, finishedTask);

@ -180,21 +180,74 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
public void ClientStreaming_WriteCompletionFailure()
public void ClientStreaming_WriteFailureThrowsRpcException()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// TODO: maybe IOException or waiting for RPCException is more appropriate here.
Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await writeTask);
// The write will wait for call to finish to receive the status code.
Assert.IsFalse(writeTask.IsCompleted);
fakeCall.UnaryResponseClientHandler(true,
CreateClientSideStatus(StatusCode.Internal),
null,
new Metadata());
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
}
[Test]
public void ClientStreaming_WriteFailureThrowsRpcException2()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.UnaryResponseClientHandler(true,
CreateClientSideStatus(StatusCode.Internal),
null,
new Metadata());
fakeCall.SendCompletionHandler(false);
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
}
[Test]
public void ClientStreaming_WriteFailureThrowsRpcException3()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// Until the delayed write completion has been triggered,
// we still act as if there was an active write.
Assert.Throws(typeof(InvalidOperationException), () => requestStream.WriteAsync("request2"));
fakeCall.UnaryResponseClientHandler(true,
CreateClientSideStatus(StatusCode.Internal),
null,
new Metadata());
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
// Following attempts to write keep delivering the same status
var ex2 = Assert.ThrowsAsync<RpcException>(async () => await requestStream.WriteAsync("after call has finished"));
Assert.AreEqual(StatusCode.Internal, ex2.Status.StatusCode);
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
}
@ -415,6 +468,49 @@ namespace Grpc.Core.Internal.Tests
Assert.DoesNotThrowAsync(async () => await requestStream.CompleteAsync());
}
[Test]
public void DuplexStreaming_WriteFailureThrowsRpcException()
{
asyncCall.StartDuplexStreamingCall();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var responseStream = new ClientResponseStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// The write will wait for call to finish to receive the status code.
Assert.IsFalse(writeTask.IsCompleted);
var readTask = responseStream.MoveNext();
fakeCall.ReceivedMessageHandler(true, null);
fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.PermissionDenied));
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.PermissionDenied, ex.Status.StatusCode);
AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.PermissionDenied);
}
[Test]
public void DuplexStreaming_WriteFailureThrowsRpcException2()
{
asyncCall.StartDuplexStreamingCall();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var responseStream = new ClientResponseStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
var readTask = responseStream.MoveNext();
fakeCall.ReceivedMessageHandler(true, null);
fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.PermissionDenied));
fakeCall.SendCompletionHandler(false);
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.PermissionDenied, ex.Status.StatusCode);
AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.PermissionDenied);
}
[Test]
public void DuplexStreaming_WriteAfterCancellationRequestThrowsTaskCanceledException()
{

@ -341,6 +341,11 @@ namespace Grpc.Core.Internal
get { return true; }
}
protected override Exception GetRpcExceptionClientOnly()
{
return new RpcException(finishedStatus.Value.Status);
}
protected override Task CheckSendAllowedOrEarlyResult()
{
var earlyResult = CheckSendPreconditionsClientSide();
@ -452,6 +457,7 @@ namespace Grpc.Core.Internal
using (Profilers.ForCurrentThread().NewScope("AsyncCall.HandleUnaryResponse"))
{
TaskCompletionSource<object> delayedStreamingWriteTcs = null;
TResponse msg = default(TResponse);
var deserializeException = TryDeserialize(receivedMessage, out msg);
@ -465,13 +471,23 @@ namespace Grpc.Core.Internal
}
finishedStatus = receivedStatus;
if (isStreamingWriteCompletionDelayed)
{
delayedStreamingWriteTcs = streamingWriteTcs;
streamingWriteTcs = null;
}
ReleaseResourcesIfPossible();
}
responseHeadersTcs.SetResult(responseHeaders);
var status = receivedStatus.Status;
if (delayedStreamingWriteTcs != null)
{
delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly());
}
var status = receivedStatus.Status;
if (status.StatusCode != StatusCode.OK)
{
unaryResponseTcs.SetException(new RpcException(status));
@ -490,16 +506,27 @@ namespace Grpc.Core.Internal
// NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT,
// success will be always set to true.
TaskCompletionSource<object> delayedStreamingWriteTcs = null;
lock (myLock)
{
finished = true;
finishedStatus = receivedStatus;
if (isStreamingWriteCompletionDelayed)
{
delayedStreamingWriteTcs = streamingWriteTcs;
streamingWriteTcs = null;
}
ReleaseResourcesIfPossible();
}
var status = receivedStatus.Status;
if (delayedStreamingWriteTcs != null)
{
delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly());
}
var status = receivedStatus.Status;
if (status.StatusCode != StatusCode.OK)
{
streamingCallFinishedTcs.SetException(new RpcException(status));

@ -69,6 +69,7 @@ namespace Grpc.Core.Internal
protected TaskCompletionSource<TRead> streamingReadTcs; // Completion of a pending streaming read if not null.
protected TaskCompletionSource<object> streamingWriteTcs; // Completion of a pending streaming write or send close from client if not null.
protected TaskCompletionSource<object> sendStatusFromServerTcs;
protected bool isStreamingWriteCompletionDelayed; // Only used for the client side.
protected bool readingDone; // True if last read (i.e. read with null payload) was already received.
protected bool halfcloseRequested; // True if send close have been initiated.
@ -200,6 +201,12 @@ namespace Grpc.Core.Internal
get;
}
/// <summary>
/// Returns an exception to throw for a failed send operation.
/// It is only allowed to call this method for a call that has already finished.
/// </summary>
protected abstract Exception GetRpcExceptionClientOnly();
private void ReleaseResources()
{
if (call != null)
@ -252,18 +259,43 @@ namespace Grpc.Core.Internal
/// </summary>
protected void HandleSendFinished(bool success)
{
bool delayCompletion = false;
TaskCompletionSource<object> origTcs = null;
lock (myLock)
{
origTcs = streamingWriteTcs;
streamingWriteTcs = null;
if (!success && !finished && IsClient) {
// We should be setting this only once per call, following writes will be short circuited
// because they cannot start until the entire call finishes.
GrpcPreconditions.CheckState(!isStreamingWriteCompletionDelayed);
// leave streamingWriteTcs set, it will be completed once call finished.
isStreamingWriteCompletionDelayed = true;
delayCompletion = true;
}
else
{
origTcs = streamingWriteTcs;
streamingWriteTcs = null;
}
ReleaseResourcesIfPossible();
}
if (!success)
{
origTcs.SetException(new InvalidOperationException("Send failed"));
if (!delayCompletion)
{
if (IsClient)
{
GrpcPreconditions.CheckState(finished); // implied by !success && !delayCompletion && IsClient
origTcs.SetException(GetRpcExceptionClientOnly());
}
else
{
origTcs.SetException (new IOException("Error sending from server."));
}
}
// if delayCompletion == true, postpone SetException until call finishes.
}
else
{
@ -283,7 +315,7 @@ namespace Grpc.Core.Internal
if (!success)
{
sendStatusFromServerTcs.SetException(new InvalidOperationException("Error sending status from server."));
sendStatusFromServerTcs.SetException(new IOException("Error sending status from server."));
}
else
{

@ -33,6 +33,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
@ -193,6 +194,11 @@ namespace Grpc.Core.Internal
get { return false; }
}
protected override Exception GetRpcExceptionClientOnly()
{
throw new InvalidOperationException("Call be only called for client calls");
}
protected override void OnAfterReleaseResources()
{
server.RemoveCallReference(this);

@ -80,11 +80,14 @@ const char kTestCredsPluginErrorMsg[] = "Could not find plugin metadata.";
class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
public:
static const char kMetadataKey[];
static const char kGoodMetadataKey[];
static const char kBadMetadataKey[];
TestMetadataCredentialsPlugin(grpc::string_ref metadata_value,
TestMetadataCredentialsPlugin(grpc::string_ref metadata_key,
grpc::string_ref metadata_value,
bool is_blocking, bool is_successful)
: metadata_value_(metadata_value.data(), metadata_value.length()),
: metadata_key_(metadata_key.data(), metadata_key.length()),
metadata_value_(metadata_value.data(), metadata_value.length()),
is_blocking_(is_blocking),
is_successful_(is_successful) {}
@ -99,7 +102,7 @@ class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
EXPECT_TRUE(channel_auth_context.IsPeerAuthenticated());
EXPECT_TRUE(metadata != nullptr);
if (is_successful_) {
metadata->insert(std::make_pair(kMetadataKey, metadata_value_));
metadata->insert(std::make_pair(metadata_key_, metadata_value_));
return Status::OK;
} else {
return Status(StatusCode::NOT_FOUND, kTestCredsPluginErrorMsg);
@ -107,12 +110,16 @@ class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
}
private:
grpc::string metadata_key_;
grpc::string metadata_value_;
bool is_blocking_;
bool is_successful_;
};
const char TestMetadataCredentialsPlugin::kMetadataKey[] = "TestPluginMetadata";
const char TestMetadataCredentialsPlugin::kBadMetadataKey[] =
"TestPluginMetadata";
const char TestMetadataCredentialsPlugin::kGoodMetadataKey[] =
"test-plugin-metadata";
class TestAuthMetadataProcessor : public AuthMetadataProcessor {
public:
@ -123,13 +130,17 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor {
std::shared_ptr<CallCredentials> GetCompatibleClientCreds() {
return MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(kGoodGuy, is_blocking_, true)));
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey, kGoodGuy,
is_blocking_, true)));
}
std::shared_ptr<CallCredentials> GetIncompatibleClientCreds() {
return MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin("Mr Hyde", is_blocking_, true)));
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey, "Mr Hyde",
is_blocking_, true)));
}
// Interface implementation
@ -142,7 +153,7 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor {
EXPECT_TRUE(context != nullptr);
EXPECT_TRUE(response_metadata != nullptr);
auto auth_md =
auth_metadata.find(TestMetadataCredentialsPlugin::kMetadataKey);
auth_metadata.find(TestMetadataCredentialsPlugin::kGoodMetadataKey);
EXPECT_NE(auth_md, auth_metadata.end());
string_ref auth_md_value = auth_md->second;
if (auth_md_value == kGoodGuy) {
@ -1322,6 +1333,40 @@ TEST_P(SecureEnd2endTest, OverridePerCallCredentials) {
EXPECT_TRUE(s.ok());
}
TEST_P(SecureEnd2endTest, AuthMetadataPluginKeyFailure) {
ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kBadMetadataKey,
"Does not matter, will fail the key is invalid.", false, true))));
request.set_message("Hello");
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
TEST_P(SecureEnd2endTest, AuthMetadataPluginValueFailure) {
ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey,
"With illegal \n value.", false, true))));
request.set_message("Hello");
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) {
ResetStub();
EchoRequest request;
@ -1330,6 +1375,7 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) {
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey,
"Does not matter, will fail anyway (see 3rd param)", false,
false))));
request.set_message("Hello");
@ -1388,6 +1434,7 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) {
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey,
"Does not matter, will fail anyway (see 3rd param)", true,
false))));
request.set_message("Hello");

Loading…
Cancel
Save