示例#1
0
        public async Task AsyncDuplexStreamingCall_MessageLargerThanReceiveMaxMessageSize_ThrowsError()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(HandleRequest);
            var invoker    = HttpClientCallInvokerFactory.Create(httpClient);

            invoker.ReceiveMaxMessageSize = 1;

            // Act
            var call = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());
            await call.RequestStream.WriteAsync(new HelloRequest
            {
                Name = "World"
            });

            await call.RequestStream.CompleteAsync();

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseStream.MoveNext(CancellationToken.None));

            Assert.AreEqual(StatusCode.ResourceExhausted, ex.StatusCode);
            Assert.AreEqual("Received message exceeds the maximum configured message size.", ex.Status.Detail);
        }
示例#2
0
        public async Task AsyncUnaryCall_SetSecondDeadline_RequestMessageContainsDeadlineHeader()
        {
            // Arrange
            HttpRequestMessage?httpRequestMessage = null;

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                httpRequestMessage = request;

                var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var invoker = HttpClientCallInvokerFactory.Create(
                httpClient,
                systemClock: new TestSystemClock(new DateTime(2019, 11, 29, 1, 1, 1, DateTimeKind.Utc)));

            // Act
            await invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(deadline : invoker.Channel.Clock.UtcNow.AddSeconds(1)), new HelloRequest());

            // Assert
            Assert.IsNotNull(httpRequestMessage);
            Assert.AreEqual("1S", httpRequestMessage !.Headers.GetValues(GrpcProtocolConstants.TimeoutHeader).Single());
        }
示例#3
0
        public async Task AsyncUnaryCall_MultipleStatusHeaders_ThrowError()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout();
                var response      = ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent, grpcStatusCode: StatusCode.Aborted);
                response.TrailingHeaders.Add(GrpcProtocolConstants.MessageTrailer, "one");
                response.TrailingHeaders.Add(GrpcProtocolConstants.MessageTrailer, "two");
                return(response);
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest());

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual("Multiple grpc-message headers.", ex.Status.Detail);
            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);
            Assert.AreEqual(StatusCode.Cancelled, call.GetStatus().StatusCode);
        }
        public async Task AsyncClientStreamingCall_DeadlineDuringWrite_ResponseThrowsDeadlineExceededStatus()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(request =>
            {
                var stream = new SyncPointMemoryStream();
                var content = new StreamContent(stream);
                return Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK, content, grpcStatusCode: null));
            });
            var systemClock = new TestSystemClock(DateTime.UtcNow);
            var invoker = HttpClientCallInvokerFactory.Create(httpClient, systemClock: systemClock);
            var deadline = systemClock.UtcNow.AddMilliseconds(0.1);

            // Act
            var call = invoker.AsyncClientStreamingCall<HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(deadline: deadline));

            systemClock.UtcNow = deadline;

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync<RpcException>(() => call.RequestStream.WriteAsync(new HelloRequest())).DefaultTimeout();
            Assert.AreEqual(StatusCode.DeadlineExceeded, ex.StatusCode);
            Assert.AreEqual(StatusCode.DeadlineExceeded, call.GetStatus().StatusCode);
        }
        public async Task AsyncUnaryCall_Non200HttpStatusCode_MappedToGrpcStatusCode(HttpStatusCode httpStatusCode, StatusCode statusCode)
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(request =>
            {
                var response = ResponseUtils.CreateResponse(httpStatusCode);
                return(Task.FromResult(response));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest());

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(statusCode, ex.StatusCode);

            var status = call.GetStatus();

            Assert.AreEqual(statusCode, status.StatusCode);
            Assert.AreEqual("Bad gRPC response. HTTP status code: " + (int)httpStatusCode, status.Detail);
        }
示例#6
0
        public async Task AsyncUnaryCall_MessageReturned_ReturnsTrailers()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout();
                var response      = ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent);
                response.Headers.Add("custom", "ABC");
                response.TrailingHeaders.Add("custom-header", "value");
                return(response);
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call      = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest());
            var message   = await call;
            var trailers1 = call.GetTrailers();
            var trailers2 = call.GetTrailers();

            // Assert
            Assert.AreSame(trailers1, trailers2);
            Assert.AreEqual("value", trailers1.Single(t => t.Key == "custom-header").Value);
        }
