|  | @@ -46,47 +46,18 @@ namespace Grpc.Core.Tests
 | 
	
		
			
				|  |  |      public class ClientServerTest
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |          const string Host = "127.0.0.1";
 | 
	
		
			
				|  |  | -        const string ServiceName = "tests.Test";
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        static readonly Method<string, string> EchoMethod = new Method<string, string>(
 | 
	
		
			
				|  |  | -            MethodType.Unary,
 | 
	
		
			
				|  |  | -            ServiceName,
 | 
	
		
			
				|  |  | -            "Echo",
 | 
	
		
			
				|  |  | -            Marshallers.StringMarshaller,
 | 
	
		
			
				|  |  | -            Marshallers.StringMarshaller);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        static readonly Method<string, string> ConcatAndEchoMethod = new Method<string, string>(
 | 
	
		
			
				|  |  | -            MethodType.ClientStreaming,
 | 
	
		
			
				|  |  | -            ServiceName,
 | 
	
		
			
				|  |  | -            "ConcatAndEcho",
 | 
	
		
			
				|  |  | -            Marshallers.StringMarshaller,
 | 
	
		
			
				|  |  | -            Marshallers.StringMarshaller);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        static readonly Method<string, string> NonexistentMethod = new Method<string, string>(
 | 
	
		
			
				|  |  | -            MethodType.Unary,
 | 
	
		
			
				|  |  | -            ServiceName,
 | 
	
		
			
				|  |  | -            "NonexistentMethod",
 | 
	
		
			
				|  |  | -            Marshallers.StringMarshaller,
 | 
	
		
			
				|  |  | -            Marshallers.StringMarshaller);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        static readonly ServerServiceDefinition ServiceDefinition = ServerServiceDefinition.CreateBuilder(ServiceName)
 | 
	
		
			
				|  |  | -            .AddMethod(EchoMethod, EchoHandler)
 | 
	
		
			
				|  |  | -            .AddMethod(ConcatAndEchoMethod, ConcatAndEchoHandler)
 | 
	
		
			
				|  |  | -            .Build();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        MockServiceHelper helper;
 | 
	
		
			
				|  |  |          Server server;
 | 
	
		
			
				|  |  |          Channel channel;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [SetUp]
 | 
	
		
			
				|  |  |          public void Init()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            server = new Server
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Services = { ServiceDefinition },
 | 
	
		
			
				|  |  | -                Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
 | 
	
		
			
				|  |  | -            };
 | 
	
		
			
				|  |  | +            helper = new MockServiceHelper(Host);
 | 
	
		
			
				|  |  | +            server = helper.GetServer();
 | 
	
		
			
				|  |  |              server.Start();
 | 
	
		
			
				|  |  | -            channel = new Channel(Host, server.Ports.Single().BoundPort, Credentials.Insecure);
 | 
	
		
			
				|  |  | +            channel = helper.GetChannel();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [TearDown]
 | 
	
	
		
			
				|  | @@ -103,86 +74,79 @@ namespace Grpc.Core.Tests
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  | -        public void UnaryCall()
 | 
	
		
			
				|  |  | +        public async Task UnaryCall()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            Assert.AreEqual("ABC", Calls.BlockingUnaryCall(callDetails, "ABC"));
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return request;
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC"));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Assert.AreEqual("ABC", await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "ABC"));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public void UnaryCall_ServerHandlerThrows()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                Calls.BlockingUnaryCall(callDetails, "THROW");
 | 
	
		
			
				|  |  | -                Assert.Fail();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            catch (RpcException e)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); 
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +                throw new Exception("This was thrown on purpose by a test");
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +                
 | 
	
		
			
				|  |  | +            var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); 
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var ex2 = Assert.Throws<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(StatusCode.Unknown, ex2.Status.StatusCode);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public void UnaryCall_ServerHandlerThrowsRpcException()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Calls.BlockingUnaryCall(callDetails, "THROW_UNAUTHENTICATED");
 | 
	
		
			
				|  |  | -                Assert.Fail();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            catch (RpcException e)
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                Assert.AreEqual(StatusCode.Unauthenticated, e.Status.StatusCode);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +                throw new RpcException(new Status(StatusCode.Unauthenticated, ""));
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var ex2 = Assert.Throws<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public void UnaryCall_ServerHandlerSetsStatus()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                Calls.BlockingUnaryCall(callDetails, "SET_UNAUTHENTICATED");
 | 
	
		
			
				|  |  | -                Assert.Fail();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            catch (RpcException e)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Assert.AreEqual(StatusCode.Unauthenticated, e.Status.StatusCode); 
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +                context.Status = new Status(StatusCode.Unauthenticated, "");
 | 
	
		
			
				|  |  | +                return "";
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        [Test]
 | 
	
		
			
				|  |  | -        public async Task AsyncUnaryCall()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            var result = await Calls.AsyncUnaryCall(callDetails, "ABC");
 | 
	
		
			
				|  |  | -            Assert.AreEqual("ABC", result);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +            var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        [Test]
 | 
	
		
			
				|  |  | -        public async Task AsyncUnaryCall_ServerHandlerThrows()
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                await Calls.AsyncUnaryCall(callDetails, "THROW");
 | 
	
		
			
				|  |  | -                Assert.Fail();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            catch (RpcException e)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            var ex2 = Assert.Throws<RpcException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc"));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public async Task ClientStreamingCall()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, ConcatAndEchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            var call = Calls.AsyncClientStreamingCall(callDetails);
 | 
	
		
			
				|  |  | +            helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                string result = "";
 | 
	
		
			
				|  |  | +                await requestStream.ForEach(async (request) =>
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    result += request;
 | 
	
		
			
				|  |  | +                });
 | 
	
		
			
				|  |  | +                await Task.Delay(100);
 | 
	
		
			
				|  |  | +                return result;
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +            var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall());
 | 
	
		
			
				|  |  |              await call.RequestStream.WriteAll(new string[] { "A", "B", "C" });
 | 
	
		
			
				|  |  |              Assert.AreEqual("ABC", await call.ResponseAsync);
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -190,36 +154,47 @@ namespace Grpc.Core.Tests
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public async Task ClientStreamingCall_CancelAfterBegin()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | +            var barrier = new TaskCompletionSource<object>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                barrier.SetResult(null);
 | 
	
		
			
				|  |  | +                await requestStream.ToList();
 | 
	
		
			
				|  |  | +                return "";
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              var cts = new CancellationTokenSource();
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, ConcatAndEchoMethod, new CallOptions(cancellationToken: cts.Token));
 | 
	
		
			
				|  |  | -            var call = Calls.AsyncClientStreamingCall(callDetails);
 | 
	
		
			
				|  |  | +            var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token)));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it.
 | 
	
		
			
				|  |  | -            await Task.Delay(1000);
 | 
	
		
			
				|  |  | +            await barrier.Task;  // make sure the handler has started.
 | 
	
		
			
				|  |  |              cts.Cancel();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                await call.ResponseAsync;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            catch (RpcException e)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Assert.AreEqual(StatusCode.Cancelled, e.Status.StatusCode);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            var ex = Assert.Throws<RpcException>(async () => await call.ResponseAsync);
 | 
	
		
			
				|  |  | +            Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  | -        public void AsyncUnaryCall_EchoMetadata()
 | 
	
		
			
				|  |  | +        public async Task AsyncUnaryCall_EchoMetadata()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                foreach (Metadata.Entry metadataEntry in context.RequestHeaders)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    if (metadataEntry.Key != "user-agent")
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        context.ResponseTrailers.Add(metadataEntry);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                return "";
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              var headers = new Metadata
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  |                  new Metadata.Entry("ascii-header", "abcdefg"),
 | 
	
		
			
				|  |  |                  new Metadata.Entry("binary-header-bin", new byte[] { 1, 2, 3, 0, 0xff }),
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions(headers: headers));
 | 
	
		
			
				|  |  | -            var call = Calls.AsyncUnaryCall(callDetails, "ABC");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            Assert.AreEqual("ABC", call.ResponseAsync.Result);
 | 
	
		
			
				|  |  | +            var call = Calls.AsyncUnaryCall(helper.CreateUnaryCall(new CallOptions(headers: headers)), "ABC");
 | 
	
		
			
				|  |  | +            await call;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -236,15 +211,18 @@ namespace Grpc.Core.Tests
 | 
	
		
			
				|  |  |          public void UnaryCall_DisposedChannel()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              channel.Dispose();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(callDetails, "ABC"));
 | 
	
		
			
				|  |  | +            Assert.Throws(typeof(ObjectDisposedException), () => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC"));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public void UnaryCallPerformance()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return request;
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var callDetails = helper.CreateUnaryCall();
 | 
	
		
			
				|  |  |              BenchmarkUtil.RunBenchmark(100, 100,
 | 
	
		
			
				|  |  |                                         () => { Calls.BlockingUnaryCall(callDetails, "ABC"); });
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -252,44 +230,57 @@ namespace Grpc.Core.Tests
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public void UnknownMethodHandler()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, NonexistentMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            try
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Calls.BlockingUnaryCall(callDetails, "ABC");
 | 
	
		
			
				|  |  | -                Assert.Fail();
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            catch (RpcException e)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            var nonexistentMethod = new Method<string, string>(
 | 
	
		
			
				|  |  | +                MethodType.Unary,
 | 
	
		
			
				|  |  | +                MockServiceHelper.ServiceName,
 | 
	
		
			
				|  |  | +                "NonExistentMethod",
 | 
	
		
			
				|  |  | +                Marshallers.StringMarshaller,
 | 
	
		
			
				|  |  | +                Marshallers.StringMarshaller);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var callDetails = new CallInvocationDetails<string, string>(channel, nonexistentMethod, new CallOptions());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(callDetails, "abc"));
 | 
	
		
			
				|  |  | +            Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public void UserAgentStringPresent()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            string userAgent = Calls.BlockingUnaryCall(callDetails, "RETURN-USER-AGENT");
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return context.RequestHeaders.Where(entry => entry.Key == "user-agent").Single().Value;
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            string userAgent = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc");
 | 
	
		
			
				|  |  |              Assert.IsTrue(userAgent.StartsWith("grpc-csharp/"));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public void PeerInfoPresent()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            string peer = Calls.BlockingUnaryCall(callDetails, "RETURN-PEER");
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return context.Peer;
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            string peer = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc");
 | 
	
		
			
				|  |  |              Assert.IsTrue(peer.Contains(Host));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          [Test]
 | 
	
		
			
				|  |  |          public async Task Channel_WaitForStateChangedAsync()
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  | +            helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return request;
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              Assert.Throws(typeof(TaskCanceledException), 
 | 
	
		
			
				|  |  |                  async () => await channel.WaitForStateChangedAsync(channel.State, DateTime.UtcNow.AddMilliseconds(10)));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              var stateChangedTask = channel.WaitForStateChangedAsync(channel.State);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            var callDetails = new CallInvocationDetails<string, string>(channel, EchoMethod, new CallOptions());
 | 
	
		
			
				|  |  | -            await Calls.AsyncUnaryCall(callDetails, "abc");
 | 
	
		
			
				|  |  | +            await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              await stateChangedTask;
 | 
	
		
			
				|  |  |              Assert.AreEqual(ChannelState.Ready, channel.State);
 | 
	
	
		
			
				|  | @@ -300,62 +291,9 @@ namespace Grpc.Core.Tests
 | 
	
		
			
				|  |  |          {
 | 
	
		
			
				|  |  |              await channel.ConnectAsync();
 | 
	
		
			
				|  |  |              Assert.AreEqual(ChannelState.Ready, channel.State);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |              await channel.ConnectAsync(DateTime.UtcNow.AddMilliseconds(1000));
 | 
	
		
			
				|  |  |              Assert.AreEqual(ChannelState.Ready, channel.State);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private static async Task<string> EchoHandler(string request, ServerCallContext context)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            foreach (Metadata.Entry metadataEntry in context.RequestHeaders)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                if (metadataEntry.Key != "user-agent")
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    context.ResponseTrailers.Add(metadataEntry);
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (request == "RETURN-USER-AGENT")
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return context.RequestHeaders.Where(entry => entry.Key == "user-agent").Single().Value;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (request == "RETURN-PEER")
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                return context.Peer;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (request == "THROW")
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                throw new Exception("This was thrown on purpose by a test");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (request == "THROW_UNAUTHENTICATED")
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                throw new RpcException(new Status(StatusCode.Unauthenticated, ""));
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (request == "SET_UNAUTHENTICATED")
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                context.Status = new Status(StatusCode.Unauthenticated, "");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            return request;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private static async Task<string> ConcatAndEchoHandler(IAsyncStreamReader<string> requestStream, ServerCallContext context)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            string result = "";
 | 
	
		
			
				|  |  | -            await requestStream.ForEach(async (request) =>
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                if (request == "THROW")
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    throw new Exception("This was thrown on purpose by a test");
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -                result += request;
 | 
	
		
			
				|  |  | -            });
 | 
	
		
			
				|  |  | -            // simulate processing takes some time.
 | 
	
		
			
				|  |  | -            await Task.Delay(250);
 | 
	
		
			
				|  |  | -            return result;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |