Exemplo n.º 1
0
        public async Task AsyncUnaryCall_DisposeDuringBackoff_CanceledStatus()
        {
            // 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: TimeSpan.FromSeconds(10).TotalMilliseconds.ToString()));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);
            var cts           = new CancellationTokenSource();

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

            var delayTask     = Task.Delay(100);
            var completedTask = await Task.WhenAny(call.ResponseAsync, delayTask);

            // Assert
            Assert.AreEqual(delayTask, completedTask); // Ensure that we're waiting for retry

            call.Dispose();

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

            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);
            Assert.AreEqual("gRPC call disposed.", ex.Status.Detail);
        }
Exemplo n.º 2
0
        public async Task AsyncUnaryCall_FatalStatusCode_HedgeDelay_Failure()
        {
            // 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, (callCount == 1) ? StatusCode.Unavailable : StatusCode.InvalidArgument));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(hedgingDelay: TimeSpan.FromMilliseconds(50));
            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
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(StatusCode.InvalidArgument, ex.StatusCode);
            Assert.AreEqual(StatusCode.InvalidArgument, call.GetStatus().StatusCode);
            Assert.AreEqual(2, callCount);
        }
Exemplo n.º 3
0
        public async Task AsyncUnaryCall_FailureWithLongDelay_Dispose_CallImmediatelyDisposed()
        {
            // Arrange
            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callCount++;
                await request.Content !.CopyToAsync(new MemoryStream());
                return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
            });
            // Very long delay
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig(initialBackoff: TimeSpan.FromSeconds(30), maxBackoff: TimeSpan.FromSeconds(30));
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

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

            // Test will timeout if dispose doesn't kill the timer.
            call.Dispose();

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

            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);
            Assert.AreEqual("gRPC call disposed.", ex.Status.Detail);
        }
Exemplo n.º 4
0
        public async Task AsyncUnaryCall_ExceedRetryAttempts_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));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig(maxAttempts: 3);
            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(3, callCount);
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(StatusCode.Unavailable, ex.StatusCode);
            Assert.AreEqual(StatusCode.Unavailable, call.GetStatus().StatusCode);
        }
Exemplo n.º 5
0
        public async Task AsyncUnaryCall_SuccessAfterRetry_AccessResponseHeaders_SuccessfullyResponseHeadersReturned()
        {
            // Arrange
            HttpContent?content   = null;
            var         syncPoint = new SyncPoint(runContinuationsAsynchronously: true);

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callCount++;
                content = request.Content !;

                if (callCount == 1)
                {
                    await content.CopyToAsync(new MemoryStream());

                    await syncPoint.WaitForSyncPoint();

                    return(ResponseUtils.CreateHeadersOnlyResponse(
                               HttpStatusCode.OK,
                               StatusCode.Unavailable,
                               customHeaders: new Dictionary <string, string> {
                        ["call-count"] = callCount.ToString()
                    }));
                }

                syncPoint.Continue();

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

                return(ResponseUtils.CreateResponse(
                           HttpStatusCode.OK,
                           streamContent,
                           customHeaders: new Dictionary <string, string> {
                    ["call-count"] = callCount.ToString()
                }));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

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

            // Wait until the first call has failed and the second is on the server
            await syncPoint.WaitToContinue().DefaultTimeout();

            // Assert
            Assert.AreEqual(2, callCount);
            Assert.AreEqual("Hello world", (await call.ResponseAsync.DefaultTimeout()).Message);

            var headers = await headersTask.DefaultTimeout();

            Assert.AreEqual("2", headers.GetValue("call-count"));
        }