示例#7
0
        public async Task AsyncClientStreamingCall_DeadlineDuringSend_ThrowOperationCanceledOnCancellation_ResponseThrowsDeadlineExceededStatus()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var content = (PushStreamContent)request.Content;
                await content.PushComplete.DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });
            var testSystemClock = new TestSystemClock(DateTime.UtcNow);
            var invoker         = HttpClientCallInvokerFactory.Create(httpClient, systemClock: testSystemClock, configure: o => o.ThrowOperationCanceledOnCancellation = true);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(deadline: testSystemClock.UtcNow.AddSeconds(0.5)));

            // Assert
            var responseTask = call.ResponseAsync;

            await ExceptionAssert.ThrowsAsync <OperationCanceledException>(() => responseTask).DefaultTimeout();

            Assert.AreEqual(StatusCode.DeadlineExceeded, call.GetStatus().StatusCode);
        }
示例#8
0
        public async Task AsyncClientStreamingCall_DeadlineBeforeWrite_ResponseThrowsDeadlineExceededStatus()
        {
            // Arrange
            var tcs        = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                await tcs.Task.DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });
            var systemClock = new TestSystemClock(DateTime.UtcNow);
            var invoker     = HttpClientCallInvokerFactory.Create(httpClient, systemClock: systemClock);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(deadline: systemClock.UtcNow.AddMilliseconds(10)));

            await Task.Delay(200); // Ensure the deadline has passed

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.RequestStream.WriteAsync(new HelloRequest())).DefaultTimeout();

            Assert.AreEqual(StatusCode.DeadlineExceeded, ex.StatusCode);
            Assert.AreEqual(StatusCode.DeadlineExceeded, call.GetStatus().StatusCode);
        }
示例#9
0
        public async Task AsyncUnaryCall_ManyAttemptsNoDelay_MarshallerCalledOnce()
        {
            // Arrange
            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                Interlocked.Increment(ref callCount);
                await request.Content !.CopyToAsync(new MemoryStream());
                return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

            var marshallerCount   = 0;
            var requestMarshaller = Marshallers.Create <HelloRequest>(
                r =>
            {
                Interlocked.Increment(ref marshallerCount);
                return(r.ToByteArray());
            },
                data => HelloRequest.Parser.ParseFrom(data));
            var method = ClientTestHelpers.GetServiceMethod(requestMarshaller: requestMarshaller);

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(method, string.Empty, new CallOptions(), new HelloRequest {
                Name = "World"
            });

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(StatusCode.Unavailable, ex.StatusCode);
            Assert.AreEqual(StatusCode.Unavailable, call.GetStatus().StatusCode);

            Assert.AreEqual(5, callCount);
            Assert.AreEqual(1, marshallerCount);
        }
示例#10
0
        public async Task AsyncClientStreamingCall_DeadlineLargerThanMaxTimerDueTime_DeadlineExceeded()
        {
            // Arrange
            var testSink = new TestSink();
            var testLoggerFactory = new TestLoggerFactory(testSink, true);

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var content = (PushStreamContent<HelloRequest, HelloReply>)request.Content!;
                await content.PushComplete.DefaultTimeout();

                return ResponseUtils.CreateResponse(HttpStatusCode.OK);
            });
            var testSystemClock = new TestSystemClock(DateTime.UtcNow);
            var invoker = HttpClientCallInvokerFactory.Create(httpClient, systemClock: testSystemClock, maxTimerPeriod: 20, loggerFactory: testLoggerFactory);
            var timeout = TimeSpan.FromSeconds(0.2);
            var deadline = testSystemClock.UtcNow.Add(timeout);

            // Act
            var call = invoker.AsyncClientStreamingCall<HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(deadline: deadline));

            // Assert
            var responseTask = call.ResponseAsync;

            await Task.Delay(timeout);

            // Update time so deadline exceeds correctly
            testSystemClock.UtcNow = deadline;

            var ex = await ExceptionAssert.ThrowsAsync<RpcException>(() => responseTask).DefaultTimeout();
            Assert.AreEqual(StatusCode.DeadlineExceeded, ex.StatusCode);
            Assert.AreEqual(StatusCode.DeadlineExceeded, call.GetStatus().StatusCode);

            var write = testSink.Writes.First(w => w.EventId.Name == "DeadlineTimerRescheduled");
            Assert.AreEqual(LogLevel.Trace, write.LogLevel);
            Assert.AreEqual("Deadline timer triggered but 00:00:00.2000000 remaining before deadline exceeded. Deadline timer rescheduled.", write.Message);
        }
