From 7f43eaf365334f2c394e5e5c2b6e0777c72beaaa Mon Sep 17 00:00:00 2001 From: David Klempner Date: Wed, 18 Feb 2015 17:00:31 -0800 Subject: [PATCH 01/27] Ensure there is no concurrent poller for unary->multipoll The race here is: Initially unary poller has one FD, FD_1 Thread 1 adds FD_2, promoting to multipoll, entailing epoll_ctl on FD_1 and FD_2. Concurrently, Thread 2 returns from unary poll and executes one of FD_1's callbacks, which ultimately leads to a close(FD_1) which races with the epoll_ctl by thread 1. The solution is to ensure that we don't concurrently poll and promote, which requires a bit of extra care. --- src/core/iomgr/pollset_posix.c | 65 +++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 05b78adeb61..00a22e7ae37 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -201,11 +201,43 @@ static void become_empty_pollset(grpc_pollset *pollset) { * via poll() */ -static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { + +typedef struct grpc_unary_promote_args { + const grpc_pollset_vtable *original_vtable; + grpc_pollset *pollset; + grpc_fd *fd; +} grpc_unary_promote_args; + +static void unary_poll_do_promote(void *args, int success) { + grpc_unary_promote_args *up_args = args; + const grpc_pollset_vtable *original_vtable = up_args->original_vtable; + grpc_pollset *pollset = up_args->pollset; + grpc_fd *fd = up_args->fd; grpc_fd *fds[2]; + gpr_free(up_args); + + gpr_mu_lock(&pollset->mu); + /* First we need to ensure that nobody is polling concurrently */ + while (pollset->counter != 0 && pollset->vtable == original_vtable) { + grpc_pollset_kick(pollset); + gpr_cv_wait(&pollset->cv, &pollset->mu, gpr_inf_future); + } + /* At this point the pollset may no longer be a unary poller. In that case + * we should just call the right add function and be done. */ + /* TODO(klempner): If we're not careful this could cause infinite recursion. + * That's not a problem for now because empty_pollset has a trivial poller + * and we don't have any mechanism to unbecome multipoller. */ + if (pollset->vtable != original_vtable) { + pollset->vtable->add_fd(pollset, fd); + gpr_cv_broadcast(&pollset->cv); + gpr_mu_unlock(&pollset->mu); + return; + } + if (fd == pollset->data.ptr) return; fds[0] = pollset->data.ptr; fds[1] = fd; + if (!grpc_fd_is_orphaned(fds[0])) { grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds)); grpc_fd_unref(fds[0]); @@ -216,6 +248,37 @@ static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { pollset->data.ptr = fd; grpc_fd_ref(fd); } + + gpr_cv_broadcast(&pollset->cv); + gpr_mu_unlock(&pollset->mu); + + /* Matching ref in unary_poll_pollset_add_fd */ + grpc_fd_unref(fd); +} + +static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { + grpc_unary_promote_args *up_args; + if (fd == pollset->data.ptr) return; + + if (grpc_fd_is_orphaned(pollset->data.ptr)) { + /* old fd is orphaned and we haven't cleaned it up until now, so remain a + * unary poller */ + grpc_fd_unref(pollset->data.ptr); + pollset->data.ptr = fd; + grpc_fd_ref(fd); + return; + } + + /* Now we need to promote. This needs to happen when we're not polling. Since + * this may be called from poll, the wait needs to happen asynchronously. */ + grpc_fd_ref(fd); + up_args = gpr_malloc(sizeof(*up_args)); + up_args->pollset = pollset; + up_args->fd = fd; + up_args->original_vtable = pollset->vtable; + grpc_iomgr_add_callback(unary_poll_do_promote, up_args); + + grpc_pollset_kick(pollset); } static void unary_poll_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) { From 50faa8f78b210a9922644f624d3c0a36b4e2a2db Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sat, 21 Feb 2015 17:51:52 -0800 Subject: [PATCH 02/27] Added support for true synchronous unary call and added some performance tests. --- .../Grpc.Core.Tests/ClientServerTest.cs | 11 +- .../Grpc.Core.Tests/Grpc.Core.Tests.csproj | 1 + src/csharp/Grpc.Core.Tests/PInvokeTest.cs | 139 ++++++++++++++++++ src/csharp/Grpc.Core/Calls.cs | 27 ++-- src/csharp/Grpc.Core/Grpc.Core.csproj | 1 + src/csharp/Grpc.Core/Internal/AsyncCall.cs | 25 ++++ .../Grpc.Core/Internal/CallSafeHandle.cs | 10 ++ src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs | 68 +++++++++ src/csharp/Grpc.IntegrationTesting/Client.cs | 11 ++ src/csharp/ext/grpc_csharp_ext.c | 25 ++++ 10 files changed, 297 insertions(+), 21 deletions(-) create mode 100644 src/csharp/Grpc.Core.Tests/PInvokeTest.cs create mode 100644 src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs index 7e564a2fba5..39be35c2190 100644 --- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs +++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs @@ -101,15 +101,8 @@ namespace Grpc.Core.Tests using (Channel channel = new Channel(host + ":" + port)) { var call = new Call(unaryEchoStringMethod, channel); - - var stopwatch = new Stopwatch(); - stopwatch.Start(); - for (int i = 0; i < 1000; i++) - { - Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); - } - stopwatch.Stop(); - Console.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds + "ms"); + BenchmarkUtil.RunBenchmark(100, 1000, + () => { Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); }); } server.ShutdownAsync().Wait(); diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj index 687be3c0cb6..a365320f052 100644 --- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj +++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj @@ -41,6 +41,7 @@ + diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs new file mode 100644 index 00000000000..b78609ccf08 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs @@ -0,0 +1,139 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; +using System.Runtime.InteropServices; + +namespace Grpc.Core.Tests +{ + public class PInvokeTest + { + int counter; + + [DllImport("grpc_csharp_ext.dll")] + static extern GRPCCallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); + + [DllImport("grpc_csharp_ext.dll")] + static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [TestFixtureSetUp] + public void Init() + { + GrpcEnvironment.Initialize(); + } + + [TestFixtureTearDown] + public void Cleanup() + { + GrpcEnvironment.Shutdown(); + } + + [Test] + public void CompletionQueueCreateDestroyBenchmark() + { + BenchmarkUtil.RunBenchmark( + 100000, 1000000, + () => { + CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create(); + cq.Dispose(); + } + ); + } + + + /// + /// Approximate results: + /// (mono ~80ns) + /// + [Test] + public void NativeCallbackBenchmark() + { + CompletionCallbackDelegate handler = Handler; + + counter = 0; + BenchmarkUtil.RunBenchmark( + 1000000, 10000000, + () => { + grpcsharp_test_callback(handler); + } + ); + Assert.AreNotEqual(0, counter); + } + + /// + /// Creating a new native-to-managed callback has significant overhead + /// compared to using an existing one. We need to be aware of this. + /// (~50us on mono) + /// + [Test] + public void NewNativeCallbackBenchmark() + { + counter = 0; + BenchmarkUtil.RunBenchmark( + 10000, 10000, + () => { + grpcsharp_test_callback(new CompletionCallbackDelegate(Handler)); + } + ); + Assert.AreNotEqual(0, counter); + } + + /// + /// Tests overhead of a simple PInvoke call. + /// + [Test] + public void NopPInvokeBenchmark() + { + CompletionCallbackDelegate handler = Handler; + + BenchmarkUtil.RunBenchmark( + 1000000, 100000000, + () => { + grpcsharp_test_nop(IntPtr.Zero); + } + ); + } + + private void Handler(GRPCOpError op, IntPtr ptr) { + counter ++; + } + } +} + diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs index b67332676ac..c0973234e2a 100644 --- a/src/csharp/Grpc.Core/Calls.cs +++ b/src/csharp/Grpc.Core/Calls.cs @@ -47,19 +47,22 @@ namespace Grpc.Core { public static TResponse BlockingUnaryCall(Call call, TRequest req, CancellationToken token) { + var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer); + return asyncCall.UnaryCall(call.Channel, call.MethodName, req); + //TODO: implement this in real synchronous style. - try { - return AsyncUnaryCall(call, req, token).Result; - } catch(AggregateException ae) { - foreach (var e in ae.InnerExceptions) - { - if (e is RpcException) - { - throw e; - } - } - throw; - } +// try { +// return AsyncUnaryCall(call, req, token).Result; +// } catch(AggregateException ae) { +// foreach (var e in ae.InnerExceptions) +// { +// if (e is RpcException) +// { +// throw e; +// } +// } +// throw; +// } } public static async Task AsyncUnaryCall(Call call, TRequest req, CancellationToken token) diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 4ad32e10e43..664d534dc29 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -62,6 +62,7 @@ + diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index 5e96092e270..7c40661cf4b 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -112,6 +112,31 @@ namespace Grpc.Core.Internal InitializeInternal(call, true); } + public TRead UnaryCall(Channel channel, String methodName, TWrite msg) + { + using(CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create()) + { + // TODO: handle serialization error... + byte[] payload = serializer(msg); + + unaryResponseTcs = new TaskCompletionSource(); + + lock (myLock) + { + Initialize(channel, cq, methodName); + started = true; + halfcloseRequested = true; + readingDone = true; + } + call.BlockingUnary(cq, payload, unaryResponseHandler); + + // task should be finished once BlockingUnary returns. + return unaryResponseTcs.Task.Result; + + // TODO: unwrap aggregate exception... + } + } + public Task UnaryCallAsync(TWrite msg) { lock (myLock) diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index 659a383b4bd..1c0bc98f062 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -62,6 +62,11 @@ namespace Grpc.Core.Internal [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, byte[] send_buffer, UIntPtr send_buffer_len); + [DllImport("grpc_csharp_ext.dll")] + static extern void grpcsharp_call_blocking_unary(CallSafeHandle call, CompletionQueueSafeHandle dedicatedCq, + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, + byte[] send_buffer, UIntPtr send_buffer_len); + [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call, [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); @@ -113,6 +118,11 @@ namespace Grpc.Core.Internal AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong) payload.Length))); } + public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback) + { + grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong) payload.Length)); + } + public void StartClientStreaming(CompletionCallbackDelegate callback) { AssertCallOk(grpcsharp_call_start_client_streaming(this, callback)); diff --git a/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs b/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs new file mode 100644 index 00000000000..3f0dae84cf8 --- /dev/null +++ b/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs @@ -0,0 +1,68 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Diagnostics; + +namespace Grpc.Core.Utils +{ + public static class BenchmarkUtil + { + /// + /// Runs a simple benchmark preceded by warmup phase. + /// + public static void RunBenchmark(int warmupIterations, int benchmarkIterations, Action action) + { + Console.WriteLine("Warmup iterations: " + warmupIterations); + for (int i = 0; i < warmupIterations; i++) + { + action(); + } + + Console.WriteLine("Benchmark iterations: " + benchmarkIterations); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + for (int i = 0; i < benchmarkIterations; i++) + { + action(); + } + stopwatch.Stop(); + Console.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds + "ms"); + Console.WriteLine("Ops per second: " + (int) ((double) benchmarkIterations * 1000 / stopwatch.ElapsedMilliseconds)); + } + } +} + diff --git a/src/csharp/Grpc.IntegrationTesting/Client.cs b/src/csharp/Grpc.IntegrationTesting/Client.cs index bb650a112de..0c70744cea5 100644 --- a/src/csharp/Grpc.IntegrationTesting/Client.cs +++ b/src/csharp/Grpc.IntegrationTesting/Client.cs @@ -33,7 +33,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Text.RegularExpressions; +using System.Threading.Tasks; using Google.ProtocolBuffers; using Grpc.Core; using Grpc.Core.Utils; @@ -128,6 +130,9 @@ namespace Grpc.IntegrationTesting case "empty_stream": RunEmptyStream(client); break; + case "benchmark_empty_unary": + RunBenchmarkEmptyUnary(client); + break; default: throw new ArgumentException("Unknown test case " + testCase); } @@ -267,6 +272,12 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } + // This is not an official interop test, but it's useful. + private void RunBenchmarkEmptyUnary(TestServiceGrpc.ITestServiceClient client) + { + BenchmarkUtil.RunBenchmark(10000, 10000, + () => { client.EmptyCall(Empty.DefaultInstance);}); + } private Payload CreateZerosPayload(int size) { return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build(); diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 5f9f22cab10..18e0431e3b2 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -343,6 +343,18 @@ grpcsharp_call_start_unary(grpc_call *call, callback_funcptr callback, return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx); } +/* Synchronous unary call */ +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_call_blocking_unary(grpc_call *call, grpc_completion_queue *dedicated_cq, callback_funcptr callback, + const char *send_buffer, size_t send_buffer_len) { + GPR_ASSERT(grpcsharp_call_start_unary(call, callback, send_buffer, send_buffer_len) == GRPC_CALL_OK); + + /* TODO: we would like to use pluck, but we don't know the tag */ + GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) == GRPC_OP_COMPLETE); + grpc_completion_queue_shutdown(dedicated_cq); + GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) == GRPC_QUEUE_SHUTDOWN); +} + GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(grpc_call *call, callback_funcptr callback) { @@ -566,3 +578,16 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq, server, &(ctx->server_rpc_new.call), &(ctx->server_rpc_new.call_details), &(ctx->server_rpc_new.request_metadata), cq, ctx); } + + +/* For testing */ +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_test_callback(callback_funcptr callback) { + callback(GRPC_OP_OK, NULL); +} + +/* For testing */ +GPR_EXPORT void *GPR_CALLTYPE +grpcsharp_test_nop(void *ptr) { + return ptr; +} From 4d703268adb6769b835070d3222a39c7fa399303 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 23 Feb 2015 11:33:44 -0800 Subject: [PATCH 03/27] Fix exception unwrapping for unary call --- src/csharp/Grpc.Core/Calls.cs | 14 ----- src/csharp/Grpc.Core/Grpc.Core.csproj | 1 + src/csharp/Grpc.Core/Internal/AsyncCall.cs | 14 +++-- src/csharp/Grpc.Core/RpcException.cs | 3 +- src/csharp/Grpc.Core/ServerCallHandler.cs | 2 + src/csharp/Grpc.Core/Utils/ExceptionHelper.cs | 57 +++++++++++++++++++ 6 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 src/csharp/Grpc.Core/Utils/ExceptionHelper.cs diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs index c0973234e2a..ee2208e5c25 100644 --- a/src/csharp/Grpc.Core/Calls.cs +++ b/src/csharp/Grpc.Core/Calls.cs @@ -49,20 +49,6 @@ namespace Grpc.Core { var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer); return asyncCall.UnaryCall(call.Channel, call.MethodName, req); - - //TODO: implement this in real synchronous style. -// try { -// return AsyncUnaryCall(call, req, token).Result; -// } catch(AggregateException ae) { -// foreach (var e in ae.InnerExceptions) -// { -// if (e is RpcException) -// { -// throw e; -// } -// } -// throw; -// } } public static async Task AsyncUnaryCall(Call call, TRequest req, CancellationToken token) diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 664d534dc29..135ce26cbd2 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -63,6 +63,7 @@ + diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index 7c40661cf4b..dadc9ab76cf 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -38,6 +38,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Grpc.Core.Internal; +using Grpc.Core.Utils; namespace Grpc.Core.Internal { @@ -130,10 +131,15 @@ namespace Grpc.Core.Internal } call.BlockingUnary(cq, payload, unaryResponseHandler); - // task should be finished once BlockingUnary returns. - return unaryResponseTcs.Task.Result; - - // TODO: unwrap aggregate exception... + try + { + // Once the blocking call returns, the result should be available synchronously. + return unaryResponseTcs.Task.Result; + } + catch (AggregateException ae) + { + throw ExceptionHelper.UnwrapRpcException(ae); + } } } diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core/RpcException.cs index 5a9d0039bc9..e1cf64ca56a 100644 --- a/src/csharp/Grpc.Core/RpcException.cs +++ b/src/csharp/Grpc.Core/RpcException.cs @@ -49,7 +49,8 @@ namespace Grpc.Core this.status = status; } - public Status Status { + public Status Status + { get { return status; diff --git a/src/csharp/Grpc.Core/ServerCallHandler.cs b/src/csharp/Grpc.Core/ServerCallHandler.cs index 1296947f34d..289f97aecee 100644 --- a/src/csharp/Grpc.Core/ServerCallHandler.cs +++ b/src/csharp/Grpc.Core/ServerCallHandler.cs @@ -111,6 +111,8 @@ namespace Grpc.Core var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(new NullObserver()); + // TODO: this makes the call finish before all reads can be done which causes trouble + // in AsyncCall.HandleReadFinished callback. Revisit this. asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, "No such method.")).Wait(); finishedTask.Wait(); diff --git a/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs b/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs new file mode 100644 index 00000000000..18702e1cc42 --- /dev/null +++ b/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs @@ -0,0 +1,57 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; + +namespace Grpc.Core.Utils +{ + public static class ExceptionHelper + { + /// + /// If inner exceptions contain RpcException, rethrows it. + /// Otherwise, rethrows the original aggregate exception. + /// Always throws, the exception return type is here only to make the. + /// + public static Exception UnwrapRpcException(AggregateException ae) { + foreach (var e in ae.InnerExceptions) + { + if (e is RpcException) + { + throw e; + } + } + throw ae; + } + } +} + From 597a4f2273f9dda0dbac45b021706ce8b715f93c Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Mon, 23 Feb 2015 15:57:14 -0800 Subject: [PATCH 04/27] Verifying the peer name on the X509 Certs correctly. - The SANs take precedence over the CN. - The CN is only checked if there are no SANs. - Fixing the tests as the test cert did not list *.test.google.com in the SANs. Will fix the test cert another time... --- src/core/tsi/ssl_transport_security.c | 32 ++++++++++++------- src/node/test/interop_sanity_test.js | 2 +- src/php/tests/interop/interop_client.php | 2 +- .../tests/unit_tests/SecureEndToEndTest.php | 2 +- src/ruby/bin/interop/interop_client.rb | 2 +- src/ruby/bin/math_client.rb | 2 +- src/ruby/bin/noproto_client.rb | 2 +- src/ruby/spec/client_server_spec.rb | 2 +- src/ruby/spec/generic/client_stub_spec.rb | 2 +- test/core/end2end/dualstack_socket_test.c | 4 +-- .../fixtures/chttp2_simple_ssl_fullstack.c | 2 +- .../chttp2_simple_ssl_with_oauth2_fullstack.c | 2 +- test/core/end2end/tests/cancel_after_accept.c | 2 +- .../cancel_after_accept_and_writes_closed.c | 4 +-- ...el_after_accept_and_writes_closed_legacy.c | 4 +-- .../tests/cancel_after_accept_legacy.c | 4 +-- test/core/end2end/tests/cancel_after_invoke.c | 2 +- .../tests/cancel_after_invoke_legacy.c | 2 +- .../core/end2end/tests/cancel_before_invoke.c | 2 +- .../tests/cancel_before_invoke_legacy.c | 2 +- test/core/end2end/tests/cancel_in_a_vacuum.c | 2 +- .../end2end/tests/cancel_in_a_vacuum_legacy.c | 2 +- .../end2end/tests/census_simple_request.c | 4 +-- .../tests/census_simple_request_legacy.c | 4 +-- test/core/end2end/tests/disappearing_server.c | 4 +-- .../tests/disappearing_server_legacy.c | 4 +-- ..._server_shutdown_finishes_inflight_calls.c | 4 +-- ..._shutdown_finishes_inflight_calls_legacy.c | 4 +-- test/core/end2end/tests/empty_batch.c | 2 +- .../end2end/tests/graceful_server_shutdown.c | 4 +-- .../tests/graceful_server_shutdown_legacy.c | 4 +-- .../core/end2end/tests/invoke_large_request.c | 4 +-- .../tests/invoke_large_request_legacy.c | 4 +-- .../end2end/tests/max_concurrent_streams.c | 12 +++---- .../tests/max_concurrent_streams_legacy.c | 12 +++---- test/core/end2end/tests/ping_pong_streaming.c | 4 +-- .../tests/ping_pong_streaming_legacy.c | 4 +-- ...esponse_with_binary_metadata_and_payload.c | 4 +-- ..._with_binary_metadata_and_payload_legacy.c | 4 +-- ...quest_response_with_metadata_and_payload.c | 4 +-- ...esponse_with_metadata_and_payload_legacy.c | 4 +-- .../tests/request_response_with_payload.c | 4 +-- .../request_response_with_payload_legacy.c | 4 +-- ...ponse_with_trailing_metadata_and_payload.c | 4 +-- ...ith_trailing_metadata_and_payload_legacy.c | 4 +-- .../tests/request_with_large_metadata.c | 4 +-- .../request_with_large_metadata_legacy.c | 4 +-- .../core/end2end/tests/request_with_payload.c | 4 +-- .../tests/request_with_payload_legacy.c | 4 +-- .../end2end/tests/simple_delayed_request.c | 4 +-- .../tests/simple_delayed_request_legacy.c | 4 +-- test/core/end2end/tests/simple_request.c | 4 +-- .../end2end/tests/simple_request_legacy.c | 8 ++--- test/core/end2end/tests/thread_stress.c | 2 +- .../core/end2end/tests/thread_stress_legacy.c | 2 +- .../writes_done_hangs_with_pending_read.c | 4 +-- ...ites_done_hangs_with_pending_read_legacy.c | 4 +-- test/cpp/interop/client.cc | 2 +- test/cpp/util/create_test_channel.cc | 2 +- 59 files changed, 124 insertions(+), 116 deletions(-) diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c index 92fcb96dd23..f1a52746d24 100644 --- a/src/core/tsi/ssl_transport_security.c +++ b/src/core/tsi/ssl_transport_security.c @@ -1282,25 +1282,18 @@ tsi_result tsi_create_ssl_server_handshaker_factory( int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) { size_t i = 0; - const tsi_peer_property* property = tsi_peer_get_property_by_name( - peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); - if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_STRING) { - gpr_log(GPR_ERROR, "Invalid x509 subject common name property."); - return 0; - } - if (does_entry_match_name(property->value.string.data, - property->value.string.length, name)) { - return 1; - } + size_t san_count = 0; - property = tsi_peer_get_property_by_name( + /* Check the SAN first. */ + const tsi_peer_property* property = tsi_peer_get_property_by_name( peer, TSI_X509_SUBJECT_ALTERNATIVE_NAMES_PEER_PROPERTY); if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_LIST) { gpr_log(GPR_ERROR, "Invalid x509 subject alternative names property."); return 0; } - for (i = 0; i < property->value.list.child_count; i++) { + san_count = property->value.list.child_count; + for (i = 0; i < san_count; i++) { const tsi_peer_property* alt_name_property = &property->value.list.children[i]; if (alt_name_property->type != TSI_PEER_PROPERTY_TYPE_STRING) { @@ -1312,5 +1305,20 @@ int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) { return 1; } } + + /* If there's no SAN, try the CN. */ + if (san_count == 0) { + property = tsi_peer_get_property_by_name( + peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); + if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_STRING) { + gpr_log(GPR_ERROR, "Invalid x509 subject common name property."); + return 0; + } + if (does_entry_match_name(property->value.string.data, + property->value.string.length, name)) { + return 1; + } + } + return 0; /* Not found. */ } diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js index 8dc933eac56..6b3aa3dd842 100644 --- a/src/node/test/interop_sanity_test.js +++ b/src/node/test/interop_sanity_test.js @@ -40,7 +40,7 @@ var server; var port; -var name_override = 'foo.test.google.com'; +var name_override = 'foo.test.google.fr'; describe('Interop tests', function() { before(function(done) { diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index 5a09fc7d78c..82ca4381690 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -215,7 +215,7 @@ $stub = new grpc\testing\TestServiceClient( new Grpc\BaseStub( $server_address, [ - 'grpc.ssl_target_name_override' => 'foo.test.google.com', + 'grpc.ssl_target_name_override' => 'foo.test.google.fr', 'credentials' => $credentials ])); diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php index b19ac80ddd4..c23dd791acf 100755 --- a/src/php/tests/unit_tests/SecureEndToEndTest.php +++ b/src/php/tests/unit_tests/SecureEndToEndTest.php @@ -47,7 +47,7 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase{ $this->channel = new Grpc\Channel( 'localhost:' . $port, [ - 'grpc.ssl_target_name_override' => 'foo.test.google.com', + 'grpc.ssl_target_name_override' => 'foo.test.google.fr', 'credentials' => $credentials ]); } diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb index 76402b7c894..380ceb11df0 100755 --- a/src/ruby/bin/interop/interop_client.rb +++ b/src/ruby/bin/interop/interop_client.rb @@ -291,7 +291,7 @@ Args = Struct.new(:default_service_account, :host, :host_override, # validates the the command line options, returning them as a Hash. def parse_args args = Args.new - args.host_override = 'foo.test.google.com' + args.host_override = 'foo.test.google.fr' OptionParser.new do |opts| opts.on('--oauth_scope scope', 'Scope for OAuth tokens') { |v| args['oauth_scope'] = v } diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb index cb085d4d429..db254efb002 100755 --- a/src/ruby/bin/math_client.rb +++ b/src/ruby/bin/math_client.rb @@ -127,7 +127,7 @@ def main if options['secure'] stub_opts = { :creds => test_creds, - GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com' + GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr' } p stub_opts p options['host'] diff --git a/src/ruby/bin/noproto_client.rb b/src/ruby/bin/noproto_client.rb index 44710520d29..f3fd1103478 100755 --- a/src/ruby/bin/noproto_client.rb +++ b/src/ruby/bin/noproto_client.rb @@ -89,7 +89,7 @@ def main if options['secure'] stub_opts = { :creds => test_creds, - GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com' + GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr' } p stub_opts p options['host'] diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb index 52c985786a8..030ff328f21 100644 --- a/src/ruby/spec/client_server_spec.rb +++ b/src/ruby/spec/client_server_spec.rb @@ -353,7 +353,7 @@ describe 'the secure http client/server' do @server = GRPC::Core::Server.new(@server_queue, nil, server_creds) server_port = @server.add_http2_port(server_host, true) @server.start - args = { Channel::SSL_TARGET => 'foo.test.google.com' } + args = { Channel::SSL_TARGET => 'foo.test.google.fr' } @ch = Channel.new("0.0.0.0:#{server_port}", args, GRPC::Core::Credentials.new(certs[0], nil, nil)) end diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb index 297a1338313..adf354f4eef 100644 --- a/src/ruby/spec/generic/client_stub_spec.rb +++ b/src/ruby/spec/generic/client_stub_spec.rb @@ -116,7 +116,7 @@ describe 'ClientStub' do host = FAKE_HOST blk = proc do opts = { - GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com', + GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr', a_channel_arg: 'an_arg', creds: GRPC::Core::Credentials.new(certs[0], nil, nil) } diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index 2c4c3b77462..62676d01e09 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -112,7 +112,7 @@ void test_connect(const char *server_host, const char *client_host, int port, } /* Send a trivial request. */ - c = grpc_channel_create_call_old(client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -126,7 +126,7 @@ void test_connect(const char *server_host, const char *client_host, int port, GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c index 1db9e727b86..9343eb5a427 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c @@ -105,7 +105,7 @@ static void chttp2_init_client_simple_ssl_secure_fullstack( grpc_ssl_credentials_create(NULL, NULL); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.com"}}; + {"foo.test.google.fr"}}; grpc_channel_args *new_client_args = grpc_channel_args_copy_and_add(client_args, &ssl_name_override); chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds); diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c index 35e022c4947..9fb95c95d9d 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c @@ -107,7 +107,7 @@ static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack( grpc_composite_credentials_create(ssl_creds, oauth2_creds); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, - {"foo.test.google.com"}}; + {"foo.test.google.fr"}}; grpc_channel_args *new_client_args = grpc_channel_args_copy_and_add(client_args, &ssl_name_override); chttp2_init_client_secure_fullstack(f, new_client_args, ssl_oauth2_creds); diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c index faaa14727c9..1aeb723553a 100644 --- a/test/core/end2end/tests/cancel_after_accept.c +++ b/test/core/end2end/tests/cancel_after_accept.c @@ -132,7 +132,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config, int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); diff --git a/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c b/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c index c6fb8b3ea2e..a69f86a3271 100644 --- a/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c +++ b/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c @@ -113,7 +113,7 @@ static void test_cancel_after_accept_and_writes_closed( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -122,7 +122,7 @@ static void test_cancel_after_accept_and_writes_closed( GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/cancel_after_accept_and_writes_closed_legacy.c b/test/core/end2end/tests/cancel_after_accept_and_writes_closed_legacy.c index 85b7599b195..6a3a6528b90 100644 --- a/test/core/end2end/tests/cancel_after_accept_and_writes_closed_legacy.c +++ b/test/core/end2end/tests/cancel_after_accept_and_writes_closed_legacy.c @@ -113,7 +113,7 @@ static void test_cancel_after_accept_and_writes_closed( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -121,7 +121,7 @@ static void test_cancel_after_accept_and_writes_closed( grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/cancel_after_accept_legacy.c b/test/core/end2end/tests/cancel_after_accept_legacy.c index 345c31d31f8..15338b5c7ad 100644 --- a/test/core/end2end/tests/cancel_after_accept_legacy.c +++ b/test/core/end2end/tests/cancel_after_accept_legacy.c @@ -113,7 +113,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config, cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -121,7 +121,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config, grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c index 3c75024922b..71d241ffee9 100644 --- a/test/core/end2end/tests/cancel_after_invoke.c +++ b/test/core/end2end/tests/cancel_after_invoke.c @@ -125,7 +125,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config, grpc_byte_buffer_create(&request_payload_slice, 1); c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); diff --git a/test/core/end2end/tests/cancel_after_invoke_legacy.c b/test/core/end2end/tests/cancel_after_invoke_legacy.c index 64af7cd3db2..092b35d0a9a 100644 --- a/test/core/end2end/tests/cancel_after_invoke_legacy.c +++ b/test/core/end2end/tests/cancel_after_invoke_legacy.c @@ -111,7 +111,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config, gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c index bee6dd2e7b9..0ab9ac6c2f2 100644 --- a/test/core/end2end/tests/cancel_before_invoke.c +++ b/test/core/end2end/tests/cancel_before_invoke.c @@ -123,7 +123,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config, int test_ grpc_byte_buffer_create(&request_payload_slice, 1); c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c)); diff --git a/test/core/end2end/tests/cancel_before_invoke_legacy.c b/test/core/end2end/tests/cancel_before_invoke_legacy.c index 23e82cf2683..0c308acde03 100644 --- a/test/core/end2end/tests/cancel_before_invoke_legacy.c +++ b/test/core/end2end/tests/cancel_before_invoke_legacy.c @@ -109,7 +109,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config) { gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c index 8228353b09b..6cb87525d00 100644 --- a/test/core/end2end/tests/cancel_in_a_vacuum.c +++ b/test/core/end2end/tests/cancel_in_a_vacuum.c @@ -110,7 +110,7 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config, cq_verifier *v_client = cq_verifier_create(f.client_cq); c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c)); diff --git a/test/core/end2end/tests/cancel_in_a_vacuum_legacy.c b/test/core/end2end/tests/cancel_in_a_vacuum_legacy.c index 869f091180c..cc6297b1337 100644 --- a/test/core/end2end/tests/cancel_in_a_vacuum_legacy.c +++ b/test/core/end2end/tests/cancel_in_a_vacuum_legacy.c @@ -109,7 +109,7 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config, gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c index 003a8bef9b7..98244db5412 100644 --- a/test/core/end2end/tests/census_simple_request.c +++ b/test/core/end2end/tests/census_simple_request.c @@ -106,7 +106,7 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); tag(1); @@ -118,7 +118,7 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/census_simple_request_legacy.c b/test/core/end2end/tests/census_simple_request_legacy.c index 003a8bef9b7..98244db5412 100644 --- a/test/core/end2end/tests/census_simple_request_legacy.c +++ b/test/core/end2end/tests/census_simple_request_legacy.c @@ -106,7 +106,7 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); tag(1); @@ -118,7 +118,7 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c index 611589678f4..d5d1550f903 100644 --- a/test/core/end2end/tests/disappearing_server.c +++ b/test/core/end2end/tests/disappearing_server.c @@ -97,7 +97,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, grpc_call *s; gpr_timespec deadline = five_seconds_time(); - c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -110,7 +110,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/disappearing_server_legacy.c b/test/core/end2end/tests/disappearing_server_legacy.c index ff8832a231e..7dd6804b380 100644 --- a/test/core/end2end/tests/disappearing_server_legacy.c +++ b/test/core/end2end/tests/disappearing_server_legacy.c @@ -97,7 +97,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, grpc_call *s; gpr_timespec deadline = five_seconds_time(); - c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -109,7 +109,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c index 49ec4715cc4..d65617c4735 100644 --- a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c +++ b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c @@ -111,7 +111,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -124,7 +124,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls_legacy.c b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls_legacy.c index 2e3a05e6692..09ddfc1671a 100644 --- a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls_legacy.c +++ b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls_legacy.c @@ -111,7 +111,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -123,7 +123,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/empty_batch.c b/test/core/end2end/tests/empty_batch.c index 7faeeaa889b..de22518301b 100644 --- a/test/core/end2end/tests/empty_batch.c +++ b/test/core/end2end/tests/empty_batch.c @@ -111,7 +111,7 @@ static void empty_batch_body(grpc_end2end_test_fixture f) { grpc_op *op = NULL; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, op, 0, tag(1))); diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c index ab9792e40ab..9227d3bd463 100644 --- a/test/core/end2end/tests/graceful_server_shutdown.c +++ b/test/core/end2end/tests/graceful_server_shutdown.c @@ -110,7 +110,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -123,7 +123,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/graceful_server_shutdown_legacy.c b/test/core/end2end/tests/graceful_server_shutdown_legacy.c index 852a153accd..19c895eaa28 100644 --- a/test/core/end2end/tests/graceful_server_shutdown_legacy.c +++ b/test/core/end2end/tests/graceful_server_shutdown_legacy.c @@ -110,7 +110,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -122,7 +122,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c index 2a302e2b137..86a0fbdb70d 100644 --- a/test/core/end2end/tests/invoke_large_request.c +++ b/test/core/end2end/tests/invoke_large_request.c @@ -122,7 +122,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -139,7 +139,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { cq_verify_empty(v_client); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/invoke_large_request_legacy.c b/test/core/end2end/tests/invoke_large_request_legacy.c index 875458e7f80..d0a1cebfcb4 100644 --- a/test/core/end2end/tests/invoke_large_request_legacy.c +++ b/test/core/end2end/tests/invoke_large_request_legacy.c @@ -122,7 +122,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -138,7 +138,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { request (as this request is very large) */ cq_verify_empty(v_client); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index 85369b5aac4..743048881d7 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -109,7 +109,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -122,7 +122,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == @@ -182,10 +182,10 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* start two requests - ensuring that the second is not accepted until the first completes */ deadline = five_seconds_time(); - c1 = grpc_channel_create_call_old(f.client, "/alpha", "foo.test.google.com", + c1 = grpc_channel_create_call_old(f.client, "/alpha", "foo.test.google.fr", deadline); GPR_ASSERT(c1); - c2 = grpc_channel_create_call_old(f.client, "/beta", "foo.test.google.com", + c2 = grpc_channel_create_call_old(f.client, "/beta", "foo.test.google.fr", deadline); GPR_ASSERT(c1); @@ -211,7 +211,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { cq_expect_server_rpc_new(v_server, &s1, tag(100), live_call == 300 ? "/alpha" : "/beta", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == @@ -237,7 +237,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200))); cq_expect_server_rpc_new(v_server, &s2, tag(200), live_call == 300 ? "/alpha" : "/beta", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/max_concurrent_streams_legacy.c b/test/core/end2end/tests/max_concurrent_streams_legacy.c index 0cb118d7950..8bf11543878 100644 --- a/test/core/end2end/tests/max_concurrent_streams_legacy.c +++ b/test/core/end2end/tests/max_concurrent_streams_legacy.c @@ -109,7 +109,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -121,7 +121,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); @@ -182,10 +182,10 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* start two requests - ensuring that the second is not accepted until the first completes */ deadline = five_seconds_time(); - c1 = grpc_channel_create_call_old(f.client, "/alpha", "foo.test.google.com", + c1 = grpc_channel_create_call_old(f.client, "/alpha", "foo.test.google.fr", deadline); GPR_ASSERT(c1); - c2 = grpc_channel_create_call_old(f.client, "/beta", "foo.test.google.com", + c2 = grpc_channel_create_call_old(f.client, "/beta", "foo.test.google.fr", deadline); GPR_ASSERT(c1); @@ -211,7 +211,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { cq_expect_server_rpc_new(v_server, &s1, tag(100), live_call == 300 ? "/alpha" : "/beta", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == @@ -237,7 +237,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200))); cq_expect_server_rpc_new(v_server, &s2, tag(200), live_call == 300 ? "/alpha" : "/beta", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c index 2930ba61430..06a029eb650 100644 --- a/test/core/end2end/tests/ping_pong_streaming.c +++ b/test/core/end2end/tests/ping_pong_streaming.c @@ -118,7 +118,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, cq_verifier *v_server = cq_verifier_create(f.server_cq); gpr_log(GPR_INFO, "testing with %d message pairs.", messages); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -128,7 +128,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept_old(s, f.server_cq, tag(102))); diff --git a/test/core/end2end/tests/ping_pong_streaming_legacy.c b/test/core/end2end/tests/ping_pong_streaming_legacy.c index b2764e9f858..b4175b4d095 100644 --- a/test/core/end2end/tests/ping_pong_streaming_legacy.c +++ b/test/core/end2end/tests/ping_pong_streaming_legacy.c @@ -118,7 +118,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, cq_verifier *v_server = cq_verifier_create(f.server_cq); gpr_log(GPR_INFO, "testing with %d message pairs.", messages); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -127,7 +127,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c index 843e9db9edd..45b2ea3e823 100644 --- a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c @@ -140,7 +140,7 @@ static void test_request_response_with_metadata_and_payload( int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); @@ -210,7 +210,7 @@ static void test_request_response_with_metadata_and_payload( GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); diff --git a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload_legacy.c b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload_legacy.c index 9c09e516fae..be74e8bdce9 100644 --- a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload_legacy.c +++ b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload_legacy.c @@ -137,7 +137,7 @@ static void test_request_response_with_metadata_and_payload( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -157,7 +157,7 @@ static void test_request_response_with_metadata_and_payload( cq_verify(v_client); cq_expect_server_rpc_new( - v_server, &s, tag(100), "/foo", "foo.test.google.com", deadline, "key1-bin", + v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, "key1-bin", "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", "key2-bin", "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d", NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/request_response_with_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_metadata_and_payload.c index 7f7b594d807..1675a9e5377 100644 --- a/test/core/end2end/tests/request_response_with_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_metadata_and_payload.c @@ -133,7 +133,7 @@ static void test_request_response_with_metadata_and_payload( int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); @@ -203,7 +203,7 @@ static void test_request_response_with_metadata_and_payload( GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); diff --git a/test/core/end2end/tests/request_response_with_metadata_and_payload_legacy.c b/test/core/end2end/tests/request_response_with_metadata_and_payload_legacy.c index ba330d5f5f8..5c0b9d5b12f 100644 --- a/test/core/end2end/tests/request_response_with_metadata_and_payload_legacy.c +++ b/test/core/end2end/tests/request_response_with_metadata_and_payload_legacy.c @@ -128,7 +128,7 @@ static void test_request_response_with_metadata_and_payload( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -147,7 +147,7 @@ static void test_request_response_with_metadata_and_payload( cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, "key1", "val1", "key2", "val2", NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/request_response_with_payload.c b/test/core/end2end/tests/request_response_with_payload.c index a0dc0331f4e..16f07c7107b 100644 --- a/test/core/end2end/tests/request_response_with_payload.c +++ b/test/core/end2end/tests/request_response_with_payload.c @@ -128,7 +128,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) { int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); @@ -196,7 +196,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) { GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); diff --git a/test/core/end2end/tests/request_response_with_payload_legacy.c b/test/core/end2end/tests/request_response_with_payload_legacy.c index be562748994..37ce89b29a5 100644 --- a/test/core/end2end/tests/request_response_with_payload_legacy.c +++ b/test/core/end2end/tests/request_response_with_payload_legacy.c @@ -121,7 +121,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -136,7 +136,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) { cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c index bf3b19b62d4..fa0d313f490 100644 --- a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c @@ -134,7 +134,7 @@ static void test_request_response_with_metadata_and_payload( int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); @@ -205,7 +205,7 @@ static void test_request_response_with_metadata_and_payload( GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 1); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); diff --git a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload_legacy.c b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload_legacy.c index 0ed0f985ec8..5bce89a3fa6 100644 --- a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload_legacy.c +++ b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload_legacy.c @@ -130,7 +130,7 @@ static void test_request_response_with_metadata_and_payload( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -149,7 +149,7 @@ static void test_request_response_with_metadata_and_payload( cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, "key1", "val1", "key2", "val2", NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/request_with_large_metadata.c b/test/core/end2end/tests/request_with_large_metadata.c index 75341040188..7908493565d 100644 --- a/test/core/end2end/tests/request_with_large_metadata.c +++ b/test/core/end2end/tests/request_with_large_metadata.c @@ -128,7 +128,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { const int large_size = 64 * 1024; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); meta.key = "key"; @@ -197,7 +197,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value)); diff --git a/test/core/end2end/tests/request_with_large_metadata_legacy.c b/test/core/end2end/tests/request_with_large_metadata_legacy.c index bc3b3800139..85926aac149 100644 --- a/test/core/end2end/tests/request_with_large_metadata_legacy.c +++ b/test/core/end2end/tests/request_with_large_metadata_legacy.c @@ -121,7 +121,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { ((char*)meta.value)[large_size] = 0; meta.value_length = large_size; - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -131,7 +131,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, "key", meta.value, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c index bb13512ad42..72614a0bf80 100644 --- a/test/core/end2end/tests/request_with_payload.c +++ b/test/core/end2end/tests/request_with_payload.c @@ -126,7 +126,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); @@ -188,7 +188,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); diff --git a/test/core/end2end/tests/request_with_payload_legacy.c b/test/core/end2end/tests/request_with_payload_legacy.c index b56e08cf1fc..b71e682b9d9 100644 --- a/test/core/end2end/tests/request_with_payload_legacy.c +++ b/test/core/end2end/tests/request_with_payload_legacy.c @@ -116,7 +116,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -132,7 +132,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c index 0a3eb7c7b79..83b065b59eb 100644 --- a/test/core/end2end/tests/simple_delayed_request.c +++ b/test/core/end2end/tests/simple_delayed_request.c @@ -114,7 +114,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, config.init_client(f, client_args); c = grpc_channel_create_call(f->client, f->client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); @@ -172,7 +172,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); gpr_free(details); diff --git a/test/core/end2end/tests/simple_delayed_request_legacy.c b/test/core/end2end/tests/simple_delayed_request_legacy.c index 3c94de548ea..325261449af 100644 --- a/test/core/end2end/tests/simple_delayed_request_legacy.c +++ b/test/core/end2end/tests/simple_delayed_request_legacy.c @@ -103,7 +103,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, config.init_client(f, client_args); - c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -119,7 +119,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c index 591bc52dc5b..dac82535be7 100644 --- a/test/core/end2end/tests/simple_request.c +++ b/test/core/end2end/tests/simple_request.c @@ -122,7 +122,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", - "foo.test.google.com", deadline); + "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); @@ -178,7 +178,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); - GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); + GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); gpr_free(details); diff --git a/test/core/end2end/tests/simple_request_legacy.c b/test/core/end2end/tests/simple_request_legacy.c index 2e30d101e18..52dd6b08451 100644 --- a/test/core/end2end/tests/simple_request_legacy.c +++ b/test/core/end2end/tests/simple_request_legacy.c @@ -110,7 +110,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -122,7 +122,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); @@ -157,7 +157,7 @@ static void simple_request_body2(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -169,7 +169,7 @@ static void simple_request_body2(grpc_end2end_test_fixture f) { cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", + cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/thread_stress.c b/test/core/end2end/tests/thread_stress.c index c10b3737441..996229c2282 100644 --- a/test/core/end2end/tests/thread_stress.c +++ b/test/core/end2end/tests/thread_stress.c @@ -109,7 +109,7 @@ static void start_request(void) { gpr_slice slice = gpr_slice_malloc(100); grpc_byte_buffer *buf; grpc_call *call = grpc_channel_create_call_old( - g_fixture.client, "/Foo", "foo.test.google.com", g_test_end_time); + g_fixture.client, "/Foo", "foo.test.google.fr", g_test_end_time); memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice)); buf = grpc_byte_buffer_create(&slice, 1); diff --git a/test/core/end2end/tests/thread_stress_legacy.c b/test/core/end2end/tests/thread_stress_legacy.c index c10b3737441..996229c2282 100644 --- a/test/core/end2end/tests/thread_stress_legacy.c +++ b/test/core/end2end/tests/thread_stress_legacy.c @@ -109,7 +109,7 @@ static void start_request(void) { gpr_slice slice = gpr_slice_malloc(100); grpc_byte_buffer *buf; grpc_call *call = grpc_channel_create_call_old( - g_fixture.client, "/Foo", "foo.test.google.com", g_test_end_time); + g_fixture.client, "/Foo", "foo.test.google.fr", g_test_end_time); memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice)); buf = grpc_byte_buffer_create(&slice, 1); diff --git a/test/core/end2end/tests/writes_done_hangs_with_pending_read.c b/test/core/end2end/tests/writes_done_hangs_with_pending_read.c index 5f8b9974d68..0189762b5eb 100644 --- a/test/core/end2end/tests/writes_done_hangs_with_pending_read.c +++ b/test/core/end2end/tests/writes_done_hangs_with_pending_read.c @@ -124,7 +124,7 @@ static void test_writes_done_hangs_with_pending_read( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -141,7 +141,7 @@ static void test_writes_done_hangs_with_pending_read( GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/writes_done_hangs_with_pending_read_legacy.c b/test/core/end2end/tests/writes_done_hangs_with_pending_read_legacy.c index 5f8b9974d68..0189762b5eb 100644 --- a/test/core/end2end/tests/writes_done_hangs_with_pending_read_legacy.c +++ b/test/core/end2end/tests/writes_done_hangs_with_pending_read_legacy.c @@ -124,7 +124,7 @@ static void test_writes_done_hangs_with_pending_read( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", + c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); @@ -141,7 +141,7 @@ static void test_writes_done_hangs_with_pending_read( GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", - "foo.test.google.com", deadline, NULL); + "foo.test.google.fr", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index 78f2063c45b..acfaa87ec8b 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -57,7 +57,7 @@ DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); DEFINE_bool(use_prod_roots, false, "True to use SSL roots for google"); DEFINE_int32(server_port, 0, "Server port."); DEFINE_string(server_host, "127.0.0.1", "Server host to connect to"); -DEFINE_string(server_host_override, "foo.test.google.com", +DEFINE_string(server_host_override, "foo.test.google.fr", "Override the server host which is sent in HTTP header"); DEFINE_string(test_case, "large_unary", "Configure different test cases. Valid options are: " diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index 66a9a7b7c40..99b3c2ecd47 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -93,7 +93,7 @@ std::shared_ptr CreateTestChannel( // Shortcut for end2end and interop tests. std::shared_ptr CreateTestChannel(const grpc::string& server, bool enable_ssl) { - return CreateTestChannel(server, "foo.test.google.com", enable_ssl, false); + return CreateTestChannel(server, "foo.test.google.fr", enable_ssl, false); } } // namespace grpc From a0fcfcc1fac262eae219c2585c587968f67ed00c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 23 Feb 2015 20:26:50 -0800 Subject: [PATCH 05/27] Fixed formatting --- src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs index 8d3aef946a6..596918c231c 100644 --- a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs +++ b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs @@ -41,14 +41,16 @@ namespace Grpc.Core.Tests public class GrpcEnvironmentTest { [Test] - public void InitializeAndShutdownGrpcEnvironment() { + public void InitializeAndShutdownGrpcEnvironment() + { GrpcEnvironment.Initialize(); Assert.IsNotNull(GrpcEnvironment.ThreadPool.CompletionQueue); GrpcEnvironment.Shutdown(); } [Test] - public void SubsequentInvocations() { + public void SubsequentInvocations() + { GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize(); GrpcEnvironment.Shutdown(); @@ -56,7 +58,8 @@ namespace Grpc.Core.Tests } [Test] - public void InitializeAfterShutdown() { + public void InitializeAfterShutdown() + { GrpcEnvironment.Initialize(); var tp1 = GrpcEnvironment.ThreadPool; GrpcEnvironment.Shutdown(); From 5b141669e6e2cf8f93ee2150cc60fcb154ac54c0 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 23 Feb 2015 20:28:30 -0800 Subject: [PATCH 06/27] Added some measurement numbers to comments. --- src/csharp/Grpc.Core.Tests/PInvokeTest.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs index b78609ccf08..282d521ba37 100644 --- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs +++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs @@ -65,6 +65,9 @@ namespace Grpc.Core.Tests GrpcEnvironment.Shutdown(); } + /// + /// (~1.26us .NET Windows) + /// [Test] public void CompletionQueueCreateDestroyBenchmark() { @@ -80,7 +83,8 @@ namespace Grpc.Core.Tests /// /// Approximate results: - /// (mono ~80ns) + /// (~80ns Mono Linux) + /// (~110ns .NET Windows) /// [Test] public void NativeCallbackBenchmark() @@ -100,7 +104,8 @@ namespace Grpc.Core.Tests /// /// Creating a new native-to-managed callback has significant overhead /// compared to using an existing one. We need to be aware of this. - /// (~50us on mono) + /// (~50us on Mono Linux!!!) + /// (~1.1us on .NET Windows) /// [Test] public void NewNativeCallbackBenchmark() @@ -117,6 +122,7 @@ namespace Grpc.Core.Tests /// /// Tests overhead of a simple PInvoke call. + /// (~46ns .NET Windows) /// [Test] public void NopPInvokeBenchmark() From b505661b1ae833154deebb689c2c1ba415bc1c11 Mon Sep 17 00:00:00 2001 From: David Klempner Date: Tue, 24 Feb 2015 14:22:50 -0800 Subject: [PATCH 07/27] Add a shutdown API to pollset This allows us to safely asynchronously add FDs in the possibly-promoting unary add case. Also fix the unary add async path to properly handle more of the extra cases it needs to handle. --- src/core/iomgr/pollset.h | 5 ++ src/core/iomgr/pollset_posix.c | 122 ++++++++++++++++++++++------ src/core/iomgr/pollset_posix.h | 4 + src/core/iomgr/pollset_windows.c | 6 ++ src/core/surface/completion_queue.c | 9 +- 5 files changed, 117 insertions(+), 29 deletions(-) diff --git a/src/core/iomgr/pollset.h b/src/core/iomgr/pollset.h index 9d04b014ba7..c26947f37cb 100644 --- a/src/core/iomgr/pollset.h +++ b/src/core/iomgr/pollset.h @@ -52,9 +52,14 @@ #include "src/core/iomgr/pollset_windows.h" #endif + void grpc_pollset_init(grpc_pollset *pollset); +void grpc_pollset_shutdown(grpc_pollset *pollset, + void (*shutdown_done)(void *arg), + void *shutdown_done_arg); void grpc_pollset_destroy(grpc_pollset *pollset); + /* Do some work on a pollset. May involve invoking asynchronous callbacks, or actually polling file descriptors. diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 39945ff3cb7..f0a8453fd77 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -55,6 +55,7 @@ static grpc_pollset g_backup_pollset; static int g_shutdown_backup_poller; static gpr_event g_backup_poller_done; +static gpr_event g_backup_pollset_shutdown_done; static void backup_poller(void *p) { gpr_timespec delta = gpr_time_from_millis(100); @@ -104,9 +105,14 @@ void grpc_pollset_global_init(void) { /* start the backup poller thread */ g_shutdown_backup_poller = 0; gpr_event_init(&g_backup_poller_done); + gpr_event_init(&g_backup_pollset_shutdown_done); gpr_thd_new(&id, backup_poller, NULL, NULL); } +static void on_backup_pollset_shutdown_done(void *arg) { + gpr_event_set(&g_backup_pollset_shutdown_done, (void *)1); +} + void grpc_pollset_global_shutdown(void) { /* terminate the backup poller thread */ gpr_mu_lock(&g_backup_pollset.mu); @@ -114,6 +120,10 @@ void grpc_pollset_global_shutdown(void) { gpr_mu_unlock(&g_backup_pollset.mu); gpr_event_wait(&g_backup_poller_done, gpr_inf_future); + grpc_pollset_shutdown(&g_backup_pollset, on_backup_pollset_shutdown_done, + NULL); + gpr_event_wait(&g_backup_pollset_shutdown_done, gpr_inf_future); + /* destroy the backup pollset */ grpc_pollset_destroy(&g_backup_pollset); @@ -130,6 +140,8 @@ void grpc_pollset_init(grpc_pollset *pollset) { gpr_mu_init(&pollset->mu); gpr_cv_init(&pollset->cv); grpc_pollset_kick_init(&pollset->kick_state); + pollset->in_flight_cbs = 0; + pollset->shutting_down = 0; become_empty_pollset(pollset); } @@ -163,7 +175,24 @@ int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) { return pollset->vtable->maybe_work(pollset, deadline, now, 1); } +void grpc_pollset_shutdown(grpc_pollset *pollset, + void (*shutdown_done)(void *arg), + void *shutdown_done_arg) { + int in_flight_cbs; + gpr_mu_lock(&pollset->mu); + pollset->shutting_down = 1; + in_flight_cbs = pollset->in_flight_cbs; + pollset->shutdown_done_cb = shutdown_done; + pollset->shutdown_done_arg = shutdown_done_arg; + gpr_mu_unlock(&pollset->mu); + if (in_flight_cbs == 0) { + shutdown_done(shutdown_done_arg); + } +} + void grpc_pollset_destroy(grpc_pollset *pollset) { + GPR_ASSERT(pollset->shutting_down); + GPR_ASSERT(pollset->in_flight_cbs == 0); pollset->vtable->destroy(pollset); grpc_pollset_kick_destroy(&pollset->kick_state); gpr_mu_destroy(&pollset->mu); @@ -213,12 +242,21 @@ static void unary_poll_do_promote(void *args, int success) { const grpc_pollset_vtable *original_vtable = up_args->original_vtable; grpc_pollset *pollset = up_args->pollset; grpc_fd *fd = up_args->fd; - grpc_fd *fds[2]; + int do_shutdown_cb = 0; gpr_free(up_args); + /* + * This is quite tricky. There are a number of cases to keep in mind here: + * 1. fd may have been orphaned + * 2. The pollset may no longer be a unary poller (and we can't let case #1 + * leak to other pollset types!) + * 3. pollset's fd (which may have changed) may have been orphaned + * 4. The pollset may be shutting down. + */ + gpr_mu_lock(&pollset->mu); /* First we need to ensure that nobody is polling concurrently */ - while (pollset->counter != 0 && pollset->vtable == original_vtable) { + while (pollset->counter != 0) { grpc_pollset_kick(pollset); gpr_cv_wait(&pollset->cv, &pollset->mu, gpr_inf_future); } @@ -227,31 +265,44 @@ static void unary_poll_do_promote(void *args, int success) { /* TODO(klempner): If we're not careful this could cause infinite recursion. * That's not a problem for now because empty_pollset has a trivial poller * and we don't have any mechanism to unbecome multipoller. */ - if (pollset->vtable != original_vtable) { + pollset->in_flight_cbs--; + if (pollset->shutting_down) { + gpr_log(GPR_INFO, "Shutting down"); + /* We don't care about this pollset anymore. */ + if (pollset->in_flight_cbs == 0) { + do_shutdown_cb = 1; + } + } else if (grpc_fd_is_orphaned(fd)) { + /* Don't try to add it to anything, we'll drop our ref on it below */ + } else if (pollset->vtable != original_vtable) { + gpr_log(GPR_INFO, "Not original vtable"); pollset->vtable->add_fd(pollset, fd); - gpr_cv_broadcast(&pollset->cv); - gpr_mu_unlock(&pollset->mu); - return; - } - - if (fd == pollset->data.ptr) return; - fds[0] = pollset->data.ptr; - fds[1] = fd; - - if (!grpc_fd_is_orphaned(fds[0])) { - grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds)); - grpc_fd_unref(fds[0]); - } else { - /* old fd is orphaned and we haven't cleaned it up until now, so remain a - * unary poller */ - grpc_fd_unref(fds[0]); - pollset->data.ptr = fd; - grpc_fd_ref(fd); + } else if (fd != pollset->data.ptr) { + grpc_fd *fds[2]; + fds[0] = pollset->data.ptr; + fds[1] = fd; + + if (!grpc_fd_is_orphaned(fds[0])) { + grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds)); + grpc_fd_unref(fds[0]); + } else { + /* old fd is orphaned and we haven't cleaned it up until now, so remain a + * unary poller */ + /* Note that it is possible that fds[1] is also orphaned at this point. + * That's okay, we'll correct it at the next add or poll. */ + grpc_fd_unref(fds[0]); + pollset->data.ptr = fd; + grpc_fd_ref(fd); + } } gpr_cv_broadcast(&pollset->cv); gpr_mu_unlock(&pollset->mu); + if (do_shutdown_cb) { + pollset->shutdown_done_cb(pollset->shutdown_done_arg); + } + /* Matching ref in unary_poll_pollset_add_fd */ grpc_fd_unref(fd); } @@ -260,18 +311,31 @@ static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { grpc_unary_promote_args *up_args; if (fd == pollset->data.ptr) return; - if (grpc_fd_is_orphaned(pollset->data.ptr)) { - /* old fd is orphaned and we haven't cleaned it up until now, so remain a - * unary poller */ - grpc_fd_unref(pollset->data.ptr); - pollset->data.ptr = fd; - grpc_fd_ref(fd); + if (!pollset->counter) { + /* Fast path -- no in flight cbs */ + /* TODO(klempner): Comment this out and fix any test failures or establish + * they are due to timing issues */ + grpc_fd *fds[2]; + fds[0] = pollset->data.ptr; + fds[1] = fd; + + if (!grpc_fd_is_orphaned(fds[0])) { + grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds)); + grpc_fd_unref(fds[0]); + } else { + /* old fd is orphaned and we haven't cleaned it up until now, so remain a + * unary poller */ + grpc_fd_unref(fds[0]); + pollset->data.ptr = fd; + grpc_fd_ref(fd); + } return; } /* Now we need to promote. This needs to happen when we're not polling. Since * this may be called from poll, the wait needs to happen asynchronously. */ grpc_fd_ref(fd); + pollset->in_flight_cbs++; up_args = gpr_malloc(sizeof(*up_args)); up_args->pollset = pollset; up_args->fd = fd; @@ -301,6 +365,10 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset, if (pollset->counter) { return 0; } + if (pollset->in_flight_cbs) { + /* Give do_promote priority so we don't starve it out */ + return 0; + } fd = pollset->data.ptr; if (grpc_fd_is_orphaned(fd)) { grpc_fd_unref(fd); diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h index 03b4c775b7f..86b6c9f20e8 100644 --- a/src/core/iomgr/pollset_posix.h +++ b/src/core/iomgr/pollset_posix.h @@ -55,6 +55,10 @@ typedef struct grpc_pollset { gpr_cv cv; grpc_pollset_kick_state kick_state; int counter; + int in_flight_cbs; + int shutting_down; + void (*shutdown_done_cb)(void *arg); + void *shutdown_done_arg; union { int fd; void *ptr; diff --git a/src/core/iomgr/pollset_windows.c b/src/core/iomgr/pollset_windows.c index d21072b2832..bea67116116 100644 --- a/src/core/iomgr/pollset_windows.c +++ b/src/core/iomgr/pollset_windows.c @@ -46,6 +46,12 @@ void grpc_pollset_init(grpc_pollset *pollset) { gpr_cv_init(&pollset->cv); } +void grpc_pollset_shutdown(grpc_pollset *pollset, + void (*shutdown_done)(void *arg), + void *shutdown_done_arg) { + shutdown_done(shutdown_done_arg); +} + void grpc_pollset_destroy(grpc_pollset *pollset) { gpr_mu_destroy(&pollset->mu); gpr_cv_destroy(&pollset->cv); diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index 2efc084d7b3..c4b8d60782f 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -389,12 +389,17 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) { } } -void grpc_completion_queue_destroy(grpc_completion_queue *cc) { - GPR_ASSERT(cc->queue == NULL); +static void on_pollset_destroy_done(void *arg) { + grpc_completion_queue *cc = arg; grpc_pollset_destroy(&cc->pollset); gpr_free(cc); } +void grpc_completion_queue_destroy(grpc_completion_queue *cc) { + GPR_ASSERT(cc->queue == NULL); + grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc); +} + void grpc_event_finish(grpc_event *base) { event *ev = (event *)base; ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK); From 9fff77e4f8175cc26619a167192c8fba1b4b0dd8 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 24 Feb 2015 16:50:35 -0800 Subject: [PATCH 08/27] Addressing comments. --- Makefile | 36 ++- build.json | 14 ++ src/core/tsi/ssl_transport_security.c | 72 +++++- src/core/tsi/ssl_transport_security.h | 7 +- test/core/tsi/transport_security_test.c | 303 ++++++++++++++++++++++++ tools/run_tests/tests.json | 4 + vsprojects/vs2013/Grpc.mak | 12 +- 7 files changed, 436 insertions(+), 12 deletions(-) create mode 100644 test/core/tsi/transport_security_test.c diff --git a/Makefile b/Makefile index 278824a59aa..7b662e575ca 100644 --- a/Makefile +++ b/Makefile @@ -509,6 +509,7 @@ time_averaged_stats_test: $(BINDIR)/$(CONFIG)/time_averaged_stats_test time_test: $(BINDIR)/$(CONFIG)/time_test timeout_encoding_test: $(BINDIR)/$(CONFIG)/timeout_encoding_test transport_metadata_test: $(BINDIR)/$(CONFIG)/transport_metadata_test +transport_security_test: $(BINDIR)/$(CONFIG)/transport_security_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test credentials_test: $(BINDIR)/$(CONFIG)/credentials_test @@ -930,7 +931,7 @@ privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/ buildtests: buildtests_c buildtests_cxx -buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/census_hash_table_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test $(BINDIR)/$(CONFIG)/census_statistics_performance_test $(BINDIR)/$(CONFIG)/census_statistics_quick_test $(BINDIR)/$(CONFIG)/census_statistics_small_log_test $(BINDIR)/$(CONFIG)/census_stub_test $(BINDIR)/$(CONFIG)/census_window_stats_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/chttp2_transport_end2end_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/echo_client $(BINDIR)/$(CONFIG)/echo_server $(BINDIR)/$(CONFIG)/echo_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/metadata_buffer_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_legacy_test +buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/census_hash_table_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test $(BINDIR)/$(CONFIG)/census_statistics_performance_test $(BINDIR)/$(CONFIG)/census_statistics_quick_test $(BINDIR)/$(CONFIG)/census_statistics_small_log_test $(BINDIR)/$(CONFIG)/census_stub_test $(BINDIR)/$(CONFIG)/census_window_stats_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/chttp2_transport_end2end_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/echo_client $(BINDIR)/$(CONFIG)/echo_server $(BINDIR)/$(CONFIG)/echo_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/metadata_buffer_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_legacy_test buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/pubsub_client $(BINDIR)/$(CONFIG)/pubsub_publisher_test $(BINDIR)/$(CONFIG)/pubsub_subscriber_test $(BINDIR)/$(CONFIG)/qps_client $(BINDIR)/$(CONFIG)/qps_server $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/thread_pool_test @@ -1069,6 +1070,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/timeout_encoding_test || ( echo test timeout_encoding_test failed ; exit 1 ) $(E) "[RUN] Testing transport_metadata_test" $(Q) $(BINDIR)/$(CONFIG)/transport_metadata_test || ( echo test transport_metadata_test failed ; exit 1 ) + $(E) "[RUN] Testing transport_security_test" + $(Q) $(BINDIR)/$(CONFIG)/transport_security_test || ( echo test transport_security_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_cancel_after_accept_test" $(Q) $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test || ( echo test chttp2_fake_security_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_cancel_after_accept_and_writes_closed_test" @@ -7429,6 +7432,37 @@ endif endif +TRANSPORT_SECURITY_TEST_SRC = \ + test/core/tsi/transport_security_test.c \ + +TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(TRANSPORT_SECURITY_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/transport_security_test: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/transport_security_test: $(TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/transport_security_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/tsi/transport_security_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_transport_security_test: $(TRANSPORT_SECURITY_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(TRANSPORT_SECURITY_TEST_OBJS:.o=.dep) +endif +endif + + ASYNC_END2END_TEST_SRC = \ test/cpp/end2end/async_end2end_test.cc \ diff --git a/build.json b/build.json index 3e9d2a7584c..7a030ea888a 100644 --- a/build.json +++ b/build.json @@ -1579,6 +1579,20 @@ "gpr" ] }, + { + "name": "transport_security_test", + "build": "test", + "language": "c", + "src": [ + "test/core/tsi/transport_security_test.c" + ], + "deps": [ + "grpc_test_util", + "grpc", + "gpr_test_util", + "gpr" + ] + }, { "name": "async_end2end_test", "build": "test", diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c index f1a52746d24..bda28e90016 100644 --- a/src/core/tsi/ssl_transport_security.c +++ b/src/core/tsi/ssl_transport_security.c @@ -180,6 +180,28 @@ static void ssl_info_callback(const SSL* ssl, int where, int ret) { ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE"); } +/* Returns 1 if name looks like an IP address, 0 otherwise. */ +static int looks_like_ip_address(const char *name) { + size_t i; + size_t dot_count = 0; + size_t num_size = 0; + for (i = 0; i < strlen(name); i++) { + if (name[i] >= '0' && name[i] <= '9') { + if (num_size > 3) return 0; + num_size++; + } else if (name[i] == '.') { + if (dot_count > 3 || num_size == 0) return 0; + dot_count++; + num_size = 0; + } else { + return 0; + } + } + if (dot_count < 3 || num_size == 0) return 0; + return 1; +} + + /* Gets the subject CN from an X509 cert. */ static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8, size_t* utf8_size) { @@ -226,10 +248,18 @@ static tsi_result peer_property_from_x509_common_name( size_t common_name_size; tsi_result result = ssl_get_x509_common_name(cert, &common_name, &common_name_size); - if (result != TSI_OK) return result; + if (result != TSI_OK) { + if (result == TSI_NOT_FOUND) { + common_name = NULL; + common_name_size = 0; + } else { + return result; + } + } result = tsi_construct_string_peer_property( - TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, (const char*)common_name, - common_name_size, property); + TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, + common_name == NULL ? "" : (const char*)common_name, common_name_size, + property); OPENSSL_free(common_name); return result; } @@ -1036,9 +1066,22 @@ static void ssl_server_handshaker_factory_destroy( static int does_entry_match_name(const char* entry, size_t entry_length, const char* name) { + const char *dot; const char* name_subdomain = NULL; + size_t name_length = strlen(name); + size_t name_subdomain_length; if (entry_length == 0) return 0; - if (!strncmp(name, entry, entry_length) && (strlen(name) == entry_length)) { + + /* Take care of '.' terminations. */ + if (name[name_length - 1] == '.') { + name_length--; + } + if (entry[entry_length - 1] == '.') { + entry_length--; + } + + if ((entry_length > 0) && (name_length == entry_length) && + !strncmp(name, entry, entry_length)) { return 1; /* Perfect match. */ } if (entry[0] != '*') return 0; @@ -1053,14 +1096,23 @@ static int does_entry_match_name(const char* entry, size_t entry_length, name_subdomain++; /* Starts after the dot. */ entry += 2; /* Remove *. */ entry_length -= 2; - return (!strncmp(entry, name_subdomain, entry_length) && - (strlen(name_subdomain) == entry_length)); + name_subdomain_length = strlen(name_subdomain); + dot = strchr(name_subdomain, '.'); + if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) { + gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain); + return 0; + } + if (name_subdomain[name_subdomain_length - 1] == '.') { + name_subdomain_length--; + } + return ((entry_length > 0) && (name_subdomain_length == entry_length) && + !strncmp(entry, name_subdomain, entry_length)); } static int ssl_server_handshaker_factory_servername_callback(SSL* ssl, int* ap, void* arg) { tsi_ssl_server_handshaker_factory* impl = - (tsi_ssl_server_handshaker_factory*)arg; + (tsi_ssl_server_handshaker_factory*)arg; size_t i = 0; const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (servername == NULL || strlen(servername) == 0) { @@ -1283,9 +1335,13 @@ tsi_result tsi_create_ssl_server_handshaker_factory( int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) { size_t i = 0; size_t san_count = 0; + const tsi_peer_property* property = NULL; + + /* For now reject what looks like an IP address. */ + if (looks_like_ip_address(name)) return 0; /* Check the SAN first. */ - const tsi_peer_property* property = tsi_peer_get_property_by_name( + property = tsi_peer_get_property_by_name( peer, TSI_X509_SUBJECT_ALTERNATIVE_NAMES_PEER_PROPERTY); if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_LIST) { gpr_log(GPR_ERROR, "Invalid x509 subject alternative names property."); diff --git a/src/core/tsi/ssl_transport_security.h b/src/core/tsi/ssl_transport_security.h index 3c1c4c01a2a..eecf2d7c2d6 100644 --- a/src/core/tsi/ssl_transport_security.h +++ b/src/core/tsi/ssl_transport_security.h @@ -158,7 +158,12 @@ tsi_result tsi_ssl_handshaker_factory_create_handshaker( while handshakers created with this factory are still in use. */ void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory* self); -/* Util that checks that an ssl peer matches a specific name. */ +/* Util that checks that an ssl peer matches a specific name. + Still TODO(jboeuf): + - handle mixed case. + - handle %encoded chars. + - handle public suffix wildchar more strictly (e.g. *.co.uk) + - handle IP addresses in SAN. */ int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name); #ifdef __cplusplus diff --git a/test/core/tsi/transport_security_test.c b/test/core/tsi/transport_security_test.c new file mode 100644 index 00000000000..597b390c9b9 --- /dev/null +++ b/test/core/tsi/transport_security_test.c @@ -0,0 +1,303 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/tsi/transport_security.h" + +#include + +#include +#include +#include + +#include "src/core/support/string.h" +#include "src/core/tsi/ssl_transport_security.h" +#include "test/core/util/test_config.h" + +typedef struct { + /* 1 if success, 0 if failure. */ + int expected; + + /* Host name to match. */ + const char *host_name; + + /* Common name (CN). */ + const char *common_name; + + /* Comma separated list of certificate names to match against. Any occurrence + of '#' will be replaced with a null character before processing. */ + const char *dns_names; + +} cert_name_test_entry; + +/* Largely inspired from: + chromium/src/net/cert/x509_certificate_unittest.cc. + TODO(jboeuf) uncomment test cases as we fix tsi_ssl_peer_matches_name. */ +const cert_name_test_entry cert_name_test_entries[] = { + {1, "foo.com", "foo.com", NULL}, + {1, "f", "f", NULL}, + {0, "h", "i", NULL}, + {1, "bar.foo.com", "*.foo.com", NULL}, + {1, "www.test.fr", "common.name", + "*.test.com,*.test.co.uk,*.test.de,*.test.fr"}, + /* + {1, "wwW.tESt.fr", "common.name", ",*.*,*.test.de,*.test.FR,www"}, + */ + {0, "f.uk", ".uk", NULL}, + {0, "w.bar.foo.com", "?.bar.foo.com", NULL}, + {0, "www.foo.com", "(www|ftp).foo.com", NULL}, + {0, "www.foo.com", "www.foo.com#", NULL}, /* # = null char. */ + {0, "www.foo.com", "", "www.foo.com#*.foo.com,#,#"}, + {0, "www.house.example", "ww.house.example", NULL}, + {0, "test.org", "", "www.test.org,*.test.org,*.org"}, + {0, "w.bar.foo.com", "w*.bar.foo.com", NULL}, + {0, "www.bar.foo.com", "ww*ww.bar.foo.com", NULL}, + {0, "wwww.bar.foo.com", "ww*ww.bar.foo.com", NULL}, + {0, "wwww.bar.foo.com", "w*w.bar.foo.com", NULL}, + {0, "wwww.bar.foo.com", "w*w.bar.foo.c0m", NULL}, + {0, "WALLY.bar.foo.com", "wa*.bar.foo.com", NULL}, + {0, "wally.bar.foo.com", "*Ly.bar.foo.com", NULL}, + /* + {1, "ww%57.foo.com", "", "www.foo.com"}, + {1, "www&.foo.com", "www%26.foo.com", NULL}, + */ + + /* Common name must not be used if subject alternative name was provided. */ + {0, "www.test.co.jp", "www.test.co.jp", + "*.test.de,*.jp,www.test.co.uk,www.*.co.jp"}, + {0, "www.bar.foo.com", "www.bar.foo.com", + "*.foo.com,*.*.foo.com,*.*.bar.foo.com,*..bar.foo.com,"}, + + /* IDN tests */ + {1, "xn--poema-9qae5a.com.br", "xn--poema-9qae5a.com.br", NULL}, + {1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL}, + {0, "xn--poema-9qae5a.com.br", "", + "*.xn--poema-9qae5a.com.br," + "xn--poema-*.com.br," + "xn--*-9qae5a.com.br," + "*--poema-9qae5a.com.br"}, + + /* The following are adapted from the examples quoted from + http://tools.ietf.org/html/rfc6125#section-6.4.3 + (e.g., *.example.com would match foo.example.com but + not bar.foo.example.com or example.com). */ + {1, "foo.example.com", "*.example.com", NULL}, + {0, "bar.foo.example.com", "*.example.com", NULL}, + {0, "example.com", "*.example.com", NULL}, + + /* Partial wildcards are disallowed, though RFC 2818 rules allow them. + That is, forms such as baz*.example.net, *baz.example.net, and + b*z.example.net should NOT match domains. Instead, the wildcard must + always be the left-most label, and only a single label. */ + {0, "baz1.example.net", "baz*.example.net", NULL}, + {0, "foobaz.example.net", "*baz.example.net", NULL}, + {0, "buzz.example.net", "b*z.example.net", NULL}, + {0, "www.test.example.net", "www.*.example.net", NULL}, + + /* Wildcards should not be valid for public registry controlled domains, + and unknown/unrecognized domains, at least three domain components must + be present. */ + {1, "www.test.example", "*.test.example", NULL}, + {1, "test.example.co.uk", "*.example.co.uk", NULL}, + {0, "test.example", "*.example", NULL}, + /* + {0, "example.co.uk", "*.co.uk", NULL}, + */ + {0, "foo.com", "*.com", NULL}, + {0, "foo.us", "*.us", NULL}, + {0, "foo", "*", NULL}, + + /* IDN variants of wildcards and registry controlled domains. */ + {1, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br", NULL}, + {1, "test.example.xn--mgbaam7a8h", "*.example.xn--mgbaam7a8h", NULL}, + /* + {0, "xn--poema-9qae5a.com.br", "*.com.br", NULL}, + */ + {0, "example.xn--mgbaam7a8h", "*.xn--mgbaam7a8h", NULL}, + + /* Wildcards should be permissible for 'private' registry controlled + domains. */ + {1, "www.appspot.com", "*.appspot.com", NULL}, + {1, "foo.s3.amazonaws.com", "*.s3.amazonaws.com", NULL}, + + /* Multiple wildcards are not valid. */ + {0, "foo.example.com", "*.*.com", NULL}, + {0, "foo.bar.example.com", "*.bar.*.com", NULL}, + + /* Absolute vs relative DNS name tests. Although not explicitly specified + in RFC 6125, absolute reference names (those ending in a .) should + match either absolute or relative presented names. */ + {1, "foo.com", "foo.com.", NULL}, + {1, "foo.com.", "foo.com", NULL}, + {1, "foo.com.", "foo.com.", NULL}, + {1, "f", "f.", NULL}, + {1, "f.", "f", NULL}, + {1, "f.", "f.", NULL}, + {1, "www-3.bar.foo.com", "*.bar.foo.com.", NULL}, + {1, "www-3.bar.foo.com.", "*.bar.foo.com", NULL}, + {1, "www-3.bar.foo.com.", "*.bar.foo.com.", NULL}, + {0, ".", ".", NULL}, + {0, "example.com", "*.com.", NULL}, + {0, "example.com.", "*.com", NULL}, + {0, "example.com.", "*.com.", NULL}, + {0, "foo.", "*.", NULL}, + {0, "foo", "*.", NULL}, + /* + {0, "foo.co.uk", "*.co.uk.", NULL}, + {0, "foo.co.uk.", "*.co.uk.", NULL}, + */ + + /* An empty CN is OK. */ + {1, "test.foo.com", "", "test.foo.com"}, + + /* An IP should not be used for the CN. */ + {0, "173.194.195.139", "173.194.195.139", NULL}, +}; + +typedef struct name_list { + const char *name; + struct name_list *next; +} name_list; + +typedef struct { + size_t name_count; + char *buffer; + name_list *names; +} parsed_dns_names; + +name_list *name_list_add(const char *n) { + name_list *result = gpr_malloc(sizeof(name_list)); + result->name = n; + result->next = NULL; + return result; +} + +static parsed_dns_names parse_dns_names(const char *dns_names_str) { + parsed_dns_names result; + name_list *current_nl; + size_t i; + memset(&result, 0, sizeof(parsed_dns_names)); + if (dns_names_str == 0) return result; + result.name_count = 1; + result.buffer = gpr_strdup(dns_names_str); + result.names = name_list_add(result.buffer); + current_nl = result.names; + for (i = 0; i < strlen(dns_names_str); i++) { + if (dns_names_str[i] == ',') { + result.buffer[i] = '\0'; + result.name_count++; + i++; + current_nl->next = name_list_add(result.buffer + i); + current_nl = current_nl->next; + } + } + return result; +} + +static void destruct_parsed_dns_names(parsed_dns_names *pdn) { + name_list *nl = pdn->names; + if (pdn->buffer != NULL) gpr_free(pdn->buffer); + while (nl != NULL) { + name_list *to_be_free = nl; + nl = nl->next; + gpr_free(to_be_free); + } +} + +static char *processed_dns_name(const char *dns_name) { + char *result = gpr_strdup(dns_name); + size_t i; + for (i = 0; i < strlen(result); i++) { + if (result[i] == '#') { + result[i] = '\0'; + } + } + return result; +} + +static tsi_peer peer_from_cert_name_test_entry( + const cert_name_test_entry *entry) { + size_t i; + tsi_peer peer; + name_list *nl; + parsed_dns_names dns_entries = parse_dns_names(entry->dns_names); + nl = dns_entries.names; + GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, entry->common_name, + &peer.properties[0]) == TSI_OK); + GPR_ASSERT(tsi_construct_list_peer_property( + TSI_X509_SUBJECT_ALTERNATIVE_NAMES_PEER_PROPERTY, + dns_entries.name_count, &peer.properties[1]) == TSI_OK); + i = 0; + while (nl != NULL) { + char *processed = processed_dns_name(nl->name); + GPR_ASSERT(tsi_construct_string_peer_property( + NULL, processed, strlen(nl->name), + &peer.properties[1].value.list.children[i++]) == TSI_OK); + nl = nl->next; + gpr_free(processed); + } + destruct_parsed_dns_names(&dns_entries); + return peer; +} + +char *cert_name_test_entry_to_string(const cert_name_test_entry *entry) { + char *s; + gpr_asprintf( + &s, "{ success = %s, host_name = %s, common_name = %s, dns_names = %s}", + entry->expected ? "true" : "false", entry->host_name, entry->common_name, + entry->dns_names != NULL ? entry->dns_names : ""); + return s; +} + +static void test_peer_matches_name(void) { + size_t i = 0; + for (i = 0; i < GPR_ARRAY_SIZE(cert_name_test_entries); i++) { + const cert_name_test_entry *entry = &cert_name_test_entries[i]; + tsi_peer peer = peer_from_cert_name_test_entry(entry); + int result = tsi_ssl_peer_matches_name(&peer, entry->host_name); + if (result != entry->expected) { + char *entry_str = cert_name_test_entry_to_string(entry); + gpr_log(GPR_ERROR, "%s", entry_str); + gpr_free(entry_str); + GPR_ASSERT(0); /* Unexpected result. */ + } + tsi_peer_destruct(&peer); + } +} + +int main(int argc, char **argv) { + grpc_test_init(argc, argv); + test_peer_matches_name(); + return 0; +} diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index 84f830c456e..4fb3e2d6b9e 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -265,6 +265,10 @@ "language": "c", "name": "transport_metadata_test" }, + { + "language": "c", + "name": "transport_security_test" + }, { "language": "c++", "name": "async_end2end_test" diff --git a/vsprojects/vs2013/Grpc.mak b/vsprojects/vs2013/Grpc.mak index 9272d07cb93..203c7872878 100644 --- a/vsprojects/vs2013/Grpc.mak +++ b/vsprojects/vs2013/Grpc.mak @@ -53,10 +53,10 @@ grpc_test_util: $(OUT_DIR): mkdir $(OUT_DIR) -buildtests: alarm_heap_test.exe alarm_list_test.exe alarm_test.exe alpn_test.exe bin_encoder_test.exe census_hash_table_test.exe census_statistics_multiple_writers_circular_buffer_test.exe census_statistics_multiple_writers_test.exe census_statistics_performance_test.exe census_statistics_quick_test.exe census_statistics_small_log_test.exe census_stats_store_test.exe census_stub_test.exe census_trace_store_test.exe census_window_stats_test.exe chttp2_status_conversion_test.exe chttp2_stream_encoder_test.exe chttp2_stream_map_test.exe chttp2_transport_end2end_test.exe dualstack_socket_test.exe echo_test.exe fd_posix_test.exe fling_stream_test.exe fling_test.exe gpr_cancellable_test.exe gpr_cmdline_test.exe gpr_env_test.exe gpr_file_test.exe gpr_histogram_test.exe gpr_host_port_test.exe gpr_log_test.exe gpr_slice_buffer_test.exe gpr_slice_test.exe gpr_string_test.exe gpr_sync_test.exe gpr_thd_test.exe gpr_time_test.exe gpr_useful_test.exe grpc_base64_test.exe grpc_byte_buffer_reader_test.exe grpc_channel_stack_test.exe grpc_completion_queue_test.exe grpc_credentials_test.exe grpc_json_token_test.exe grpc_stream_op_test.exe hpack_parser_test.exe hpack_table_test.exe httpcli_format_request_test.exe httpcli_parser_test.exe httpcli_test.exe json_rewrite_test.exe json_test.exe lame_client_test.exe message_compress_test.exe metadata_buffer_test.exe multi_init_test.exe murmur_hash_test.exe no_server_test.exe poll_kick_posix_test.exe resolve_address_test.exe secure_endpoint_test.exe sockaddr_utils_test.exe tcp_client_posix_test.exe tcp_posix_test.exe tcp_server_posix_test.exe time_averaged_stats_test.exe time_test.exe timeout_encoding_test.exe transport_metadata_test.exe +buildtests: alarm_heap_test.exe alarm_list_test.exe alarm_test.exe alpn_test.exe bin_encoder_test.exe census_hash_table_test.exe census_statistics_multiple_writers_circular_buffer_test.exe census_statistics_multiple_writers_test.exe census_statistics_performance_test.exe census_statistics_quick_test.exe census_statistics_small_log_test.exe census_stats_store_test.exe census_stub_test.exe census_trace_store_test.exe census_window_stats_test.exe chttp2_status_conversion_test.exe chttp2_stream_encoder_test.exe chttp2_stream_map_test.exe chttp2_transport_end2end_test.exe dualstack_socket_test.exe echo_test.exe fd_posix_test.exe fling_stream_test.exe fling_test.exe gpr_cancellable_test.exe gpr_cmdline_test.exe gpr_env_test.exe gpr_file_test.exe gpr_histogram_test.exe gpr_host_port_test.exe gpr_log_test.exe gpr_slice_buffer_test.exe gpr_slice_test.exe gpr_string_test.exe gpr_sync_test.exe gpr_thd_test.exe gpr_time_test.exe gpr_useful_test.exe grpc_base64_test.exe grpc_byte_buffer_reader_test.exe grpc_channel_stack_test.exe grpc_completion_queue_test.exe grpc_credentials_test.exe grpc_json_token_test.exe grpc_stream_op_test.exe hpack_parser_test.exe hpack_table_test.exe httpcli_format_request_test.exe httpcli_parser_test.exe httpcli_test.exe json_rewrite_test.exe json_test.exe lame_client_test.exe message_compress_test.exe metadata_buffer_test.exe multi_init_test.exe murmur_hash_test.exe no_server_test.exe poll_kick_posix_test.exe resolve_address_test.exe secure_endpoint_test.exe sockaddr_utils_test.exe tcp_client_posix_test.exe tcp_posix_test.exe tcp_server_posix_test.exe time_averaged_stats_test.exe time_test.exe timeout_encoding_test.exe transport_metadata_test.exe transport_security_test.exe echo All tests built. -test: alarm_heap_test alarm_list_test alarm_test alpn_test bin_encoder_test census_hash_table_test census_statistics_multiple_writers_circular_buffer_test census_statistics_multiple_writers_test census_statistics_performance_test census_statistics_quick_test census_statistics_small_log_test census_stats_store_test census_stub_test census_trace_store_test census_window_stats_test chttp2_status_conversion_test chttp2_stream_encoder_test chttp2_stream_map_test chttp2_transport_end2end_test dualstack_socket_test echo_test fd_posix_test fling_stream_test fling_test gpr_cancellable_test gpr_cmdline_test gpr_env_test gpr_file_test gpr_histogram_test gpr_host_port_test gpr_log_test gpr_slice_buffer_test gpr_slice_test gpr_string_test gpr_sync_test gpr_thd_test gpr_time_test gpr_useful_test grpc_base64_test grpc_byte_buffer_reader_test grpc_channel_stack_test grpc_completion_queue_test grpc_credentials_test grpc_json_token_test grpc_stream_op_test hpack_parser_test hpack_table_test httpcli_format_request_test httpcli_parser_test httpcli_test json_rewrite_test json_test lame_client_test message_compress_test metadata_buffer_test multi_init_test murmur_hash_test no_server_test poll_kick_posix_test resolve_address_test secure_endpoint_test sockaddr_utils_test tcp_client_posix_test tcp_posix_test tcp_server_posix_test time_averaged_stats_test time_test timeout_encoding_test transport_metadata_test +test: alarm_heap_test alarm_list_test alarm_test alpn_test bin_encoder_test census_hash_table_test census_statistics_multiple_writers_circular_buffer_test census_statistics_multiple_writers_test census_statistics_performance_test census_statistics_quick_test census_statistics_small_log_test census_stats_store_test census_stub_test census_trace_store_test census_window_stats_test chttp2_status_conversion_test chttp2_stream_encoder_test chttp2_stream_map_test chttp2_transport_end2end_test dualstack_socket_test echo_test fd_posix_test fling_stream_test fling_test gpr_cancellable_test gpr_cmdline_test gpr_env_test gpr_file_test gpr_histogram_test gpr_host_port_test gpr_log_test gpr_slice_buffer_test gpr_slice_test gpr_string_test gpr_sync_test gpr_thd_test gpr_time_test gpr_useful_test grpc_base64_test grpc_byte_buffer_reader_test grpc_channel_stack_test grpc_completion_queue_test grpc_credentials_test grpc_json_token_test grpc_stream_op_test hpack_parser_test hpack_table_test httpcli_format_request_test httpcli_parser_test httpcli_test json_rewrite_test json_test lame_client_test message_compress_test metadata_buffer_test multi_init_test murmur_hash_test no_server_test poll_kick_posix_test resolve_address_test secure_endpoint_test sockaddr_utils_test tcp_client_posix_test tcp_posix_test tcp_server_posix_test time_averaged_stats_test time_test timeout_encoding_test transport_metadata_test transport_security_test echo All tests ran. test_gpr: gpr_cancellable_test gpr_cmdline_test gpr_env_test gpr_file_test gpr_histogram_test gpr_host_port_test gpr_log_test gpr_slice_buffer_test gpr_slice_test gpr_string_test gpr_sync_test gpr_thd_test gpr_time_test gpr_useful_test @@ -702,3 +702,11 @@ transport_metadata_test: transport_metadata_test.exe echo Running transport_metadata_test $(OUT_DIR)\transport_metadata_test.exe +transport_security_test.exe: grpc_test_util + echo Building transport_security_test + $(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ ..\..\test\core\tsi\transport_security_test.c + $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\transport_security_test.exe" Debug\grpc_test_util.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(LIBS) $(OUT_DIR)\transport_security_test.obj +transport_security_test: transport_security_test.exe + echo Running transport_security_test + $(OUT_DIR)\transport_security_test.exe + From c6bccc24d39cf651219e96e91ccc7767943272b8 Mon Sep 17 00:00:00 2001 From: David Klempner Date: Tue, 24 Feb 2015 17:33:05 -0800 Subject: [PATCH 09/27] Move close() to when the fd refcount goes to zero Instead, we do a shutdown() at the point we are currently closing, to kick off socket teardown while ensuring an fd ref is sufficient to make concurrent syscalls like epoll_ctl safe. --- src/core/iomgr/fd_posix.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index 41fd24e05a8..abdd49bbda3 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -38,6 +38,7 @@ #include "src/core/iomgr/fd_posix.h" #include +#include #include #include "src/core/iomgr/iomgr_internal.h" @@ -113,6 +114,7 @@ static void ref_by(grpc_fd *fd, int n) { static void unref_by(grpc_fd *fd, int n) { gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); if (old == n) { + close(fd->fd); grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data); freelist_fd(fd); grpc_iomgr_unref(); @@ -158,9 +160,9 @@ static void wake_watchers(grpc_fd *fd) { void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) { fd->on_done = on_done ? on_done : do_nothing; fd->on_done_user_data = user_data; + shutdown(fd->fd, SHUT_RDWR); ref_by(fd, 1); /* remove active status, but keep referenced */ wake_watchers(fd); - close(fd->fd); unref_by(fd, 2); /* drop the reference */ } From 0170a6c662337a1d9c741fa466d3a26723f2d5cf Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 24 Feb 2015 18:08:01 -0800 Subject: [PATCH 10/27] Addressing another round of comments. --- src/core/tsi/ssl_transport_security.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c index bda28e90016..567b990610b 100644 --- a/src/core/tsi/ssl_transport_security.c +++ b/src/core/tsi/ssl_transport_security.c @@ -180,7 +180,9 @@ static void ssl_info_callback(const SSL* ssl, int where, int ret) { ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE"); } -/* Returns 1 if name looks like an IP address, 0 otherwise. */ +/* Returns 1 if name looks like an IP address, 0 otherwise. + This is a very rough heuristic as it does not handle IPV6 or things like: + 0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */ static int looks_like_ip_address(const char *name) { size_t i; size_t dot_count = 0; @@ -1078,10 +1080,10 @@ static int does_entry_match_name(const char* entry, size_t entry_length, } if (entry[entry_length - 1] == '.') { entry_length--; + if (entry_length == 0) return 0; } - if ((entry_length > 0) && (name_length == entry_length) && - !strncmp(name, entry, entry_length)) { + if ((name_length == entry_length) && !strncmp(name, entry, entry_length)) { return 1; /* Perfect match. */ } if (entry[0] != '*') return 0; @@ -1092,11 +1094,12 @@ static int does_entry_match_name(const char* entry, size_t entry_length, return 0; } name_subdomain = strchr(name, '.'); - if (name_subdomain == NULL || strlen(name_subdomain) < 2) return 0; + name_subdomain_length = strlen(name_subdomain); + if (name_subdomain == NULL || name_subdomain_length < 2) return 0; name_subdomain++; /* Starts after the dot. */ + name_subdomain_length--; entry += 2; /* Remove *. */ entry_length -= 2; - name_subdomain_length = strlen(name_subdomain); dot = strchr(name_subdomain, '.'); if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) { gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain); From 59d9ff4d9fd596f7cf77cf4285c3519363df4af8 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Mon, 23 Feb 2015 15:28:07 -0800 Subject: [PATCH 11/27] Updated Python protoc plugin testing. --- src/compiler/python_generator.cc | 367 +++++++++++++++----------- src/compiler/python_generator.h | 3 +- src/compiler/python_plugin.cc | 16 +- test/compiler/python_plugin_test.py | 395 +++++++++++++++------------- test/compiler/test.proto | 3 +- tools/run_tests/run_python.sh | 3 +- 6 files changed, 443 insertions(+), 344 deletions(-) diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index cdd3d8a98a5..34d5332d03f 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -33,9 +33,11 @@ #include #include +#include #include #include #include +#include #include "src/compiler/python_generator.h" #include @@ -43,14 +45,19 @@ #include #include +using google::protobuf::Descriptor; using google::protobuf::FileDescriptor; using google::protobuf::ServiceDescriptor; using google::protobuf::MethodDescriptor; using google::protobuf::io::Printer; using google::protobuf::io::StringOutputStream; using std::initializer_list; +using std::make_pair; using std::map; +using std::pair; using std::string; +using std::strlen; +using std::vector; namespace grpc_python_generator { namespace { @@ -99,62 +106,81 @@ class IndentScope { // END FORMATTING BOILERPLATE // //////////////////////////////// -void PrintService(const ServiceDescriptor* service, - Printer* out) { +bool PrintServicer(const ServiceDescriptor* service, + Printer* out) { string doc = ""; map dict = ListToDict({ "Service", service->name(), "Documentation", doc, }); - out->Print(dict, "class $Service$Service(object):\n"); + out->Print(dict, "class EarlyAdopter$Service$Servicer(object):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); - out->Print("def __init__(self):\n"); - { - IndentScope raii_method_indent(out); - out->Print("pass\n"); + out->Print("__metaclass__ = abc.ABCMeta\n"); + for (int i = 0; i < service->method_count(); ++i) { + auto meth = service->method(i); + string arg_name = meth->client_streaming() ? + "request_iterator" : "request"; + out->Print("@abc.abstractmethod\n"); + out->Print("def $Method$(self, $ArgName$):\n", + "Method", meth->name(), "ArgName", arg_name); + { + IndentScope raii_method_indent(out); + out->Print("raise NotImplementedError()\n"); + } } } + return true; } -void PrintServicer(const ServiceDescriptor* service, - Printer* out) { +bool PrintServer(const ServiceDescriptor* service, Printer* out) { string doc = ""; map dict = ListToDict({ "Service", service->name(), "Documentation", doc, }); - out->Print(dict, "class $Service$Servicer(object):\n"); + out->Print(dict, "class EarlyAdopter$Service$Server(object):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); - for (int i = 0; i < service->method_count(); ++i) { - auto meth = service->method(i); - out->Print("def $Method$(self, arg):\n", "Method", meth->name()); - { - IndentScope raii_method_indent(out); - out->Print("raise NotImplementedError()\n"); - } + out->Print("__metaclass__ = abc.ABCMeta\n"); + out->Print("@abc.abstractmethod\n"); + out->Print("def start(self):\n"); + { + IndentScope raii_method_indent(out); + out->Print("raise NotImplementedError()\n"); + } + + out->Print("@abc.abstractmethod\n"); + out->Print("def stop(self):\n"); + { + IndentScope raii_method_indent(out); + out->Print("raise NotImplementedError()\n"); } } + return true; } -void PrintStub(const ServiceDescriptor* service, +bool PrintStub(const ServiceDescriptor* service, Printer* out) { string doc = ""; map dict = ListToDict({ "Service", service->name(), "Documentation", doc, }); - out->Print(dict, "class $Service$Stub(object):\n"); + out->Print(dict, "class EarlyAdopter$Service$Stub(object):\n"); { IndentScope raii_class_indent(out); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); + out->Print("__metaclass__ = abc.ABCMeta\n"); for (int i = 0; i < service->method_count(); ++i) { const MethodDescriptor* meth = service->method(i); - auto methdict = ListToDict({"Method", meth->name()}); - out->Print(methdict, "def $Method$(self, arg):\n"); + string arg_name = meth->client_streaming() ? + "request_iterator" : "request"; + auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name}); + out->Print("@abc.abstractmethod\n"); + out->Print(methdict, "def $Method$(self, $ArgName$):\n"); { IndentScope raii_method_indent(out); out->Print("raise NotImplementedError()\n"); @@ -162,169 +188,190 @@ void PrintStub(const ServiceDescriptor* service, out->Print(methdict, "$Method$.async = None\n"); } } + return true; } -void PrintStubImpl(const ServiceDescriptor* service, - Printer* out) { - map dict = ListToDict({ - "Service", service->name(), - }); - out->Print(dict, "class _$Service$Stub($Service$Stub):\n"); - { - IndentScope raii_class_indent(out); - out->Print("def __init__(self, face_stub, default_timeout):\n"); - { - IndentScope raii_method_indent(out); - out->Print("self._face_stub = face_stub\n" - "self._default_timeout = default_timeout\n" - "stub_self = self\n"); +bool GetModuleAndMessagePath(const Descriptor* type, + pair* out) { + const Descriptor* path_elem_type = type; + vector message_path; + do { + message_path.push_back(path_elem_type); + path_elem_type = path_elem_type->containing_type(); + } while (path_elem_type != nullptr); + string file_name = type->file()->name(); + string module_name; + static const int proto_suffix_length = strlen(".proto"); + if (!(file_name.size() > static_cast(proto_suffix_length) && + file_name.find_last_of(".proto") == file_name.size() - 1)) { + return false; + } + module_name = file_name.substr( + 0, file_name.size() - proto_suffix_length) + "_pb2"; + string package = type->file()->package(); + string module = (package.empty() ? "" : package + ".") + + module_name; + string message_type; + for (auto path_iter = message_path.rbegin(); + path_iter != message_path.rend(); ++path_iter) { + message_type += (*path_iter)->name() + "."; + } + message_type.pop_back(); + *out = make_pair(module, message_type); + return true; +} - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* meth = service->method(i); - bool server_streaming = meth->server_streaming(); - bool client_streaming = meth->client_streaming(); - std::string blocking_call, future_call; - if (server_streaming) { - if (client_streaming) { - blocking_call = "stub_self._face_stub.inline_stream_in_stream_out"; - future_call = blocking_call; - } else { - blocking_call = "stub_self._face_stub.inline_value_in_stream_out"; - future_call = blocking_call; - } - } else { - if (client_streaming) { - blocking_call = "stub_self._face_stub.blocking_stream_in_value_out"; - future_call = "stub_self._face_stub.future_stream_in_value_out"; - } else { - blocking_call = "stub_self._face_stub.blocking_value_in_value_out"; - future_call = "stub_self._face_stub.future_value_in_value_out"; - } - } - // TODO(atash): use the solution described at - // http://stackoverflow.com/a/2982 to bind 'async' attribute - // functions to def'd functions instead of using callable attributes. - auto methdict = ListToDict({ - "Method", meth->name(), - "BlockingCall", blocking_call, - "FutureCall", future_call - }); - out->Print(methdict, "class $Method$(object):\n"); - { - IndentScope raii_callable_indent(out); - out->Print("def __call__(self, arg):\n"); - { - IndentScope raii_callable_call_indent(out); - out->Print(methdict, - "return $BlockingCall$(\"$Method$\", arg, " - "stub_self._default_timeout)\n"); - } - out->Print("def async(self, arg):\n"); - { - IndentScope raii_callable_async_indent(out); - out->Print(methdict, - "return $FutureCall$(\"$Method$\", arg, " - "stub_self._default_timeout)\n"); - } - } - out->Print(methdict, "self.$Method$ = $Method$()\n"); +bool PrintServerFactory(const ServiceDescriptor* service, Printer* out) { + out->Print("def early_adopter_create_$Service$_server(servicer, port, " + "root_certificates, key_chain_pairs):\n", + "Service", service->name()); + { + IndentScope raii_create_server_indent(out); + map> method_to_module_and_message; + out->Print("method_implementations = {\n"); + for (int i = 0; i < service->method_count(); ++i) { + IndentScope raii_implementations_indent(out); + const MethodDescriptor* meth = service->method(i); + string meth_type = + string(meth->client_streaming() ? "stream" : "unary") + + string(meth->server_streaming() ? "_stream" : "_unary") + "_inline"; + out->Print("\"$Method$\": utilities.$Type$(servicer.$Method$),\n", + "Method", meth->name(), + "Type", meth_type); + // Maintain information on the input type of the service method for later + // use in constructing the service assembly's activated fore link. + const Descriptor* input_type = meth->input_type(); + pair module_and_message; + if (!GetModuleAndMessagePath(input_type, &module_and_message)) { + return false; } + method_to_module_and_message.emplace( + meth->name(), module_and_message); + } + out->Print("}\n"); + // Ensure that we've imported all of the relevant messages. + for (auto& meth_vals : method_to_module_and_message) { + out->Print("import $Module$\n", + "Module", meth_vals.second.first); } + out->Print("request_deserializers = {\n"); + for (auto& meth_vals : method_to_module_and_message) { + IndentScope raii_serializers_indent(out); + string full_input_type_path = meth_vals.second.first + "." + + meth_vals.second.second; + out->Print("\"$Method$\": $Type$.FromString,\n", + "Method", meth_vals.first, + "Type", full_input_type_path); + } + out->Print("}\n"); + out->Print("response_serializers = {\n"); + for (auto& meth_vals : method_to_module_and_message) { + IndentScope raii_serializers_indent(out); + out->Print("\"$Method$\": lambda x: x.SerializeToString(),\n", + "Method", meth_vals.first); + } + out->Print("}\n"); + out->Print("link = fore.activated_fore_link(port, request_deserializers, " + "response_serializers, root_certificates, key_chain_pairs)\n"); + out->Print("return implementations.assemble_service(" + "method_implementations, link)\n"); } + return true; } -void PrintStubGenerators(const ServiceDescriptor* service, Printer* out) { +bool PrintStubFactory(const ServiceDescriptor* service, Printer* out) { map dict = ListToDict({ "Service", service->name(), }); - // Write out a generator of linked pairs of Server/Stub - out->Print(dict, "def mock_$Service$(servicer, default_timeout):\n"); + out->Print(dict, "def early_adopter_create_$Service$_stub(host, port):\n"); { - IndentScope raii_mock_indent(out); - out->Print("value_in_value_out = {}\n" - "value_in_stream_out = {}\n" - "stream_in_value_out = {}\n" - "stream_in_stream_out = {}\n"); + IndentScope raii_create_server_indent(out); + map> method_to_module_and_message; + out->Print("method_implementations = {\n"); for (int i = 0; i < service->method_count(); ++i) { + IndentScope raii_implementations_indent(out); const MethodDescriptor* meth = service->method(i); - std::string super_interface, meth_dict; - bool server_streaming = meth->server_streaming(); - bool client_streaming = meth->client_streaming(); - if (server_streaming) { - if (client_streaming) { - super_interface = "InlineStreamInStreamOutMethod"; - meth_dict = "stream_in_stream_out"; - } else { - super_interface = "InlineValueInStreamOutMethod"; - meth_dict = "value_in_stream_out"; - } - } else { - if (client_streaming) { - super_interface = "InlineStreamInValueOutMethod"; - meth_dict = "stream_in_value_out"; - } else { - super_interface = "InlineValueInValueOutMethod"; - meth_dict = "value_in_value_out"; - } - } - map methdict = ListToDict({ - "Method", meth->name(), - "SuperInterface", super_interface, - "MethodDict", meth_dict - }); - out->Print( - methdict, "class $Method$(_face_interfaces.$SuperInterface$):\n"); - { - IndentScope raii_inline_class_indent(out); - out->Print("def service(self, request, context):\n"); - { - IndentScope raii_inline_class_fn_indent(out); - out->Print(methdict, "return servicer.$Method$(request)\n"); - } + string meth_type = + string(meth->client_streaming() ? "stream" : "unary") + + string(meth->server_streaming() ? "_stream" : "_unary") + "_inline"; + // TODO(atash): once the expected input to assemble_dynamic_inline_stub is + // cleaned up, change this to the expected argument's dictionary values. + out->Print("\"$Method$\": utilities.$Type$(None),\n", + "Method", meth->name(), + "Type", meth_type); + // Maintain information on the input type of the service method for later + // use in constructing the service assembly's activated fore link. + const Descriptor* output_type = meth->output_type(); + pair module_and_message; + if (!GetModuleAndMessagePath(output_type, &module_and_message)) { + return false; } - out->Print(methdict, "$MethodDict$['$Method$'] = $Method$()\n"); + method_to_module_and_message.emplace( + meth->name(), module_and_message); } - out->Print( - "face_linked_pair = _face_testing.server_and_stub(default_timeout," - "inline_value_in_value_out_methods=value_in_value_out," - "inline_value_in_stream_out_methods=value_in_stream_out," - "inline_stream_in_value_out_methods=stream_in_value_out," - "inline_stream_in_stream_out_methods=stream_in_stream_out)\n"); - out->Print("class LinkedPair(object):\n"); - { - IndentScope raii_linked_pair(out); - out->Print("def __init__(self, server, stub):\n"); - { - IndentScope raii_linked_pair_init(out); - out->Print("self.server = server\n" - "self.stub = stub\n"); - } + out->Print("}\n"); + // Ensure that we've imported all of the relevant messages. + for (auto& meth_vals : method_to_module_and_message) { + out->Print("import $Module$\n", + "Module", meth_vals.second.first); } - out->Print( - dict, - "stub = _$Service$Stub(face_linked_pair.stub, default_timeout)\n"); - out->Print("return LinkedPair(None, stub)\n"); + out->Print("response_deserializers = {\n"); + for (auto& meth_vals : method_to_module_and_message) { + IndentScope raii_serializers_indent(out); + string full_output_type_path = meth_vals.second.first + "." + + meth_vals.second.second; + out->Print("\"$Method$\": $Type$.FromString,\n", + "Method", meth_vals.first, + "Type", full_output_type_path); + } + out->Print("}\n"); + out->Print("request_serializers = {\n"); + for (auto& meth_vals : method_to_module_and_message) { + IndentScope raii_serializers_indent(out); + out->Print("\"$Method$\": lambda x: x.SerializeToString(),\n", + "Method", meth_vals.first); + } + out->Print("}\n"); + out->Print("link = rear.activated_rear_link(" + "host, port, request_serializers, response_deserializers)\n"); + out->Print("return implementations.assemble_dynamic_inline_stub(" + "method_implementations, link)\n"); } + return true; +} + +bool PrintPreamble(const FileDescriptor* file, Printer* out) { + out->Print("import abc\n"); + out->Print("from grpc._adapter import fore\n"); + out->Print("from grpc._adapter import rear\n"); + out->Print("from grpc.framework.assembly import implementations\n"); + out->Print("from grpc.framework.assembly import utilities\n"); + return true; } } // namespace -string GetServices(const FileDescriptor* file) { +pair GetServices(const FileDescriptor* file) { string output; - StringOutputStream output_stream(&output); - Printer out(&output_stream, '$'); - out.Print("from grpc.framework.face import demonstration as _face_testing\n"); - out.Print("from grpc.framework.face import interfaces as _face_interfaces\n"); - - for (int i = 0; i < file->service_count(); ++i) { - auto service = file->service(i); - PrintService(service, &out); - PrintServicer(service, &out); - PrintStub(service, &out); - PrintStubImpl(service, &out); - PrintStubGenerators(service, &out); + { + // Scope the output stream so it closes and finalizes output to the string. + StringOutputStream output_stream(&output); + Printer out(&output_stream, '$'); + if (!PrintPreamble(file, &out)) { + return make_pair(false, ""); + } + for (int i = 0; i < file->service_count(); ++i) { + auto service = file->service(i); + if (!(PrintServicer(service, &out) && + PrintServer(service, &out) && + PrintStub(service, &out) && + PrintServerFactory(service, &out) && + PrintStubFactory(service, &out))) { + return make_pair(false, ""); + } + } } - return output; + return make_pair(true, std::move(output)); } } // namespace grpc_python_generator diff --git a/src/compiler/python_generator.h b/src/compiler/python_generator.h index 673ef7b23b3..773dfa3513d 100644 --- a/src/compiler/python_generator.h +++ b/src/compiler/python_generator.h @@ -35,6 +35,7 @@ #define __GRPC_COMPILER_PYTHON_GENERATOR_H__ #include +#include namespace google { namespace protobuf { @@ -44,7 +45,7 @@ class FileDescriptor; namespace grpc_python_generator { -std::string GetServices(const google::protobuf::FileDescriptor* file); +std::pair GetServices(const google::protobuf::FileDescriptor* file); } // namespace grpc_python_generator diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc index 05c6b095d8e..ed1e0494fbe 100644 --- a/src/compiler/python_plugin.cc +++ b/src/compiler/python_plugin.cc @@ -33,6 +33,7 @@ // Generates a Python gRPC service interface out of Protobuf IDL. +#include #include #include @@ -50,6 +51,7 @@ using google::protobuf::compiler::PluginMain; using google::protobuf::io::CodedOutputStream; using google::protobuf::io::ZeroCopyOutputStream; using std::string; +using std::strlen; class PythonGrpcGenerator : public CodeGenerator { public: @@ -62,7 +64,7 @@ class PythonGrpcGenerator : public CodeGenerator { string* error) const override { // Get output file name. string file_name; - static const int proto_suffix_length = 6; // length of ".proto" + static const int proto_suffix_length = strlen(".proto"); if (file->name().size() > static_cast(proto_suffix_length) && file->name().find_last_of(".proto") == file->name().size() - 1) { file_name = file->name().substr( @@ -75,9 +77,15 @@ class PythonGrpcGenerator : public CodeGenerator { std::unique_ptr output( context->OpenForInsert(file_name, "module_scope")); CodedOutputStream coded_out(output.get()); - string code = grpc_python_generator::GetServices(file); - coded_out.WriteRaw(code.data(), code.size()); - return true; + bool success = false; + string code = ""; + tie(success, code) = grpc_python_generator::GetServices(file); + if (success) { + coded_out.WriteRaw(code.data(), code.size()); + return true; + } else { + return false; + } } }; diff --git a/test/compiler/python_plugin_test.py b/test/compiler/python_plugin_test.py index b0c9ec62d07..3919de14509 100644 --- a/test/compiler/python_plugin_test.py +++ b/test/compiler/python_plugin_test.py @@ -40,8 +40,24 @@ import unittest from grpc.framework.face import exceptions from grpc.framework.foundation import future +# Identifiers of entities we expect to find in the generated module. +SERVICER_IDENTIFIER = 'EarlyAdopterTestServiceServicer' +SERVER_IDENTIFIER = 'EarlyAdopterTestServiceServer' +STUB_IDENTIFIER = 'EarlyAdopterTestServiceStub' +SERVER_FACTORY_IDENTIFIER = 'early_adopter_create_TestService_server' +STUB_FACTORY_IDENTIFIER = 'early_adopter_create_TestService_stub' + +# Timeouts and delays. +SHORT_TIMEOUT = 0.1 +NORMAL_TIMEOUT = 1 +LONG_TIMEOUT = 2 +DOES_NOT_MATTER_DELAY = 0 +NO_DELAY = 0 +LONG_DELAY = 1 + # Assigned in __main__. _build_mode = None +_port = None class _ServicerMethods(object): @@ -71,14 +87,14 @@ class _ServicerMethods(object): while self._paused: time.sleep(0) - def UnaryCall(self, request): + def UnaryCall(self, request, context): response = self.test_pb2.SimpleResponse() response.payload.payload_type = self.test_pb2.COMPRESSABLE response.payload.payload_compressable = 'a' * request.response_size self._control() return response - def StreamingOutputCall(self, request): + def StreamingOutputCall(self, request, context): for parameter in request.response_parameters: response = self.test_pb2.StreamingOutputCallResponse() response.payload.payload_type = self.test_pb2.COMPRESSABLE @@ -86,7 +102,7 @@ class _ServicerMethods(object): self._control() yield response - def StreamingInputCall(self, request_iter): + def StreamingInputCall(self, request_iter, context): response = self.test_pb2.StreamingInputCallResponse() aggregated_payload_size = 0 for request in request_iter: @@ -95,7 +111,7 @@ class _ServicerMethods(object): self._control() return response - def FullDuplexCall(self, request_iter): + def FullDuplexCall(self, request_iter, context): for request in request_iter: for parameter in request.response_parameters: response = self.test_pb2.StreamingOutputCallResponse() @@ -104,7 +120,7 @@ class _ServicerMethods(object): self._control() yield response - def HalfDuplexCall(self, request_iter): + def HalfDuplexCall(self, request_iter, context): responses = [] for request in request_iter: for parameter in request.response_parameters: @@ -117,7 +133,7 @@ class _ServicerMethods(object): yield response -def CreateService(test_pb2, delay=0, timeout=1): +def _CreateService(test_pb2, delay): """Provides a servicer backend and a stub. The servicer is just the implementation @@ -136,28 +152,30 @@ def CreateService(test_pb2, delay=0, timeout=1): A two-tuple (servicer, stub), where the servicer is the back-end of the service bound to the stub. """ - class Servicer(test_pb2.TestServiceServicer): + servicer_methods = _ServicerMethods(test_pb2, delay) - def UnaryCall(self, request): - return servicer_methods.UnaryCall(request) + class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)): - def StreamingOutputCall(self, request): - return servicer_methods.StreamingOutputCall(request) + def UnaryCall(self, request, context): + return servicer_methods.UnaryCall(request, context) - def StreamingInputCall(self, request_iter): - return servicer_methods.StreamingInputCall(request_iter) + def StreamingOutputCall(self, request, context): + return servicer_methods.StreamingOutputCall(request, context) - def FullDuplexCall(self, request_iter): - return servicer_methods.FullDuplexCall(request_iter) + def StreamingInputCall(self, request_iter, context): + return servicer_methods.StreamingInputCall(request_iter, context) - def HalfDuplexCall(self, request_iter): - return servicer_methods.HalfDuplexCall(request_iter) + def FullDuplexCall(self, request_iter, context): + return servicer_methods.FullDuplexCall(request_iter, context) + + def HalfDuplexCall(self, request_iter, context): + return servicer_methods.HalfDuplexCall(request_iter, context) - servicer_methods = _ServicerMethods(test_pb2, delay) servicer = Servicer() - linked_pair = test_pb2.mock_TestService(servicer, timeout) - stub = linked_pair.stub - return servicer_methods, stub + server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer, _port, + None, None) + stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)('localhost', _port) + return servicer_methods, stub, server def StreamingInputRequest(test_pb2): @@ -198,19 +216,20 @@ class PythonPluginTest(unittest.TestCase): def setUp(self): protoc_command = '../../bins/%s/protobuf/protoc' % _build_mode protoc_plugin_filename = '../../bins/%s/grpc_python_plugin' % _build_mode - test_proto_filename = '../cpp/interop/test.proto' + test_proto_filename = './test.proto' if not os.path.isfile(protoc_command): # Assume that if we haven't built protoc that it's on the system. protoc_command = 'protoc' - # ensure that the output directory exists - outdir = '../../gens/test/compiler/python/' + # Ensure that the output directory exists. + outdir = '../../gens/test/compiler/python' try: os.makedirs(outdir) except OSError as exception: if exception.errno != errno.EEXIST: raise + # Invoke protoc with the plugin. cmd = [ protoc_command, '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename, @@ -222,215 +241,231 @@ class PythonPluginTest(unittest.TestCase): subprocess.call(' '.join(cmd), shell=True) sys.path.append(outdir) - self.delay = 1 # seconds - self.timeout = 2 # seconds + # TODO(atash): Figure out which of theses tests is hanging flakily with small + # probability. def testImportAttributes(self): - # check that we can access the members + # check that we can access the generated module and its members. import test_pb2 # pylint: disable=g-import-not-at-top - self.assertIsNotNone(getattr(test_pb2, 'TestServiceServicer', None)) - self.assertIsNotNone(getattr(test_pb2, 'TestServiceService', None)) - self.assertIsNotNone(getattr(test_pb2, 'TestServiceStub', None)) + self.assertIsNotNone(getattr(test_pb2, SERVICER_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, SERVER_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, STUB_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, SERVER_FACTORY_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, STUB_FACTORY_IDENTIFIER, None)) + + def testUpDown(self): + import test_pb2 + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) + request = test_pb2.SimpleRequest(response_size=13) + with server, stub: + pass def testUnaryCall(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) + servicer, stub, server = _CreateService(test_pb2, NO_DELAY) request = test_pb2.SimpleRequest(response_size=13) - response = stub.UnaryCall(request) - expected_response = servicer.UnaryCall(request) + with server, stub: + response = stub.UnaryCall(request, NORMAL_TIMEOUT) + expected_response = servicer.UnaryCall(request, None) self.assertEqual(expected_response, response) def testUnaryCallAsync(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService( - test_pb2, delay=self.delay, timeout=self.timeout) + servicer, stub, server = _CreateService(test_pb2, LONG_DELAY) request = test_pb2.SimpleRequest(response_size=13) - # TODO(atash): consider using the 'profile' module? Does it even work here? - start_time = time.clock() - response_future = stub.UnaryCall.async(request) - self.assertGreater(self.delay, time.clock() - start_time) - response = response_future.result() - expected_response = servicer.UnaryCall(request) + with server, stub: + start_time = time.clock() + response_future = stub.UnaryCall.async(request, LONG_TIMEOUT) + # Check that we didn't block on the asynchronous call. + self.assertGreater(LONG_DELAY, time.clock() - start_time) + response = response_future.result() + expected_response = servicer.UnaryCall(request, None) self.assertEqual(expected_response, response) def testUnaryCallAsyncExpired(self): import test_pb2 # pylint: disable=g-import-not-at-top # set the timeout super low... - servicer, stub = CreateService(test_pb2, delay=1, timeout=0.1) + servicer, stub, server = _CreateService(test_pb2, + delay=DOES_NOT_MATTER_DELAY) request = test_pb2.SimpleRequest(response_size=13) - with servicer.pause(): - response_future = stub.UnaryCall.async(request) - with self.assertRaises(exceptions.ExpirationError): - response_future.result() + with server, stub: + with servicer.pause(): + response_future = stub.UnaryCall.async(request, SHORT_TIMEOUT) + with self.assertRaises(exceptions.ExpirationError): + response_future.result() def testUnaryCallAsyncCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) request = test_pb2.SimpleRequest(response_size=13) - with servicer.pause(): - response_future = stub.UnaryCall.async(request) - response_future.cancel() - self.assertTrue(response_future.cancelled()) + with server, stub: + with servicer.pause(): + response_future = stub.UnaryCall.async(request, 1) + response_future.cancel() + self.assertTrue(response_future.cancelled()) def testUnaryCallAsyncFailed(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) request = test_pb2.SimpleRequest(response_size=13) - with servicer.fail(): - response_future = stub.UnaryCall.async(request) - self.assertIsNotNone(response_future.exception()) + with server, stub: + with servicer.fail(): + response_future = stub.UnaryCall.async(request, NORMAL_TIMEOUT) + self.assertIsNotNone(response_future.exception()) def testStreamingOutputCall(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) + servicer, stub, server = _CreateService(test_pb2, NO_DELAY) request = StreamingOutputRequest(test_pb2) - responses = stub.StreamingOutputCall(request) - expected_responses = servicer.StreamingOutputCall(request) - for check in itertools.izip_longest(expected_responses, responses): - expected_response, response = check - self.assertEqual(expected_response, response) - - def testStreamingOutputCallAsync(self): - import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2, timeout=self.timeout) - request = StreamingOutputRequest(test_pb2) - responses = stub.StreamingOutputCall.async(request) - expected_responses = servicer.StreamingOutputCall(request) - for check in itertools.izip_longest(expected_responses, responses): - expected_response, response = check - self.assertEqual(expected_response, response) - - def testStreamingOutputCallAsyncExpired(self): + with server, stub: + responses = stub.StreamingOutputCall(request, NORMAL_TIMEOUT) + expected_responses = servicer.StreamingOutputCall(request, None) + for check in itertools.izip_longest(expected_responses, responses): + expected_response, response = check + self.assertEqual(expected_response, response) + + def testStreamingOutputCallExpired(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2, timeout=0.1) + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) request = StreamingOutputRequest(test_pb2) - with servicer.pause(): - responses = stub.StreamingOutputCall.async(request) - with self.assertRaises(exceptions.ExpirationError): - list(responses) + with server, stub: + with servicer.pause(): + responses = stub.StreamingOutputCall(request, SHORT_TIMEOUT) + with self.assertRaises(exceptions.ExpirationError): + list(responses) - def testStreamingOutputCallAsyncCancelled(self): + def testStreamingOutputCallCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top - _, stub = CreateService(test_pb2, timeout=0.1) + unused_servicer, stub, server = _CreateService(test_pb2, + DOES_NOT_MATTER_DELAY) request = StreamingOutputRequest(test_pb2) - responses = stub.StreamingOutputCall.async(request) - next(responses) - responses.cancel() - with self.assertRaises(future.CancelledError): + with server, stub: + responses = stub.StreamingOutputCall(request, SHORT_TIMEOUT) next(responses) + responses.cancel() + with self.assertRaises(future.CancelledError): + next(responses) - def testStreamingOutputCallAsyncFailed(self): + @unittest.skip('TODO(atash,nathaniel): figure out why this times out ' + 'instead of raising the proper error.') + def testStreamingOutputCallFailed(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2, timeout=0.1) + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) request = StreamingOutputRequest(test_pb2) - with servicer.fail(): - responses = stub.StreamingOutputCall.async(request) - self.assertIsNotNone(responses) - with self.assertRaises(exceptions.ServicerError): - next(responses) + with server, stub: + with servicer.fail(): + responses = stub.StreamingOutputCall(request, 1) + self.assertIsNotNone(responses) + with self.assertRaises(exceptions.ServicerError): + next(responses) def testStreamingInputCall(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) - response = stub.StreamingInputCall(StreamingInputRequest(test_pb2)) + servicer, stub, server = _CreateService(test_pb2, NO_DELAY) + with server, stub: + response = stub.StreamingInputCall(StreamingInputRequest(test_pb2), + NORMAL_TIMEOUT) expected_response = servicer.StreamingInputCall( - StreamingInputRequest(test_pb2)) + StreamingInputRequest(test_pb2), None) self.assertEqual(expected_response, response) def testStreamingInputCallAsync(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService( - test_pb2, delay=self.delay, timeout=self.timeout) - start_time = time.clock() - response_future = stub.StreamingInputCall.async( - StreamingInputRequest(test_pb2)) - self.assertGreater(self.delay, time.clock() - start_time) - response = response_future.result() + servicer, stub, server = _CreateService( + test_pb2, LONG_DELAY) + with server, stub: + start_time = time.clock() + response_future = stub.StreamingInputCall.async( + StreamingInputRequest(test_pb2), LONG_TIMEOUT) + self.assertGreater(LONG_DELAY, time.clock() - start_time) + response = response_future.result() expected_response = servicer.StreamingInputCall( - StreamingInputRequest(test_pb2)) + StreamingInputRequest(test_pb2), None) self.assertEqual(expected_response, response) def testStreamingInputCallAsyncExpired(self): import test_pb2 # pylint: disable=g-import-not-at-top # set the timeout super low... - servicer, stub = CreateService(test_pb2, delay=1, timeout=0.1) - with servicer.pause(): - response_future = stub.StreamingInputCall.async( - StreamingInputRequest(test_pb2)) - with self.assertRaises(exceptions.ExpirationError): - response_future.result() - self.assertIsInstance( - response_future.exception(), exceptions.ExpirationError) + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) + with server, stub: + with servicer.pause(): + response_future = stub.StreamingInputCall.async( + StreamingInputRequest(test_pb2), SHORT_TIMEOUT) + with self.assertRaises(exceptions.ExpirationError): + response_future.result() + self.assertIsInstance( + response_future.exception(), exceptions.ExpirationError) def testStreamingInputCallAsyncCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) - with servicer.pause(): - response_future = stub.StreamingInputCall.async( - StreamingInputRequest(test_pb2)) - response_future.cancel() - self.assertTrue(response_future.cancelled()) - with self.assertRaises(future.CancelledError): - response_future.result() + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) + with server, stub: + with servicer.pause(): + response_future = stub.StreamingInputCall.async( + StreamingInputRequest(test_pb2), NORMAL_TIMEOUT) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + with self.assertRaises(future.CancelledError): + response_future.result() def testStreamingInputCallAsyncFailed(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) - with servicer.fail(): - response_future = stub.StreamingInputCall.async( - StreamingInputRequest(test_pb2)) - self.assertIsNotNone(response_future.exception()) + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) + with server, stub: + with servicer.fail(): + response_future = stub.StreamingInputCall.async( + StreamingInputRequest(test_pb2), SHORT_TIMEOUT) + self.assertIsNotNone(response_future.exception()) def testFullDuplexCall(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) - responses = stub.FullDuplexCall(FullDuplexRequest(test_pb2)) - expected_responses = servicer.FullDuplexCall(FullDuplexRequest(test_pb2)) - for check in itertools.izip_longest(expected_responses, responses): - expected_response, response = check - self.assertEqual(expected_response, response) - - def testFullDuplexCallAsync(self): + servicer, stub, server = _CreateService(test_pb2, NO_DELAY) + with server, stub: + responses = stub.FullDuplexCall(FullDuplexRequest(test_pb2), + NORMAL_TIMEOUT) + expected_responses = servicer.FullDuplexCall(FullDuplexRequest(test_pb2), + None) + for check in itertools.izip_longest(expected_responses, responses): + expected_response, response = check + self.assertEqual(expected_response, response) + + def testFullDuplexCallExpired(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2, timeout=self.timeout) - responses = stub.FullDuplexCall.async(FullDuplexRequest(test_pb2)) - expected_responses = servicer.FullDuplexCall(FullDuplexRequest(test_pb2)) - for check in itertools.izip_longest(expected_responses, responses): - expected_response, response = check - self.assertEqual(expected_response, response) - - def testFullDuplexCallAsyncExpired(self): - import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2, timeout=0.1) + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) request = FullDuplexRequest(test_pb2) - with servicer.pause(): - responses = stub.FullDuplexCall.async(request) - with self.assertRaises(exceptions.ExpirationError): - list(responses) + with server, stub: + with servicer.pause(): + responses = stub.FullDuplexCall(request, SHORT_TIMEOUT) + with self.assertRaises(exceptions.ExpirationError): + list(responses) - def testFullDuplexCallAsyncCancelled(self): + def testFullDuplexCallCancelled(self): import test_pb2 # pylint: disable=g-import-not-at-top - _, stub = CreateService(test_pb2, timeout=0.1) - request = FullDuplexRequest(test_pb2) - responses = stub.FullDuplexCall.async(request) - next(responses) - responses.cancel() - with self.assertRaises(future.CancelledError): + unused_servicer, stub, server = _CreateService(test_pb2, NO_DELAY) + with server, stub: + request = FullDuplexRequest(test_pb2) + responses = stub.FullDuplexCall(request, NORMAL_TIMEOUT) next(responses) + responses.cancel() + with self.assertRaises(future.CancelledError): + next(responses) - def testFullDuplexCallAsyncFailed(self): + @unittest.skip('TODO(atash,nathaniel): figure out why this hangs forever ' + 'and fix.') + def testFullDuplexCallFailed(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2, timeout=0.1) + servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY) request = FullDuplexRequest(test_pb2) - with servicer.fail(): - responses = stub.FullDuplexCall.async(request) - self.assertIsNotNone(responses) - with self.assertRaises(exceptions.ServicerError): - next(responses) + with server, stub: + with servicer.fail(): + responses = stub.FullDuplexCall(request, NORMAL_TIMEOUT) + self.assertIsNotNone(responses) + with self.assertRaises(exceptions.ServicerError): + next(responses) def testHalfDuplexCall(self): import test_pb2 # pylint: disable=g-import-not-at-top - servicer, stub = CreateService(test_pb2) + servicer, stub, server = _CreateService(test_pb2, NO_DELAY) def HalfDuplexRequest(): request = test_pb2.StreamingOutputCallRequest() request.response_parameters.add(size=1, interval_us=0) @@ -439,15 +474,16 @@ class PythonPluginTest(unittest.TestCase): request.response_parameters.add(size=2, interval_us=0) request.response_parameters.add(size=3, interval_us=0) yield request - responses = stub.HalfDuplexCall(HalfDuplexRequest()) - expected_responses = servicer.HalfDuplexCall(HalfDuplexRequest()) - for check in itertools.izip_longest(expected_responses, responses): - expected_response, response = check - self.assertEqual(expected_response, response) - - def testHalfDuplexCallAsyncWedged(self): + with server, stub: + responses = stub.HalfDuplexCall(HalfDuplexRequest(), NORMAL_TIMEOUT) + expected_responses = servicer.HalfDuplexCall(HalfDuplexRequest(), None) + for check in itertools.izip_longest(expected_responses, responses): + expected_response, response = check + self.assertEqual(expected_response, response) + + def testHalfDuplexCallWedged(self): import test_pb2 # pylint: disable=g-import-not-at-top - _, stub = CreateService(test_pb2, timeout=1) + _, stub, server = _CreateService(test_pb2, NO_DELAY) wait_flag = [False] @contextlib.contextmanager def wait(): # pylint: disable=invalid-name @@ -461,20 +497,25 @@ class PythonPluginTest(unittest.TestCase): yield request while wait_flag[0]: time.sleep(0.1) - with wait(): - responses = stub.HalfDuplexCall.async(HalfDuplexRequest()) - # half-duplex waits for the client to send all info - with self.assertRaises(exceptions.ExpirationError): - next(responses) + with server, stub: + with wait(): + responses = stub.HalfDuplexCall(HalfDuplexRequest(), NORMAL_TIMEOUT) + # half-duplex waits for the client to send all info + with self.assertRaises(exceptions.ExpirationError): + next(responses) if __name__ == '__main__': os.chdir(os.path.dirname(sys.argv[0])) - parser = argparse.ArgumentParser(description='Run Python compiler plugin test.') - parser.add_argument('--build_mode', dest='build_mode', type=str, default='dbg', - help='The build mode of the targets to test, e.g. ' - '"dbg", "opt", "asan", etc.') + parser = argparse.ArgumentParser( + description='Run Python compiler plugin test.') + parser.add_argument( + '--build_mode', dest='build_mode', type=str, default='dbg', + help='The build mode of the targets to test, e.g. "dbg", "opt", "asan", ' + 'etc.') + parser.add_argument('--port', dest='port', type=int, default=0) args, remainder = parser.parse_known_args() _build_mode = args.build_mode + _port = args.port sys.argv[1:] = remainder unittest.main() diff --git a/test/compiler/test.proto b/test/compiler/test.proto index ed7c6a7b797..1714de7c11b 100644 --- a/test/compiler/test.proto +++ b/test/compiler/test.proto @@ -32,7 +32,8 @@ // This file is duplicated around the code base. See GitHub issue #526. syntax = "proto2"; -package grpc.testing; +// TODO(atash): Investigate this statement's utility. +// package grpc.testing; enum PayloadType { // Compressable text format. diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh index fe40b511860..2475c37b0bc 100755 --- a/tools/run_tests/run_python.sh +++ b/tools/run_tests/run_python.sh @@ -37,7 +37,8 @@ root=`pwd` export LD_LIBRARY_PATH=$root/libs/opt source python2.7_virtual_environment/bin/activate # TODO(issue 215): Properly itemize these in run_tests.py so that they can be parallelized. -python2.7 -B test/compiler/python_plugin_test.py +# TODO(atash): Enable dynamic unused port discovery for this test. +python2.7 -B test/compiler/python_plugin_test.py --build_mode=opt --port=40987 python2.7 -B -m grpc._adapter._blocking_invocation_inline_service_test python2.7 -B -m grpc._adapter._c_test python2.7 -B -m grpc._adapter._event_invocation_synchronous_event_service_test From 8d6ec91241743d121d5540cb9e389de048690415 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 24 Feb 2015 20:07:59 -0800 Subject: [PATCH 12/27] Using HTTP2 compliant cipher suites by default. - Added a way to override the cipher suites with an environment variable so that we can still do interop testing with java7. - Takes care of #681. --- src/core/security/security_context.c | 33 +++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index 9dce5af7400..eb1dd1cc4a4 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -52,20 +52,33 @@ /* -- Constants. -- */ -/* Defines the cipher suites that we accept. All these cipher suites are - compliant with TLS 1.2 and use an RSA public key. We prefer GCM over CBC - and ECDHE-RSA over just RSA. */ -#define GRPC_SSL_CIPHER_SUITES \ - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:AES128-GCM-SHA256:" \ - "AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-" \ - "SHA256:AES256-SHA256" - #ifndef INSTALL_PREFIX static const char *installed_roots_path = "/usr/share/grpc/roots.pem"; #else static const char *installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem"; #endif +/* -- Cipher suites. -- */ + +/* Defines the cipher suites that we accept by default. All these cipher suites + are compliant with HTTP2. */ +#define GRPC_SSL_CIPHER_SUITES \ + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:AES128-GCM-SHA256:" \ + "AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384" + +static gpr_once cipher_suites_once = GPR_ONCE_INIT; +static const char *cipher_suites = NULL; + +static void init_cipher_suites(void) { + char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES"); + cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES; +} + +static const char *ssl_cipher_suites(void) { + gpr_once_init(&cipher_suites_once, init_cipher_suites); + return cipher_suites; +} + /* -- Common methods. -- */ grpc_security_status grpc_security_context_create_handshaker( @@ -487,7 +500,7 @@ grpc_security_status grpc_ssl_channel_security_context_create( result = tsi_create_ssl_client_handshaker_factory( config->pem_private_key, config->pem_private_key_size, config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs, - pem_root_certs_size, GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings, + pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", @@ -541,7 +554,7 @@ grpc_security_status grpc_ssl_server_security_context_create( (const unsigned char **)config->pem_cert_chains, config->pem_cert_chains_sizes, config->num_key_cert_pairs, config->pem_root_certs, config->pem_root_certs_size, - GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings, + ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", From d43f0c371387d2f667cf14f78caadad5701d25c5 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 24 Feb 2015 20:54:12 -0800 Subject: [PATCH 13/27] Addressing comments. --- src/core/security/security_context.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index eb1dd1cc4a4..c4fdc2b9400 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -62,9 +62,9 @@ static const char *installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem" /* Defines the cipher suites that we accept by default. All these cipher suites are compliant with HTTP2. */ -#define GRPC_SSL_CIPHER_SUITES \ - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:AES128-GCM-SHA256:" \ - "AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384" +#define GRPC_SSL_CIPHER_SUITES \ + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \ + "SHA384:ECDHE-RSA-AES256-GCM-SHA384" static gpr_once cipher_suites_once = GPR_ONCE_INIT; static const char *cipher_suites = NULL; From b5a79f62dec25afb34b16ff40e40c6f92d20ec65 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 24 Feb 2015 21:02:51 -0800 Subject: [PATCH 14/27] Fix mac build --- src/core/support/cpu_posix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/support/cpu_posix.c b/src/core/support/cpu_posix.c index 33c7b90b0b2..5f45fb0bc36 100644 --- a/src/core/support/cpu_posix.c +++ b/src/core/support/cpu_posix.c @@ -40,6 +40,7 @@ #include #include +#include static __thread char magic_thread_local; @@ -55,7 +56,7 @@ static void init_ncpus() { unsigned gpr_cpu_num_cores(void) { static gpr_once once = GPR_ONCE_INIT; - gpr_once_init(&once, init_num_cpus); + gpr_once_init(&once, init_ncpus); return ncpus; } From d1345ded70c390f4287072b2ec82a890bb980312 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 24 Feb 2015 21:55:20 -0800 Subject: [PATCH 15/27] Fix shutdown race in CHTTP2 After we have called closed() ensure that no other callbacks are ever made. --- src/core/transport/chttp2_transport.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index ccd8d0c3764..f8b1db8d25d 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -301,7 +301,7 @@ static void push_setting(transport *t, grpc_chttp2_setting_id id, gpr_uint32 value); static int prepare_callbacks(transport *t); -static void run_callbacks(transport *t); +static void run_callbacks(transport *t, const grpc_transport_callbacks *cb); static int prepare_write(transport *t); static void perform_write(transport *t, grpc_endpoint *ep); @@ -706,6 +706,7 @@ static void unlock(transport *t) { pending_goaway *goaways = NULL; grpc_endpoint *ep = t->ep; grpc_stream_op_buffer nuke_now; + const grpc_transport_callbacks *cb = t->cb; grpc_sopb_init(&nuke_now); if (t->nuke_later_sopb.nops) { @@ -725,7 +726,7 @@ static void unlock(transport *t) { } /* gather any callbacks that need to be made */ - if (!t->calling_back && t->cb) { + if (!t->calling_back && cb) { perform_callbacks = prepare_callbacks(t); if (perform_callbacks) { t->calling_back = 1; @@ -733,6 +734,7 @@ static void unlock(transport *t) { if (t->error_state == ERROR_STATE_SEEN) { call_closed = 1; t->calling_back = 1; + t->cb = NULL; /* no more callbacks */ t->error_state = ERROR_STATE_NOTIFIED; } if (t->num_pending_goaways) { @@ -754,16 +756,16 @@ static void unlock(transport *t) { /* perform some callbacks if necessary */ for (i = 0; i < num_goaways; i++) { - t->cb->goaway(t->cb_user_data, &t->base, goaways[i].status, - goaways[i].debug); + cb->goaway(t->cb_user_data, &t->base, goaways[i].status, + goaways[i].debug); } if (perform_callbacks) { - run_callbacks(t); + run_callbacks(t, cb); } if (call_closed) { - t->cb->closed(t->cb_user_data, &t->base); + cb->closed(t->cb_user_data, &t->base); } /* write some bytes if necessary */ @@ -1741,13 +1743,13 @@ static int prepare_callbacks(transport *t) { return n; } -static void run_callbacks(transport *t) { +static void run_callbacks(transport *t, const grpc_transport_callbacks *cb) { stream *s; while ((s = stream_list_remove_head(t, EXECUTING_CALLBACKS))) { size_t nops = s->callback_sopb.nops; s->callback_sopb.nops = 0; - t->cb->recv_batch(t->cb_user_data, &t->base, (grpc_stream *)s, - s->callback_sopb.ops, nops, s->callback_state); + cb->recv_batch(t->cb_user_data, &t->base, (grpc_stream *)s, + s->callback_sopb.ops, nops, s->callback_state); } } From cc1150f49f7374a76f2e29b9ab4fa4bc15fe02f1 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 24 Feb 2015 21:26:21 -0800 Subject: [PATCH 16/27] Adds a reference to GoogleAuth --- src/ruby/grpc.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec index bc59c234e5a..25a3ff5ce27 100755 --- a/src/ruby/grpc.gemspec +++ b/src/ruby/grpc.gemspec @@ -22,6 +22,7 @@ Gem::Specification.new do |s| s.add_dependency 'faraday', '~> 0.9' s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1' + s.add_dependency 'googleauth', '~> 0.1' s.add_dependency 'logging', '~> 1.8' s.add_dependency 'jwt', '~> 1.2.1' s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests From b44da465d6cc2488e7919358d0a7c3d08b964736 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 24 Feb 2015 21:29:11 -0800 Subject: [PATCH 17/27] Updates the interop client to use the new auth library --- src/ruby/bin/interop/interop_client.rb | 31 +++++++------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb index 76402b7c894..4e60ca0b71d 100755 --- a/src/ruby/bin/interop/interop_client.rb +++ b/src/ruby/bin/interop/interop_client.rb @@ -48,6 +48,7 @@ require 'minitest' require 'minitest/assertions' require 'grpc' +require 'googleauth' require 'google/protobuf' require 'test/cpp/interop/test_services' @@ -56,7 +57,7 @@ require 'test/cpp/interop/empty' require 'signet/ssl_config' -include GRPC::Auth +AUTH_ENV = Google::Auth::ServiceAccountCredentials::ENV_VAR # loads the certificates used to access the test server securely. def load_test_certs @@ -101,22 +102,14 @@ def create_stub(opts) } # Add service account creds if specified - if %w(all service_account_creds).include?(opts.test_case) + wants_creds = %w(all compute_engine_creds service_account_creds) + if wants_creds.include?(opts.test_case) unless opts.oauth_scope.nil? - fd = StringIO.new(File.read(opts.oauth_key_file)) - logger.info("loading oauth certs from #{opts.oauth_key_file}") - auth_creds = ServiceAccountCredentials.new(opts.oauth_scope, fd) + auth_creds = Google::Auth.get_application_default(opts.oauth_scope) stub_opts[:update_metadata] = auth_creds.updater_proc end end - # Add compute engine creds if specified - if %w(all compute_engine_creds).include?(opts.test_case) - unless opts.oauth_scope.nil? - stub_opts[:update_metadata] = GCECredentials.new.update_proc - end - end - logger.info("... connecting securely to #{address}") Grpc::Testing::TestService::Stub.new(address, **stub_opts) else @@ -193,11 +186,11 @@ class NamedTests def service_account_creds # ignore this test if the oauth options are not set - if @args.oauth_scope.nil? || @args.oauth_key_file.nil? + if @args.oauth_scope.nil? p 'NOT RUN: service_account_creds; no service_account settings' return end - json_key = File.read(@args.oauth_key_file) + json_key = File.read(ENV[AUTH_ENV]) wanted_email = MultiJson.load(json_key)['client_email'] resp = perform_large_unary(fill_username: true, fill_oauth_scope: true) @@ -285,7 +278,7 @@ end # Args is used to hold the command line info. Args = Struct.new(:default_service_account, :host, :host_override, - :oauth_scope, :oauth_key_file, :port, :secure, :test_case, + :oauth_scope, :port, :secure, :test_case, :use_test_ca) # validates the the command line options, returning them as a Hash. @@ -302,10 +295,6 @@ def parse_args 'email address of the default service account') do |v| args['default_service_account'] = v end - opts.on('--service_account_key_file PATH', - 'Path to the service account json key file') do |v| - args['oauth_key_file'] = v - end opts.on('--server_host_override HOST_OVERRIDE', 'override host via a HTTP header') do |v| args['host_override'] = v @@ -333,10 +322,6 @@ def _check_args(args) fail(OptionParser::MissingArgument, "please specify --#{arg}") end end - if args['oauth_key_file'].nil? ^ args['oauth_scope'].nil? - fail(OptionParser::MissingArgument, - 'please specify both of --service_account_key_file and --oauth_scope') - end args end From 2731d3f40db0bbbfeb2b9fb0f5abb4c8de077790 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 24 Feb 2015 21:56:22 -0800 Subject: [PATCH 18/27] Updates the pubsub demo to use the new auth library --- src/ruby/bin/apis/pubsub_demo.rb | 35 +++++++++++--------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/ruby/bin/apis/pubsub_demo.rb b/src/ruby/bin/apis/pubsub_demo.rb index 6656a561309..9bb324ff646 100755 --- a/src/ruby/bin/apis/pubsub_demo.rb +++ b/src/ruby/bin/apis/pubsub_demo.rb @@ -31,10 +31,9 @@ # pubsub_demo demos accesses the Google PubSub API via its gRPC interface # -# TODO: update the Usage once the usable auth gem is available -# $ SSL_CERT_FILE= \ +# $ GOOGLE_APPLICATION_CREDENTIALS= \ +# SSL_CERT_FILE= \ # path/to/pubsub_demo.rb \ -# --service_account_key_file= \ # [--action= ] # # There are options related to the chosen action, see #parse_args below. @@ -49,6 +48,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'optparse' require 'grpc' +require 'googleauth' require 'google/protobuf' require 'google/protobuf/empty' @@ -59,7 +59,9 @@ require 'tech/pubsub/proto/pubsub_services' def load_prod_cert fail 'could not find a production cert' if ENV['SSL_CERT_FILE'].nil? p "loading prod certs from #{ENV['SSL_CERT_FILE']}" - File.open(ENV['SSL_CERT_FILE']).read + File.open(ENV['SSL_CERT_FILE']) do |f| + return f.read + end end # creates a SSL Credentials from the production certificates. @@ -68,14 +70,9 @@ def ssl_creds end # Builds the metadata authentication update proc. -# -# TODO: replace this once the ruby usable auth repo is available. def auth_proc(opts) - if GRPC::Auth::GCECredentials.on_gce? - return GRPC::Auth::GCECredentials.new.updater_proc - end - fd = StringIO.new(File.read(opts.oauth_key_file)) - GRPC::Auth::ServiceAccountCredentials.new(opts.oauth_scope, fd).updater_proc + auth_creds = Google::Auth.get_application_default(opts.oauth_scope) + return auth_creds.updater_proc end # Creates a stub for accessing the publisher service. @@ -216,14 +213,14 @@ class NamedActions end # Args is used to hold the command line info. -Args = Struct.new(:host, :oauth_scope, :oauth_key_file, :port, :action, - :project_id, :topic_name, :sub_name) +Args = Struct.new(:host, :oauth_scope, :port, :action, :project_id, :topic_name, + :sub_name) # validates the the command line options, returning them as an Arg. def parse_args args = Args.new('pubsub-staging.googleapis.com', 'https://www.googleapis.com/auth/pubsub', - nil, 443, 'list_some_topics', 'stoked-keyword-656') + 443, 'list_some_topics', 'stoked-keyword-656') OptionParser.new do |opts| opts.on('--oauth_scope scope', 'Scope for OAuth tokens') { |v| args['oauth_scope'] = v } @@ -233,10 +230,6 @@ def parse_args opts.on('--server_port SERVER_PORT', 'server port') do |v| args.port = v end - opts.on('--service_account_key_file PATH', - 'Path to the service account json key file') do |v| - args.oauth_key_file = v - end # instance_methods(false) gives only the methods defined in that class. scenes = NamedActions.instance_methods(false).map { |t| t.to_s } @@ -257,15 +250,11 @@ def parse_args end def _check_args(args) - %w(host port action).each do |a| + %w(host port action oauth_scope).each do |a| if args[a].nil? raise OptionParser::MissingArgument.new("please specify --#{a}") end end - if args['oauth_key_file'].nil? || args['oauth_scope'].nil? - fail(OptionParser::MissingArgument, - 'please specify both of --service_account_key_file and --oauth_scope') - end args end From 494f2f9706cc7491e111a819f8d3ea6ecd37170d Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Tue, 24 Feb 2015 22:00:42 -0800 Subject: [PATCH 19/27] Remove the ruby gRPC auth implementation --- src/ruby/lib/grpc.rb | 2 - src/ruby/lib/grpc/auth/compute_engine.rb | 67 --------- src/ruby/lib/grpc/auth/service_account.rb | 66 --------- src/ruby/lib/grpc/auth/signet.rb | 67 --------- src/ruby/spec/auth/apply_auth_examples.rb | 163 --------------------- src/ruby/spec/auth/compute_engine_spec.rb | 108 -------------- src/ruby/spec/auth/service_account_spec.rb | 75 ---------- src/ruby/spec/auth/signet_spec.rb | 70 --------- 8 files changed, 618 deletions(-) delete mode 100644 src/ruby/lib/grpc/auth/compute_engine.rb delete mode 100644 src/ruby/lib/grpc/auth/service_account.rb delete mode 100644 src/ruby/lib/grpc/auth/signet.rb delete mode 100644 src/ruby/spec/auth/apply_auth_examples.rb delete mode 100644 src/ruby/spec/auth/compute_engine_spec.rb delete mode 100644 src/ruby/spec/auth/service_account_spec.rb delete mode 100644 src/ruby/spec/auth/signet_spec.rb diff --git a/src/ruby/lib/grpc.rb b/src/ruby/lib/grpc.rb index a2a609f59ee..dd02ef7666a 100644 --- a/src/ruby/lib/grpc.rb +++ b/src/ruby/lib/grpc.rb @@ -27,8 +27,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -require 'grpc/auth/compute_engine.rb' -require 'grpc/auth/service_account.rb' require 'grpc/errors' require 'grpc/grpc' require 'grpc/logconfig' diff --git a/src/ruby/lib/grpc/auth/compute_engine.rb b/src/ruby/lib/grpc/auth/compute_engine.rb deleted file mode 100644 index 5cb1e1a4dcf..00000000000 --- a/src/ruby/lib/grpc/auth/compute_engine.rb +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -require 'faraday' -require 'grpc/auth/signet' - -module GRPC - # Module Auth provides classes that provide Google-specific authentication - # used to access Google gRPC services. - module Auth - # Extends Signet::OAuth2::Client so that the auth token is obtained from - # the GCE metadata server. - class GCECredentials < Signet::OAuth2::Client - COMPUTE_AUTH_TOKEN_URI = 'http://metadata/computeMetadata/v1/'\ - 'instance/service-accounts/default/token' - COMPUTE_CHECK_URI = 'http://metadata.google.internal' - - # Detect if this appear to be a GCE instance, by checking if metadata - # is available - def self.on_gce?(options = {}) - c = options[:connection] || Faraday.default_connection - resp = c.get(COMPUTE_CHECK_URI) - return false unless resp.status == 200 - return false unless resp.headers.key?('Metadata-Flavor') - return resp.headers['Metadata-Flavor'] == 'Google' - rescue Faraday::ConnectionFailed - return false - end - - # Overrides the super class method to change how access tokens are - # fetched. - def fetch_access_token(options = {}) - c = options[:connection] || Faraday.default_connection - c.headers = { 'Metadata-Flavor' => 'Google' } - resp = c.get(COMPUTE_AUTH_TOKEN_URI) - Signet::OAuth2.parse_credentials(resp.body, - resp.headers['content-type']) - end - end - end -end diff --git a/src/ruby/lib/grpc/auth/service_account.rb b/src/ruby/lib/grpc/auth/service_account.rb deleted file mode 100644 index 14b81a9e034..00000000000 --- a/src/ruby/lib/grpc/auth/service_account.rb +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -require 'grpc/auth/signet' -require 'multi_json' -require 'openssl' - -# Reads the private key and client email fields from service account JSON key. -def read_json_key(json_key_io) - json_key = MultiJson.load(json_key_io.read) - fail 'missing client_email' unless json_key.key?('client_email') - fail 'missing private_key' unless json_key.key?('private_key') - [json_key['private_key'], json_key['client_email']] -end - -module GRPC - # Module Auth provides classes that provide Google-specific authentication - # used to access Google gRPC services. - module Auth - # Authenticates requests using Google's Service Account credentials. - # (cf https://developers.google.com/accounts/docs/OAuth2ServiceAccount) - class ServiceAccountCredentials < Signet::OAuth2::Client - TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token' - AUDIENCE = TOKEN_CRED_URI - - # Initializes a ServiceAccountCredentials. - # - # @param scope [string|array] the scope(s) to access - # @param json_key_io [IO] an IO from which the JSON key can be read - def initialize(scope, json_key_io) - private_key, client_email = read_json_key(json_key_io) - super(token_credential_uri: TOKEN_CRED_URI, - audience: AUDIENCE, - scope: scope, - issuer: client_email, - signing_key: OpenSSL::PKey::RSA.new(private_key)) - end - end - end -end diff --git a/src/ruby/lib/grpc/auth/signet.rb b/src/ruby/lib/grpc/auth/signet.rb deleted file mode 100644 index a8bce1255c2..00000000000 --- a/src/ruby/lib/grpc/auth/signet.rb +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -require 'signet/oauth_2/client' - -module Signet - # Signet::OAuth2 supports OAuth2 authentication. - module OAuth2 - AUTH_METADATA_KEY = :Authorization - # Signet::OAuth2::Client creates an OAuth2 client - # - # Here client is re-opened to add the #apply and #apply! methods which - # update a hash map with the fetched authentication token - # - # Eventually, this change may be merged into signet itself, or some other - # package that provides Google-specific auth via signet, and this extension - # will be unnecessary. - class Client - # Updates a_hash updated with the authentication token - def apply!(a_hash, opts = {}) - # fetch the access token there is currently not one, or if the client - # has expired - fetch_access_token!(opts) if access_token.nil? || expired? - a_hash[AUTH_METADATA_KEY] = "Bearer #{access_token}" - end - - # Returns a clone of a_hash updated with the authentication token - def apply(a_hash, opts = {}) - a_copy = a_hash.clone - apply!(a_copy, opts) - a_copy - end - - # Returns a reference to the #apply method, suitable for passing as - # a closure - def updater_proc - lambda(&method(:apply)) - end - end - end -end diff --git a/src/ruby/spec/auth/apply_auth_examples.rb b/src/ruby/spec/auth/apply_auth_examples.rb deleted file mode 100644 index 09b393026f0..00000000000 --- a/src/ruby/spec/auth/apply_auth_examples.rb +++ /dev/null @@ -1,163 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.uniq! - -require 'faraday' -require 'spec_helper' - -def build_json_response(payload) - [200, - { 'Content-Type' => 'application/json; charset=utf-8' }, - MultiJson.dump(payload)] -end - -WANTED_AUTH_KEY = :Authorization - -shared_examples 'apply/apply! are OK' do - # tests that use these examples need to define - # - # @client which should be an auth client - # - # @make_auth_stubs, which should stub out the expected http behaviour of the - # auth client - describe '#fetch_access_token' do - it 'should set access_token to the fetched value' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - @client.fetch_access_token!(connection: c) - expect(@client.access_token).to eq(token) - stubs.verify_stubbed_calls - end - end - - describe '#apply!' do - it 'should update the target hash with fetched access token' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - md = { foo: 'bar' } - @client.apply!(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" } - expect(md).to eq(want) - stubs.verify_stubbed_calls - end - end - - describe 'updater_proc' do - it 'should provide a proc that updates a hash with the access token' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - md = { foo: 'bar' } - the_proc = @client.updater_proc - got = the_proc.call(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" } - expect(got).to eq(want) - stubs.verify_stubbed_calls - end - end - - describe '#apply' do - it 'should not update the original hash with the access token' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - md = { foo: 'bar' } - @client.apply(md, connection: c) - want = { foo: 'bar' } - expect(md).to eq(want) - stubs.verify_stubbed_calls - end - - it 'should add the token to the returned hash' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - md = { foo: 'bar' } - got = @client.apply(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" } - expect(got).to eq(want) - stubs.verify_stubbed_calls - end - - it 'should not fetch a new token if the current is not expired' do - token = '1/abcdef1234567890' - stubs = make_auth_stubs with_access_token: token - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - - n = 5 # arbitrary - n.times do |_t| - md = { foo: 'bar' } - got = @client.apply(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" } - expect(got).to eq(want) - end - stubs.verify_stubbed_calls - end - - it 'should fetch a new token if the current one is expired' do - token_1 = '1/abcdef1234567890' - token_2 = '2/abcdef1234567890' - - [token_1, token_2].each do |t| - stubs = make_auth_stubs with_access_token: t - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - md = { foo: 'bar' } - got = @client.apply(md, connection: c) - want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{t}" } - expect(got).to eq(want) - stubs.verify_stubbed_calls - @client.expires_at -= 3601 # default is to expire in 1hr - end - end - end -end diff --git a/src/ruby/spec/auth/compute_engine_spec.rb b/src/ruby/spec/auth/compute_engine_spec.rb deleted file mode 100644 index c43214d0861..00000000000 --- a/src/ruby/spec/auth/compute_engine_spec.rb +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.uniq! - -require 'apply_auth_examples' -require 'faraday' -require 'grpc/auth/compute_engine' -require 'spec_helper' - -describe GRPC::Auth::GCECredentials do - MD_URI = '/computeMetadata/v1/instance/service-accounts/default/token' - GCECredentials = GRPC::Auth::GCECredentials - - before(:example) do - @client = GCECredentials.new - end - - def make_auth_stubs(with_access_token: '') - Faraday::Adapter::Test::Stubs.new do |stub| - stub.get(MD_URI) do |env| - headers = env[:request_headers] - expect(headers['Metadata-Flavor']).to eq('Google') - build_json_response( - 'access_token' => with_access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600) - end - end - end - - it_behaves_like 'apply/apply! are OK' - - describe '#on_gce?' do - it 'should be true when Metadata-Flavor is Google' do - stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/') do |_env| - [200, - { 'Metadata-Flavor' => 'Google' }, - ''] - end - end - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - expect(GCECredentials.on_gce?(connection: c)).to eq(true) - stubs.verify_stubbed_calls - end - - it 'should be false when Metadata-Flavor is not Google' do - stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/') do |_env| - [200, - { 'Metadata-Flavor' => 'NotGoogle' }, - ''] - end - end - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - expect(GCECredentials.on_gce?(connection: c)).to eq(false) - stubs.verify_stubbed_calls - end - - it 'should be false if the response is not 200' do - stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/') do |_env| - [404, - { 'Metadata-Flavor' => 'Google' }, - ''] - end - end - c = Faraday.new do |b| - b.adapter(:test, stubs) - end - expect(GCECredentials.on_gce?(connection: c)).to eq(false) - stubs.verify_stubbed_calls - end - end -end diff --git a/src/ruby/spec/auth/service_account_spec.rb b/src/ruby/spec/auth/service_account_spec.rb deleted file mode 100644 index 2f14a1ae053..00000000000 --- a/src/ruby/spec/auth/service_account_spec.rb +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.uniq! - -require 'apply_auth_examples' -require 'grpc/auth/service_account' -require 'jwt' -require 'multi_json' -require 'openssl' -require 'spec_helper' - -describe GRPC::Auth::ServiceAccountCredentials do - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) - cred_json = { - private_key_id: 'a_private_key_id', - private_key: @key.to_pem, - client_email: 'app@developer.gserviceaccount.com', - client_id: 'app.apps.googleusercontent.com', - type: 'service_account' - } - cred_json_text = MultiJson.dump(cred_json) - @client = GRPC::Auth::ServiceAccountCredentials.new( - 'https://www.googleapis.com/auth/userinfo.profile', - StringIO.new(cred_json_text)) - end - - def make_auth_stubs(with_access_token: '') - Faraday::Adapter::Test::Stubs.new do |stub| - stub.post('/oauth2/v3/token') do |env| - params = Addressable::URI.form_unencode(env[:body]) - _claim, _header = JWT.decode(params.assoc('assertion').last, - @key.public_key) - want = ['grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer'] - expect(params.assoc('grant_type')).to eq(want) - build_json_response( - 'access_token' => with_access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600 - ) - end - end - end - - it_behaves_like 'apply/apply! are OK' -end diff --git a/src/ruby/spec/auth/signet_spec.rb b/src/ruby/spec/auth/signet_spec.rb deleted file mode 100644 index 1712edf2961..00000000000 --- a/src/ruby/spec/auth/signet_spec.rb +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -spec_dir = File.expand_path(File.join(File.dirname(__FILE__))) -$LOAD_PATH.unshift(spec_dir) -$LOAD_PATH.uniq! - -require 'apply_auth_examples' -require 'grpc/auth/signet' -require 'jwt' -require 'openssl' -require 'spec_helper' - -describe Signet::OAuth2::Client do - before(:example) do - @key = OpenSSL::PKey::RSA.new(2048) - @client = Signet::OAuth2::Client.new( - token_credential_uri: 'https://accounts.google.com/o/oauth2/token', - scope: 'https://www.googleapis.com/auth/userinfo.profile', - issuer: 'app@example.com', - audience: 'https://accounts.google.com/o/oauth2/token', - signing_key: @key - ) - end - - def make_auth_stubs(with_access_token: '') - Faraday::Adapter::Test::Stubs.new do |stub| - stub.post('/o/oauth2/token') do |env| - params = Addressable::URI.form_unencode(env[:body]) - _claim, _header = JWT.decode(params.assoc('assertion').last, - @key.public_key) - want = ['grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer'] - expect(params.assoc('grant_type')).to eq(want) - build_json_response( - 'access_token' => with_access_token, - 'token_type' => 'Bearer', - 'expires_in' => 3600 - ) - end - end - end - - it_behaves_like 'apply/apply! are OK' -end From fa4a4b52d80304e21dfbab85e867fda922e69f67 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Wed, 25 Feb 2015 06:06:27 -0800 Subject: [PATCH 20/27] Updates the docker test commands --- tools/gce_setup/grpc_docker.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh index bbc138c6beb..54cec2f1440 100755 --- a/tools/gce_setup/grpc_docker.sh +++ b/tools/gce_setup/grpc_docker.sh @@ -975,9 +975,10 @@ grpc_cloud_prod_auth_service_account_creds_gen_ruby_cmd() { local test_script="/var/local/git/grpc/src/ruby/bin/interop/interop_client.rb" local test_script+=" --use_tls" local gfe_flags=$(_grpc_prod_gfe_flags) - local added_gfe_flags=$(_grpc_svc_acc_test_flags) + local added_gfe_flags=$(_grpc_default_creds_test_flags) local env_prefix="SSL_CERT_FILE=/cacerts/roots.pem" - local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $added_gfe_flag $@'" + env_prefix+=" GOOGLE_APPLICATION_CREDENTIALS=/service_account/stubbyCloudTestingTest-7dd63462c60c.json" + local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $added_gfe_flags $@'" echo $the_cmd } @@ -1170,6 +1171,11 @@ _grpc_svc_acc_test_flags() { echo " --service_account_key_file=/service_account/stubbyCloudTestingTest-7dd63462c60c.json --oauth_scope=https://www.googleapis.com/auth/xapi.zoo" } +# default credentials test flag +_grpc_default_creds_test_flags() { + echo " --oauth_scope=https://www.googleapis.com/auth/xapi.zoo" +} + # outputs the flags passed to the gcloud auth tests _grpc_gce_test_flags() { echo " --default_service_account=155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel@developer.gserviceaccount.com --oauth_scope=https://www.googleapis.com/auth/xapi.zoo" From 635dbbe2fcb58be1bcd9086917488c5de5a90a5a Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Wed, 25 Feb 2015 06:17:00 -0800 Subject: [PATCH 21/27] Fixes the GCE creds test flags --- tools/gce_setup/grpc_docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh index 54cec2f1440..117edd55ba0 100755 --- a/tools/gce_setup/grpc_docker.sh +++ b/tools/gce_setup/grpc_docker.sh @@ -994,7 +994,7 @@ grpc_cloud_prod_auth_compute_engine_creds_gen_ruby_cmd() { local gfe_flags=$(_grpc_prod_gfe_flags) local added_gfe_flags=$(_grpc_gce_test_flags) local env_prefix="SSL_CERT_FILE=/cacerts/roots.pem" - local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $added_gfe_flag $@'" + local the_cmd="$cmd_prefix '$env_prefix ruby $test_script $gfe_flags $added_gfe_flags $@'" echo $the_cmd } From 5339814591c41c845996cba7ed9d83c506922de4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 24 Feb 2015 08:21:57 -0800 Subject: [PATCH 22/27] Added ability for c# to redirect C core logs to arbitrary sink --- src/csharp/Grpc.Core/Grpc.Core.csproj | 7 +- src/csharp/Grpc.Core/GrpcEnvironment.cs | 1 + src/csharp/Grpc.Core/Internal/GrpcLog.cs | 94 ++++++++++++++++++++++++ src/csharp/ext/grpc_csharp_ext.c | 24 +++++- 4 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 src/csharp/Grpc.Core/Internal/GrpcLog.cs diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 135ce26cbd2..6156b2f38bb 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -1,4 +1,4 @@ - + Debug @@ -33,6 +33,7 @@ + @@ -66,8 +67,4 @@ - - - - \ No newline at end of file diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs index 0e3a0a581cd..d3a8da4729e 100644 --- a/src/csharp/Grpc.Core/GrpcEnvironment.cs +++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs @@ -107,6 +107,7 @@ namespace Grpc.Core /// private GrpcEnvironment() { + GrpcLog.RedirectNativeLogs(Console.Error); grpcsharp_init(); threadPool = new GrpcThreadPool(THREAD_POOL_SIZE); threadPool.Start(); diff --git a/src/csharp/Grpc.Core/Internal/GrpcLog.cs b/src/csharp/Grpc.Core/Internal/GrpcLog.cs new file mode 100644 index 00000000000..98768d05c6d --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/GrpcLog.cs @@ -0,0 +1,94 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Grpc.Core.Internal +{ + internal delegate void GprLogDelegate(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr); + + /// + /// Logs from gRPC C core library can get lost if your application is not a console app. + /// This class allows redirection of logs to arbitrary destination. + /// + internal static class GrpcLog + { + static object staticLock = new object(); + static GprLogDelegate writeCallback; + static TextWriter dest; + + [DllImport("grpc_csharp_ext.dll")] + static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + /// + /// Sets text writer as destination for logs from native gRPC C core library. + /// Only first invocation has effect. + /// + /// + public static void RedirectNativeLogs(TextWriter textWriter) + { + lock (staticLock) + { + if (writeCallback == null) + { + writeCallback = new GprLogDelegate(HandleWrite); + dest = textWriter; + grpcsharp_redirect_log(writeCallback); + } + } + } + + private static void HandleWrite(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr) + { + try + { + // TODO: DateTime format used here is different than in C core. + dest.WriteLine(string.Format("{0}{1} {2} {3}:{4}: {5}", + Marshal.PtrToStringAnsi(severityStringPtr), DateTime.Now, + threadId, + Marshal.PtrToStringAnsi(fileStringPtr), + line, + Marshal.PtrToStringAnsi(msgPtr))); + } + catch (Exception e) + { + Console.WriteLine("Caught exception in native callback " + e); + } + } + } +} diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 18e0431e3b2..3cdeaef715f 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -35,9 +35,10 @@ #include #include -#include #include #include +#include +#include #include @@ -579,6 +580,27 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq, &(ctx->server_rpc_new.request_metadata), cq, ctx); } +/* Logging */ + +typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, + gpr_int32 line, + gpr_uint64 thd_id, + const char *severity_string, + const char *msg); +static grpcsharp_log_func log_func = NULL; + +/* Redirects gpr_log to log_func callback */ +static void grpcsharp_log_handler(gpr_log_func_args *args) { + log_func(args->file, args->line, gpr_thd_currentid(), + gpr_log_severity_string(args->severity), args->message); +} + +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_redirect_log(grpcsharp_log_func func) { + GPR_ASSERT(func); + log_func = func; + gpr_set_log_function(grpcsharp_log_handler); +} /* For testing */ GPR_EXPORT void GPR_CALLTYPE From abf22022465f628fce764e1f5a775310c0317973 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 24 Feb 2015 08:43:02 -0800 Subject: [PATCH 23/27] grpc_csharp_ext.dll added to the project to force automatic copying to the output dir --- src/csharp/Grpc.Core/Grpc.Core.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 6156b2f38bb..f88c9b373fe 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -66,5 +66,10 @@ + + + PreserveNewest + + \ No newline at end of file From 5ffb4c33dcffa83677370ee4e46ccee665ecedea Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 24 Feb 2015 09:07:42 -0800 Subject: [PATCH 24/27] Include grpc_csharp_ext.dll only under Windows --- src/csharp/Grpc.Core/Grpc.Core.csproj | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index f88c9b373fe..b5c15ee374f 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -66,10 +66,17 @@ - - - PreserveNewest - - + + + + + + PreserveNewest + + + + + \ No newline at end of file From b17b00b5410fdcc253f2e1c14c37ed093ff4cf95 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 24 Feb 2015 09:13:48 -0800 Subject: [PATCH 25/27] Fix to make the conditional include under Windows --- src/csharp/Grpc.Core/Grpc.Core.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index b5c15ee374f..183c4423583 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -69,7 +69,7 @@ - + PreserveNewest From 363eb8e27befc10dcff85aaadcbbf5d651c2394e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 25 Feb 2015 09:50:46 -0800 Subject: [PATCH 26/27] Fix read through null pointer --- src/core/tsi/ssl_transport_security.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c index 9ca8e6ddc98..8446cc4fdc2 100644 --- a/src/core/tsi/ssl_transport_security.c +++ b/src/core/tsi/ssl_transport_security.c @@ -1094,8 +1094,9 @@ static int does_entry_match_name(const char* entry, size_t entry_length, return 0; } name_subdomain = strchr(name, '.'); + if (name_subdomain == NULL) return 0; name_subdomain_length = strlen(name_subdomain); - if (name_subdomain == NULL || name_subdomain_length < 2) return 0; + if (name_subdomain_length < 2) return 0; name_subdomain++; /* Starts after the dot. */ name_subdomain_length--; entry += 2; /* Remove *. */ From 44553b5810939042665d966efb0d83f98bb7398c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 25 Feb 2015 09:52:18 -0800 Subject: [PATCH 27/27] clang-format --- src/csharp/ext/grpc_csharp_ext.c | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 3cdeaef715f..8f5a4141872 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -346,14 +346,19 @@ grpcsharp_call_start_unary(grpc_call *call, callback_funcptr callback, /* Synchronous unary call */ GPR_EXPORT void GPR_CALLTYPE -grpcsharp_call_blocking_unary(grpc_call *call, grpc_completion_queue *dedicated_cq, callback_funcptr callback, - const char *send_buffer, size_t send_buffer_len) { - GPR_ASSERT(grpcsharp_call_start_unary(call, callback, send_buffer, send_buffer_len) == GRPC_CALL_OK); +grpcsharp_call_blocking_unary(grpc_call *call, + grpc_completion_queue *dedicated_cq, + callback_funcptr callback, + const char *send_buffer, size_t send_buffer_len) { + GPR_ASSERT(grpcsharp_call_start_unary(call, callback, send_buffer, + send_buffer_len) == GRPC_CALL_OK); /* TODO: we would like to use pluck, but we don't know the tag */ - GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) == GRPC_OP_COMPLETE); + GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) == + GRPC_OP_COMPLETE); grpc_completion_queue_shutdown(dedicated_cq); - GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) == GRPC_QUEUE_SHUTDOWN); + GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) == + GRPC_QUEUE_SHUTDOWN); } GPR_EXPORT grpc_call_error GPR_CALLTYPE @@ -582,24 +587,22 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq, /* Logging */ -typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, - gpr_int32 line, - gpr_uint64 thd_id, - const char *severity_string, - const char *msg); +typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, gpr_int32 line, + gpr_uint64 thd_id, + const char *severity_string, + const char *msg); static grpcsharp_log_func log_func = NULL; /* Redirects gpr_log to log_func callback */ static void grpcsharp_log_handler(gpr_log_func_args *args) { - log_func(args->file, args->line, gpr_thd_currentid(), - gpr_log_severity_string(args->severity), args->message); + log_func(args->file, args->line, gpr_thd_currentid(), + gpr_log_severity_string(args->severity), args->message); } -GPR_EXPORT void GPR_CALLTYPE -grpcsharp_redirect_log(grpcsharp_log_func func) { - GPR_ASSERT(func); - log_func = func; - gpr_set_log_function(grpcsharp_log_handler); +GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) { + GPR_ASSERT(func); + log_func = func; + gpr_set_log_function(grpcsharp_log_handler); } /* For testing */ @@ -609,7 +612,4 @@ grpcsharp_test_callback(callback_funcptr callback) { } /* For testing */ -GPR_EXPORT void *GPR_CALLTYPE -grpcsharp_test_nop(void *ptr) { - return ptr; -} +GPR_EXPORT void *GPR_CALLTYPE grpcsharp_test_nop(void *ptr) { return ptr; }