Exemplo n.º 6
0
        public async Task AsyncUnaryCall_SuccessTrailersOnly_ThrowNoMessageError()
        {
            // Arrange
            HttpResponseMessage?responseMessage = null;
            var httpClient = ClientTestHelpers.CreateTestClient(request =>
            {
                responseMessage = ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.OK, customHeaders: new Dictionary <string, string> {
                    [GrpcProtocolConstants.MessageTrailer] = "Detail!"
                });
                return(Task.FromResult(responseMessage));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

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

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

            // Assert
            Assert.NotNull(responseMessage);

            Assert.IsFalse(responseMessage !.TrailingHeaders().Any()); // sanity check that there are no trailers

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

            Assert.AreEqual(StatusCode.Internal, call.GetStatus().StatusCode);
            Assert.AreEqual("Failed to deserialize response message.", call.GetStatus().Detail);

            Assert.AreEqual(0, headers.Count);
            Assert.AreEqual(0, call.GetTrailers().Count);
        }
Exemplo n.º 7
0
        public async Task AsyncServerStreamingCall_SuccessAfterRetry_RequestContentSent()
        {
            // Arrange
            var          syncPoint      = new SyncPoint(runContinuationsAsynchronously: true);
            MemoryStream?requestContent = null;

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

                var s  = await request.Content !.ReadAsStreamAsync();
                var ms = new MemoryStream();
                await s.CopyToAsync(ms);

                if (callCount == 1)
                {
                    await syncPoint.WaitForSyncPoint();

                    await request.Content !.CopyToAsync(new MemoryStream());
                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                syncPoint.Continue();

                requestContent = ms;

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

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(maxAttempts: 2, hedgingDelay: TimeSpan.FromMilliseconds(50));
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, 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);

            // Wait until the first call has failed and the second is on the server
            await syncPoint.WaitToContinue().DefaultTimeout();

            // Assert
            Assert.IsTrue(await moveNextTask);
            Assert.AreEqual("Hello world", call.ResponseStream.Current.Message);

            requestContent !.Seek(0, SeekOrigin.Begin);
            var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

            Assert.AreEqual("World", requestMessage !.Name);
        }
Exemplo n.º 8
0
        public async Task AsyncUnaryCall_ExceedAttempts_Failure()
        {
            // Arrange
            var tcs             = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);
            var requestMessages = new List <HelloRequest>();

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                // All calls are in-progress at once.
                Interlocked.Increment(ref callCount);
                if (callCount == 5)
                {
                    tcs.TrySetResult(null);
                }
                await tcs.Task;

                var requestContent = await request.Content !.ReadAsStreamAsync();
                var requestMessage = await ReadRequestMessage(requestContent);
                lock (requestMessages)
                {
                    requestMessages.Add(requestMessage !);
                }

                return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig();
            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);
            Assert.AreEqual(StatusCode.Unavailable, call.GetStatus().StatusCode);

            Assert.AreEqual(5, requestMessages.Count);
            foreach (var requestMessage in requestMessages)
            {
                Assert.AreEqual("World", requestMessage.Name);
            }
        }
Exemplo n.º 9
0
        public async Task AsyncUnaryCall_NonOkStatusTrailer_AccessHeaders_ReturnHeaders()
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(request =>
            {
                var response = ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unimplemented, customHeaders: new Dictionary <string, string> {
                    ["custom"] = "true"
                });
                return(Task.FromResult(response));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

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

            // Assert
            Assert.AreEqual("true", headers.GetValue("custom"));
        }
Exemplo n.º 10
0
        private static async Task StatusReturnedCore(StatusInterceptor interceptor, StatusCode statusCode)
        {
            // Arrange
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                if (statusCode == StatusCode.OK)
                {
                    var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply {
                        Message = "PASS"
                    }).DefaultTimeout();
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
                }
                else
                {
                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, statusCode));
                }
            });

            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var callInvoker = invoker.Intercept(interceptor);

            var call = callInvoker.AsyncUnaryCall(ClientTestHelpers.ServiceMethod, Host, new CallOptions(), new HelloRequest());

            // Assert
            if (statusCode == StatusCode.OK)
            {
                var result = await call.ResponseAsync.DefaultTimeout();

                Assert.AreEqual("PASS", result.Message);
            }
            else
            {
                var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

                Assert.AreEqual(statusCode, ex.StatusCode);
            }

            var interceptorStatusCode = await interceptor.GetStatusCodeAsync().DefaultTimeout();

            Assert.AreEqual(statusCode, interceptorStatusCode);
        }