示例#11
0
        public async Task AsyncUnaryCall_NoMessagesSuccess_Failure()
        {
            // Arrange
            var testSink = new TestSink();
            var services = new ServiceCollection();

            services.AddLogging(b =>
            {
                b.AddProvider(new TestLoggerProvider(testSink));
            });
            services.AddNUnitLogger();
            var provider = services.BuildServiceProvider();

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var content = request.Content !;
                await content.CopyToAsync(new MemoryStream());

                return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.OK));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, loggerFactory: provider.GetRequiredService <ILoggerFactory>(), serviceConfig: serviceConfig);

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.GetServiceMethod(MethodType.Unary), string.Empty, new CallOptions(), new HelloRequest {
                Name = "World"
            });
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            // Assert
            Assert.AreEqual("Failed to deserialize response message.", ex.Status.Detail);
            Assert.AreEqual(StatusCode.Internal, ex.StatusCode);

            var log = testSink.Writes.Single(w => w.EventId.Name == "CallCommited");

            Assert.AreEqual("Call commited. Reason: FatalStatusCode", log.State.ToString());
        }
示例#12
0
        public async Task AsyncServerStreamingCall_MessagesReturnedTogether_MessagesReceived()
        {
            // Arrange
            var httpClient = TestHelpers.CreateTestClient(async request =>
            {
                var streamContent = await TestHelpers.CreateResponseContent(
                    new HelloReply
                {
                    Message = "Hello world 1"
                },
                    new HelloReply
                {
                    Message = "Hello world 2"
                }).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncServerStreamingCall <HelloRequest, HelloReply>(TestHelpers.ServiceMethod, null, new CallOptions(), new HelloRequest());

            var responseStream = call.ResponseStream;

            // Assert
            Assert.IsNull(responseStream.Current);

            Assert.IsTrue(await responseStream.MoveNext(CancellationToken.None).DefaultTimeout());
            Assert.IsNotNull(responseStream.Current);
            Assert.AreEqual("Hello world 1", responseStream.Current.Message);

            Assert.IsTrue(await responseStream.MoveNext(CancellationToken.None).DefaultTimeout());
            Assert.IsNotNull(responseStream.Current);
            Assert.AreEqual("Hello world 2", responseStream.Current.Message);

            Assert.IsFalse(await responseStream.MoveNext(CancellationToken.None).DefaultTimeout());
        }
示例#13
0
        public async Task ResolverReturnsNoAddresses_DisposeWhileWaitForReady_Error()
        {
            // Arrange
            var testMessageHandler = TestHttpMessageHandler.Create(async request =>
            {
                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var services = new ServiceCollection();
            var resolver = new TestResolver();

            services.AddSingleton <ResolverFactory>(new TestResolverFactory(resolver));
            services.AddSingleton <ISubchannelTransportFactory>(new TestSubchannelTransportFactory());

            var invoker = HttpClientCallInvokerFactory.Create(testMessageHandler, "test:///localhost", configure: o =>
            {
                o.Credentials     = ChannelCredentials.Insecure;
                o.ServiceProvider = services.BuildServiceProvider();
            });

            // Act
            var callOptions = new CallOptions().WithWaitForReady();
            var call        = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, callOptions, new HelloRequest());

            var exTask = ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync);

            call.Dispose();

            var ex = await exTask.DefaultTimeout();

            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);
            Assert.AreEqual("gRPC call disposed.", ex.Status.Detail);
        }
示例#14
0
        public async Task MoveNextAsync_MultipleMessages_MessagesReceived()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var streamContent = await ClientTestHelpers.CreateResponsesContent(
                    new HelloReply
                {
                    Message = "Hello world 1"
                },
                    new HelloReply
                {
                    Message = "Hello world 2"
                }).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncServerStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest());

            var enumerator = call.ResponseStream.ReadAllAsync().GetAsyncEnumerator();

            // Assert
            Assert.IsNull(enumerator.Current);

            Assert.IsTrue(await enumerator.MoveNextAsync().AsTask().DefaultTimeout());
            Assert.IsNotNull(enumerator.Current);
            Assert.AreEqual("Hello world 1", enumerator.Current.Message);

            Assert.IsTrue(await enumerator.MoveNextAsync().AsTask().DefaultTimeout());
            Assert.IsNotNull(enumerator.Current);
            Assert.AreEqual("Hello world 2", enumerator.Current.Message);

            Assert.IsFalse(await enumerator.MoveNextAsync().AsTask().DefaultTimeout());
        }
        public async Task AsyncUnaryCall_Success_ResponseHeadersPopulated()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                HelloReply reply = new HelloReply
                {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();
                var response      = ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent);
                response.Headers.Server.Add(new ProductInfoHeaderValue("TestName", "1.0"));
                response.Headers.Add("custom", "ABC");
                response.Headers.Add("binary-bin", Convert.ToBase64String(Encoding.UTF8.GetBytes("Hello world")));
                return(response);
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call             = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest());
            var responseHeaders1 = await call.ResponseHeadersAsync.DefaultTimeout();

            var responseHeaders2 = await call.ResponseHeadersAsync.DefaultTimeout();

            // Assert
            Assert.AreSame(responseHeaders1, responseHeaders2);

            Assert.AreEqual("TestName/1.0", responseHeaders1.GetValue("server"));

            Assert.AreEqual("ABC", responseHeaders1.GetValue("custom"));

            var header = responseHeaders1.Get("binary-bin");

            Assert.AreEqual(true, header.IsBinary);
            CollectionAssert.AreEqual(Encoding.UTF8.GetBytes("Hello world"), header.ValueBytes);
        }
