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); }
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()); }
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); }
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); }
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); }
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); }
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); }
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); }
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()); }
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()); }
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); }
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); }
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()); }
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); }
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); }
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); }
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()); }
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); }
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); }
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); }
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); }
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()); }
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); }
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); }
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); }