Exemplo n.º 11
0
        public async Task AsyncUnaryCall_ExceedAttempts_PusbackDelay_Failure()
        {
            // Arrange
            var       stopwatch         = new Stopwatch();
            var       callIntervals     = new List <long>();
            var       hedgeDelay        = TimeSpan.FromMilliseconds(100);
            const int timerResolutionMs = 15 * 2; // Timer has a precision of about 15ms. Double it, just to be safe

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callIntervals.Add(stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();
                Interlocked.Increment(ref callCount);

                await request.Content !.CopyToAsync(new MemoryStream());
                return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable, retryPushbackHeader: hedgeDelay.TotalMilliseconds.ToString(CultureInfo.InvariantCulture)));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(maxAttempts: 2, hedgingDelay: hedgeDelay);
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

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

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

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

            // First call should happen immediately
            Assert.LessOrEqual(callIntervals[0], hedgeDelay.TotalMilliseconds);

            // Second call should happen after delay
            Assert.GreaterOrEqual(callIntervals[1], hedgeDelay.TotalMilliseconds - timerResolutionMs);
        }
Exemplo n.º 12
0
        public async Task AsyncUnaryCall_PushbackDelay_PushbackDelayUpdatesNextCallDelay()
        {
            // Arrange
            var stopwatch     = new Stopwatch();
            var callIntervals = new List <long>();
            var hedgingDelay  = TimeSpan.FromSeconds(10);

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callIntervals.Add(stopwatch.ElapsedMilliseconds);
                stopwatch.Restart();
                Interlocked.Increment(ref callCount);

                await request.Content !.CopyToAsync(new MemoryStream());
                var hedgingPushback = hedgingDelay.TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
                if (callCount == 1)
                {
                    hedgingPushback = "0";
                }
                return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable, retryPushbackHeader: hedgingPushback));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(maxAttempts: 5, hedgingDelay: hedgingDelay);
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

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

            // Assert
            await TestHelpers.AssertIsTrueRetryAsync(() => callIntervals.Count == 2, "Only two calls should be made.").DefaultTimeout();

            // First call should happen immediately
            Assert.LessOrEqual(callIntervals[0], 100);

            // Second call should happen after delay
            Assert.LessOrEqual(callIntervals[1], hedgingDelay.TotalMilliseconds);
        }
Exemplo n.º 13
0
        public async Task AsyncUnaryCall_PushbackExpicitDelay_DelayForSpecifiedDuration()
        {
            // Arrange
            Task?delayTask  = null;
            var  callCount  = 0;
            var  httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callCount++;
                if (callCount == 1)
                {
                    await request.Content !.CopyToAsync(new MemoryStream());
                    delayTask = Task.Delay(100);
                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable, retryPushbackHeader: "200"));
                }

                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig(backoffMultiplier: 1);
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

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

            // Delay of 100ms will finish before second record which has a pushback delay of 200ms
            var completedTask = await Task.WhenAny(call.ResponseAsync, delayTask !).DefaultTimeout();

            var rs = await call.ResponseAsync.DefaultTimeout();

            // Assert
            Assert.AreEqual(delayTask, completedTask); // Response task should finish after
            Assert.AreEqual(2, callCount);
            Assert.AreEqual("Hello world", rs.Message);
        }
Exemplo n.º 14
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);
        }
Exemplo n.º 15
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());
        }
Exemplo n.º 16
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());
        }
Exemplo n.º 17
0
        public async Task AsyncDuplexStreamingCall_SuccessAfterRetry_RequestContentSent()
        {
            // Arrange
            var requestContent = new MemoryStream();
            var syncPoint      = new SyncPoint(runContinuationsAsynchronously: true);

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callCount++;
                var content = (PushStreamContent <HelloRequest, HelloReply>)request.Content !;

                if (callCount == 1)
                {
                    _ = content.CopyToAsync(new MemoryStream());

                    await syncPoint.WaitForSyncPoint();

                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                syncPoint.Continue();

                await content.PushComplete.DefaultTimeout();
                await content.CopyToAsync(requestContent);
                requestContent.Seek(0, SeekOrigin.Begin);

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

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

            // Act
            var call         = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.GetServiceMethod(MethodType.DuplexStreaming), string.Empty, new CallOptions());
            var moveNextTask = call.ResponseStream.MoveNext(CancellationToken.None);

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

            // Wait until the first call has failed and the second is on the server
            await syncPoint.WaitToContinue().DefaultTimeout();

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

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

            // Assert
            Assert.IsTrue(await moveNextTask.DefaultTimeout());
            Assert.AreEqual("Hello world", call.ResponseStream.Current.Message);

            var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

            Assert.AreEqual("1", requestMessage !.Name);
            requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

            Assert.AreEqual("2", requestMessage !.Name);
            requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

            Assert.IsNull(requestMessage);
        }