示例#16
0
        public async Task Intercept_WrapClientStream_ClientStreamWrapperExecuted()
        {
            // Arrange
            var serviceMethod = new Method <string, string>(MethodType.Unary, "ServiceName", "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller);

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var requestContent = await request.Content.ReadAsStreamAsync();
                await requestContent.CopyToAsync(new MemoryStream());

                var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply {
                    Message = "PASS"
                }).DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var stringBuilder = new StringBuilder();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var callInvoker = invoker.Intercept(new ClientStreamingCountingInterceptor());

            var call = callInvoker.AsyncClientStreamingCall(serviceMethod, Host, new CallOptions());
            await call.RequestStream.WriteAsync("A");

            await call.RequestStream.WriteAsync("B");

            await call.RequestStream.WriteAsync("C");

            await call.RequestStream.CompleteAsync();

            // Assert
            Assert.AreEqual("3", await call.ResponseAsync);

            Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode);
            Assert.IsNotNull(call.GetTrailers());
        }
示例#17
0
        public async Task MoveNextAsync_CancelCall_ThrowOperationCanceledOnCancellation_EnumeratorThrows()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var streamContent = await ClientTestHelpers.CreateResponsesContent(
                    new HelloReply
                    {
                        Message = "Hello world 1"
                    },
                    new HelloReply
                    {
                        Message = "Hello world 2"
                    }).DefaultTimeout();

                return ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent);
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient, configure: o => o.ThrowOperationCanceledOnCancellation = true);
            var cts = new CancellationTokenSource();

            // Act
            var call = invoker.AsyncServerStreamingCall<HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(cancellationToken: cts.Token), new HelloRequest());

            var enumerator = call.ResponseStream.ReadAllAsync().GetAsyncEnumerator();

            // Assert
            Assert.IsNull(enumerator.Current);

            Assert.IsTrue(await enumerator.MoveNextAsync().AsTask().DefaultTimeout());
            Assert.IsNotNull(enumerator.Current);
            Assert.AreEqual("Hello world 1", enumerator.Current.Message);

            cts.Cancel();

            await ExceptionAssert.ThrowsAsync<OperationCanceledException>(() => enumerator.MoveNextAsync().AsTask()).DefaultTimeout();
            Assert.AreEqual(StatusCode.Cancelled, call.GetStatus().StatusCode);
        }
示例#18
0
        public void InterceptMetadata_AddRequestHeader_HeaderInRequest()
        {
            // Arrange
            const string HeaderKey   = "x-client-interceptor";
            const string HeaderValue = "hello-world";

            string?requestHeaderValue = null;
            var    httpClient         = TestHelpers.CreateTestClient(async request =>
            {
                if (request.Headers.TryGetValues(HeaderKey, out var values))
                {
                    requestHeaderValue = values.Single();
                }

                var streamContent = await TestHelpers.CreateResponseContent(new HelloReply {
                    Message = "PASS"
                }).DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var callInvoker = invoker.Intercept(metadata =>
            {
                metadata = metadata ?? new Metadata();
                metadata.Add(new Metadata.Entry(HeaderKey, HeaderValue));
                return(metadata);
            });

            var result = callInvoker.BlockingUnaryCall(TestHelpers.ServiceMethod, Host, new CallOptions(), new HelloRequest());

            // Assert
            Assert.AreEqual("PASS", result.Message);
            Assert.AreEqual(HeaderValue, requestHeaderValue);
        }
示例#19
0
        public async Task AsyncUnaryCall_ErrorParsingTrailers_ThrowsError()
        {
            // Arrange
            var testSink      = new TestSink();
            var loggerFactory = new TestLoggerFactory(testSink, true);

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout();
                var response      = ResponseUtils.CreateResponse(
                    HttpStatusCode.OK,
                    streamContent,
                    grpcStatusCode: StatusCode.Aborted,
                    customTrailers: new Dictionary <string, string>
                {
                    ["blah-bin"] = "!"
                });
                response.Headers.Add("custom", "ABC");
                return(response);
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient, loggerFactory);

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest());
            var ex   = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            // Assert
            Assert.AreEqual(StatusCode.Aborted, ex.StatusCode);
            Assert.AreEqual(null, ex.Status.Detail);
            Assert.AreEqual(0, ex.Trailers.Count);

            var log = testSink.Writes.Single(w => w.EventId.Name == "ErrorParsingTrailers");

            Assert.AreEqual("Error parsing trailers.", log.State.ToString());
            Assert.AreEqual("Invalid Base-64 header value.", log.Exception.Message);
        }
示例#20
0
        public async Task AsyncServerStreamingCall_NoMessagesSuccess_SuccussCommitLogged()
        {
            // Arrange
            var testSink = new TestSink();
            var services = new ServiceCollection();

            services.AddLogging(b =>
            {
                b.AddProvider(new TestLoggerProvider(testSink));
            });
            services.AddNUnitLogger();
            var provider = services.BuildServiceProvider();

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var content = request.Content !;
                await content.CopyToAsync(new MemoryStream());

                return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.OK));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, loggerFactory: provider.GetRequiredService <ILoggerFactory>(), serviceConfig: serviceConfig);

            // Act
            var call = invoker.AsyncServerStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.GetServiceMethod(MethodType.ServerStreaming), string.Empty, new CallOptions(), new HelloRequest {
                Name = "World"
            });
            var moveNextTask = call.ResponseStream.MoveNext(CancellationToken.None);

            // Assert
            Assert.IsFalse(await moveNextTask);

            var log = testSink.Writes.Single(w => w.EventId.Name == "CallCommited");

            Assert.AreEqual("Call commited. Reason: ResponseHeadersReceived", log.State.ToString());
        }
示例#21
0
        public async Task AsyncUnaryCall_PushbackExplicitDelayExceedAttempts_Failure()
        {
            // Arrange
            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callCount++;
                await request.Content !.CopyToAsync(new MemoryStream());
                return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable, retryPushbackHeader: "0"));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig(maxAttempts: 5);
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest {
                Name = "World"
            });

            // Assert
            Assert.AreEqual(5, callCount);
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(StatusCode.Unavailable, ex.StatusCode);
        }
示例#22
0
        public async Task AsyncClientStreamingCall_WriteAfterResult_Error()
        {
            // Arrange
            var requestContent = new MemoryStream();

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                Interlocked.Increment(ref callCount);

                _ = request.Content !.ReadAsStreamAsync();

                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.GetServiceMethod(MethodType.ClientStreaming), string.Empty, new CallOptions());

            // Assert
            var responseMessage = await call.ResponseAsync.DefaultTimeout();

            Assert.AreEqual("Hello world", responseMessage.Message);

            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.RequestStream.WriteAsync(new HelloRequest {
                Name = "1"
            })).DefaultTimeout();

            Assert.AreEqual(StatusCode.OK, ex.StatusCode);
        }