Exemplo n.º 18
0
        public async Task AsyncUnaryCall_SuccessAfterRetry_RequestContentSent()
        {
            // Arrange
            HttpContent?content = null;

            bool?  firstRequestPreviousAttemptsHeader       = null;
            string?secondRequestPreviousAttemptsHeaderValue = null;
            var    requestContent = new MemoryStream();

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callCount++;

                content = request.Content !;
                await content.CopyToAsync(requestContent);
                requestContent.Seek(0, SeekOrigin.Begin);

                if (callCount == 1)
                {
                    firstRequestPreviousAttemptsHeader = request.Headers.TryGetValues(GrpcProtocolConstants.RetryPreviousAttemptsHeader, out _);

                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                if (request.Headers.TryGetValues(GrpcProtocolConstants.RetryPreviousAttemptsHeader, out var retryAttemptCountValue))
                {
                    secondRequestPreviousAttemptsHeaderValue = retryAttemptCountValue.Single();
                }

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

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent, customTrailers: new Dictionary <string, string>
                {
                    ["custom-trailer"] = "Value!"
                }));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig();
            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(2, callCount);
            Assert.AreEqual("Hello world", (await call.ResponseAsync.DefaultTimeout()).Message);
            Assert.AreEqual("1", (await call.ResponseHeadersAsync.DefaultTimeout()).GetValue(GrpcProtocolConstants.RetryPreviousAttemptsHeader));

            Assert.IsNotNull(content);

            var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

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

            Assert.IsFalse(firstRequestPreviousAttemptsHeader);
            Assert.AreEqual("1", secondRequestPreviousAttemptsHeaderValue);

            var trailers = call.GetTrailers();

            Assert.AreEqual("Value!", trailers.GetValue("custom-trailer"));
        }
Exemplo n.º 19
0
        public async Task AsyncClientStreamingCall_SuccessAfterRetry_RequestContentSent(int hedgingDelayMS)
        {
            // Arrange
            var callLock       = new object();
            var requestContent = new MemoryStream();

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var firstCall = false;
                lock (callLock)
                {
                    callCount++;
                    if (callCount == 1)
                    {
                        firstCall = true;
                    }
                }
                if (firstCall)
                {
                    await request.Content !.CopyToAsync(new MemoryStream());
                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                var content = (PushStreamContent <HelloRequest, HelloReply>)request.Content !;
                await content.PushComplete.DefaultTimeout();

                await request.Content !.CopyToAsync(requestContent);

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

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(maxAttempts: 2, hedgingDelay: TimeSpan.FromMilliseconds(hedgingDelayMS));
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

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

            // Assert
            Assert.IsNotNull(call);

            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 responseMessage = await responseTask.DefaultTimeout();

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

            requestContent.Seek(0, SeekOrigin.Begin);

            var requests = new List <HelloRequest>();

            while (true)
            {
                var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

                if (requestMessage == null)
                {
                    break;
                }

                requests.Add(requestMessage);
            }

            Assert.AreEqual(2, requests.Count);
            Assert.AreEqual("1", requests[0].Name);
            Assert.AreEqual("2", requests[1].Name);
        }
Exemplo n.º 20
0
        public async Task AsyncClientStreamingCall_SuccessAfterRetry_RequestContentSent()
        {
            // Arrange
            var requestContent = new MemoryStream();

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

                var currentContent = new MemoryStream();
                await request.Content !.CopyToAsync(currentContent);

                if (callCount == 1)
                {
                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                currentContent.Seek(0, SeekOrigin.Begin);
                await currentContent.CopyToAsync(requestContent);

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

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

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

            // Assert
            Assert.IsNotNull(call);

            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 responseMessage = await responseTask.DefaultTimeout();

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

            requestContent.Seek(0, SeekOrigin.Begin);

            var requests = new List <HelloRequest>();

            while (true)
            {
                var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

                if (requestMessage == null)
                {
                    break;
                }

                requests.Add(requestMessage);
            }

            Assert.AreEqual(2, requests.Count);
            Assert.AreEqual("1", requests[0].Name);
            Assert.AreEqual("2", requests[1].Name);

            call.Dispose();
        }