示例#23
0
        public void AsyncClientStreamingCall_DeadlineDuringSend_ResponseThrowsDeadlineExceededStatus()
        {
            // Arrange
            var httpClient = TestHelpers.CreateTestClient(async request =>
            {
                var content = (PushStreamContent)request.Content;
                await content.PushComplete.DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(TestHelpers.ServiceMethod, string.Empty, new CallOptions(deadline: DateTime.UtcNow.AddSeconds(0.5)));

            // Assert
            var responseTask = call.ResponseAsync;

            Assert.IsFalse(responseTask.IsCompleted, "Response not returned until client stream is complete.");

            var ex = Assert.ThrowsAsync <RpcException>(async() => await responseTask.DefaultTimeout());

            Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode);
        }
示例#24
0
        public async Task AsyncServerStreamingCall_MessagesReturnedTogether_MessagesReceived()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(request =>
            {
                HelloReply reply = new HelloReply
                {
                    Message = "Hello world"
                };

                return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK, new ByteArrayContent(Array.Empty <byte>()))));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());

            var responseStream = call.ResponseStream;

            // Assert
            Assert.IsNull(responseStream.Current);
            Assert.IsFalse(await responseStream.MoveNext(CancellationToken.None).DefaultTimeout());
            Assert.IsNull(responseStream.Current);
        }
        public async Task CallCredentialsWithHttp_NoMetadataOnRequest()
        {
            // Arrange
            bool?hasAuthorizationValue = null;
            var  httpClient            = ClientTestHelpers.CreateTestClient(async request =>
            {
                hasAuthorizationValue = request.Headers.TryGetValues("authorization", out _);

                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            }, new Uri("http://localhost"));

            var testSink      = new TestSink();
            var loggerFactory = new TestLoggerFactory(testSink, true);

            var invoker = HttpClientCallInvokerFactory.Create(httpClient, loggerFactory);

            // Act
            var callCredentials = CallCredentials.FromInterceptor((context, metadata) =>
            {
                metadata.Add("authorization", "SECRET_TOKEN");
                return(Task.CompletedTask);
            });
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(credentials: callCredentials), new HelloRequest());
            await call.ResponseAsync.DefaultTimeout();

            // Assert
            Assert.AreEqual(false, hasAuthorizationValue);

            var log = testSink.Writes.Single(w => w.EventId.Name == "CallCredentialsNotUsed");

            Assert.AreEqual("The configured CallCredentials were not used because the call does not use TLS.", log.State.ToString());
        }
        public async Task PickAsync_HedgingWithDrop_ThrowsError()
        {
            // Arrange
            string?authority          = null;
            var    testMessageHandler = TestHttpMessageHandler.Create(async request =>
            {
                authority = request.RequestUri !.Authority;
                var reply = new HelloReply {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var services = new ServiceCollection();

            services.AddNUnitLogger();
            services.AddSingleton <TestResolver>();
            services.AddSingleton <ResolverFactory, TestResolverFactory>();
            DropLoadBalancer?loadBalancer = null;

            services.AddSingleton <LoadBalancerFactory>(new DropLoadBalancerFactory(c =>
            {
                loadBalancer = new DropLoadBalancer(c);
                return(loadBalancer);
            }));
            services.AddSingleton <ISubchannelTransportFactory>(new TestSubchannelTransportFactory());

            var invoker = HttpClientCallInvokerFactory.Create(testMessageHandler, "test:///localhost", configure: o =>
            {
                o.Credentials     = ChannelCredentials.Insecure;
                o.ServiceProvider = services.BuildServiceProvider();
                o.ServiceConfig   = new ServiceConfig
                {
                    MethodConfigs =
                    {
                        new MethodConfig
                        {
                            Names         = { MethodName.Default     },
                            HedgingPolicy = new HedgingPolicy
                            {
                                MaxAttempts         = 5,
                                HedgingDelay        = TimeSpan.FromMinutes(10),
                                NonFatalStatusCodes ={ StatusCode.DataLoss                    }
                            }
                        }
                    },
                    LoadBalancingConfigs = { new LoadBalancingConfig("drop") }
                };
            });

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions().WithWaitForReady(), new HelloRequest());

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(StatusCode.DataLoss, ex.StatusCode);

            Assert.AreEqual(1, loadBalancer !.PickCount);
        }
示例#27
0
        public async Task AsyncDuplexStreamingCall_MessagesStreamed_MessagesReceived()
        {
            // Arrange
            var streamContent = new SyncPointMemoryStream();

            PushStreamContent <HelloRequest, HelloReply>?content = null;

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                content = (PushStreamContent <HelloRequest, HelloReply>)request.Content !;
                await content.PushComplete.DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, new StreamContent(streamContent)));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());

            var requestStream  = call.RequestStream;
            var responseStream = call.ResponseStream;

            // Assert
            await call.RequestStream.WriteAsync(new HelloRequest { Name = "1" }).DefaultTimeout();

            await call.RequestStream.WriteAsync(new HelloRequest { Name = "2" }).DefaultTimeout();

            await call.RequestStream.CompleteAsync().DefaultTimeout();

            var deserializationContext = new DefaultDeserializationContext();

            Assert.IsNotNull(content);
            var requestContent = await content !.ReadAsStreamAsync().DefaultTimeout();
            var requestMessage = await requestContent.ReadMessageAsync(
                deserializationContext,
                NullLogger.Instance,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).AsTask().DefaultTimeout();

            Assert.AreEqual("1", requestMessage !.Name);
            requestMessage = await requestContent.ReadMessageAsync(
                deserializationContext,
                NullLogger.Instance,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).AsTask().DefaultTimeout();

            Assert.AreEqual("2", requestMessage !.Name);

            Assert.IsNull(responseStream.Current);

            var moveNextTask1 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask1.IsCompleted);

            await streamContent.AddDataAndWait(await ClientTestHelpers.GetResponseDataAsync(new HelloReply
            {
                Message = "Hello world 1"
            }).DefaultTimeout()).DefaultTimeout();

            Assert.IsTrue(await moveNextTask1.DefaultTimeout());
            Assert.IsNotNull(responseStream.Current);
            Assert.AreEqual("Hello world 1", responseStream.Current.Message);

            var moveNextTask2 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask2.IsCompleted);

            await streamContent.AddDataAndWait(await ClientTestHelpers.GetResponseDataAsync(new HelloReply
            {
                Message = "Hello world 2"
            }).DefaultTimeout()).DefaultTimeout();

            Assert.IsTrue(await moveNextTask2.DefaultTimeout());
            Assert.IsNotNull(responseStream.Current);
            Assert.AreEqual("Hello world 2", responseStream.Current.Message);

            var moveNextTask3 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask3.IsCompleted);

            await streamContent.AddDataAndWait(Array.Empty <byte>()).DefaultTimeout();

            Assert.IsFalse(await moveNextTask3.DefaultTimeout());

            var moveNextTask4 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsTrue(moveNextTask4.IsCompleted);
            Assert.IsFalse(await moveNextTask3.DefaultTimeout());
        }
示例#28
0
        public async Task AsyncClientStreamingCall_Success_RequestContentSent()
        {
            // Arrange
            var requestContentTcs = new TaskCompletionSource <Task <Stream> >(TaskCreationOptions.RunContinuationsAsynchronously);

            PushStreamContent <HelloRequest, HelloReply>?content = null;

            var handler = TestHttpMessageHandler.Create(async request =>
            {
                content        = (PushStreamContent <HelloRequest, HelloReply>)request.Content !;
                var streamTask = content.ReadAsStreamAsync();
                requestContentTcs.SetResult(streamTask);

                // Wait for RequestStream.CompleteAsync()
                await streamTask;

                HelloReply reply = new HelloReply
                {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var invoker = HttpClientCallInvokerFactory.Create(handler, "http://localhost");

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());
            var requestContentTask = await requestContentTcs.Task.DefaultTimeout();

            // Assert
            Assert.IsNotNull(call);
            Assert.IsNotNull(content);

            var responseTask = call.ResponseAsync;

            Assert.IsFalse(responseTask.IsCompleted, "Response not returned until client stream is complete.");


            await call.RequestStream.WriteAsync(new HelloRequest { Name = "1" }).DefaultTimeout();

            await call.RequestStream.WriteAsync(new HelloRequest { Name = "2" }).DefaultTimeout();

            await call.RequestStream.CompleteAsync().DefaultTimeout();

            var requestContent = await requestContentTask.DefaultTimeout();

            var requestMessage = await StreamSerializationHelper.ReadMessageAsync(
                requestContent,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).DefaultTimeout();

            Assert.AreEqual("1", requestMessage !.Name);
            requestMessage = await StreamSerializationHelper.ReadMessageAsync(
                requestContent,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).DefaultTimeout();

            Assert.AreEqual("2", requestMessage !.Name);

            var responseMessage = await responseTask.DefaultTimeout();

            Assert.AreEqual("Hello world", responseMessage.Message);
        }
示例#29
0
        public async Task AsyncClientStreamingCall_Success_RequestContentSent()
        {
            // Arrange
            PushStreamContent <HelloRequest, HelloReply>?content = null;

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                content = (PushStreamContent <HelloRequest, HelloReply>)request.Content !;
                await content.PushComplete.DefaultTimeout();

                HelloReply reply = new HelloReply
                {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());

            // Assert
            Assert.IsNotNull(call);
            Assert.IsNotNull(content);

            var responseTask = call.ResponseAsync;

            Assert.IsFalse(responseTask.IsCompleted, "Response not returned until client stream is complete.");

            var streamTask = content !.ReadAsStreamAsync().DefaultTimeout();

            await call.RequestStream.WriteAsync(new HelloRequest { Name = "1" }).DefaultTimeout();

            await call.RequestStream.WriteAsync(new HelloRequest { Name = "2" }).DefaultTimeout();

            await call.RequestStream.CompleteAsync().DefaultTimeout();

            var requestContent = await streamTask.DefaultTimeout();

            var requestMessage = await requestContent.ReadMessageAsync(
                NullLogger.Instance,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).AsTask().DefaultTimeout();

            Assert.AreEqual("1", requestMessage !.Name);
            requestMessage = await requestContent.ReadMessageAsync(
                NullLogger.Instance,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).AsTask().DefaultTimeout();

            Assert.AreEqual("2", requestMessage !.Name);

            var responseMessage = await responseTask.DefaultTimeout();

            Assert.AreEqual("Hello world", responseMessage.Message);
        }
示例#30
0
        public async Task AsyncUnaryCall_CompressMetadataSentWithRequest_RequestMessageCompressed(bool compressionDisabledOnOptions)
        {
            // Arrange
            HttpRequestMessage?httpRequestMessage = null;
            HelloRequest?      helloRequest       = null;
            bool?isRequestNotCompressed           = null;

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                httpRequestMessage = request;

                var requestData        = await request.Content.ReadAsByteArrayAsync();
                isRequestNotCompressed = requestData[0] == 0;

                helloRequest = await StreamExtensions.ReadSingleMessageAsync(
                    new MemoryStream(requestData),
                    NullLogger.Instance,
                    ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                    "gzip",
                    maximumMessageSize: null,
                    GrpcProtocolConstants.DefaultCompressionProviders,
                    CancellationToken.None);

                HelloReply reply = new HelloReply
                {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var compressionProviders = GrpcProtocolConstants.DefaultCompressionProviders.Values.ToList();

            compressionProviders.Add(new TestCompressionProvider());

            var invoker = HttpClientCallInvokerFactory.Create(httpClient, configure: o => o.CompressionProviders = compressionProviders);

            var compressionMetadata = CreateClientCompressionMetadata("gzip");
            var callOptions         = new CallOptions(headers: compressionMetadata);

            if (compressionDisabledOnOptions)
            {
                callOptions = callOptions.WithWriteOptions(new WriteOptions(WriteFlags.NoCompress));
            }

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, callOptions, new HelloRequest
            {
                Name = "Hello"
            });

            // Assert
            var response = await call.ResponseAsync;

            Assert.IsNotNull(response);
            Assert.AreEqual("Hello world", response.Message);

            Debug.Assert(httpRequestMessage != null);
            Assert.AreEqual("identity,gzip,deflate,test", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single());
            Assert.AreEqual("gzip", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single());
            Assert.AreEqual(false, httpRequestMessage.Headers.Contains(GrpcProtocolConstants.CompressionRequestAlgorithmHeader));

            Debug.Assert(helloRequest != null);
            Assert.AreEqual("Hello", helloRequest.Name);

            Assert.AreEqual(compressionDisabledOnOptions, isRequestNotCompressed);
        }