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 CreateClient_ServerCallContextAndUserCancellationToken_PropogatedDeadlineAndCancellation(Canceller canceller) { // Arrange var baseAddress = new Uri("http://localhost"); var deadline = DateTime.UtcNow.AddDays(1); var contextCts = new CancellationTokenSource(); var userCts = new CancellationTokenSource(); var tcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously); CallOptions options = default; var handler = TestHttpMessageHandler.Create(async(r, token) => { token.Register(() => tcs.SetCanceled()); await tcs.Task; var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout(); return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent)); }); var services = new ServiceCollection(); services.AddOptions(); services.AddSingleton(CreateHttpContextAccessorWithServerCallContext(deadline, contextCts.Token)); services .AddGrpcClient <Greeter.GreeterClient>(o => { o.Address = baseAddress; }) .EnableCallContextPropagation() .AddInterceptor(() => new CallbackInterceptor(o => options = o)) .ConfigurePrimaryHttpMessageHandler(() => handler); var serviceProvider = services.BuildServiceProvider(validateScopes: true); var clientFactory = CreateGrpcClientFactory(serviceProvider); var client = clientFactory.CreateClient <Greeter.GreeterClient>(nameof(Greeter.GreeterClient)); // Act using var call = client.SayHelloAsync(new HelloRequest(), cancellationToken: userCts.Token); var responseTask = call.ResponseAsync; // Assert Assert.AreEqual(deadline, options.Deadline); // CancellationToken passed to call is a linked cancellation token. // It's created from the context and user tokens. Assert.AreNotEqual(contextCts.Token, options.CancellationToken); Assert.AreNotEqual(userCts.Token, options.CancellationToken); Assert.AreNotEqual(CancellationToken.None, options.CancellationToken); Assert.IsFalse(responseTask.IsCompleted); // Either CTS should cancel call. switch (canceller) { case Canceller.Context: contextCts.Cancel(); break; case Canceller.User: userCts.Cancel(); break; } var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => responseTask).DefaultTimeout(); Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode); ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseHeadersAsync).DefaultTimeout(); Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode); Assert.AreEqual(StatusCode.Cancelled, call.GetStatus().StatusCode); Assert.Throws <InvalidOperationException>(() => call.GetTrailers()); }
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 AsyncDuplexStreamingCall_MessagesStreamed_MessagesReceived() { // Arrange var streamContent = new SyncPointMemoryStream(); PushStreamContent?content = null; var httpClient = ClientTestHelpers.CreateTestClient(async request => { content = (PushStreamContent)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(); Assert.IsNotNull(content); var requestContent = await content !.ReadAsStreamAsync().DefaultTimeout(); var requestMessage = await requestContent.ReadStreamedMessageAsync(NullLogger.Instance, ClientTestHelpers.ServiceMethod.RequestMarshaller.Deserializer, CancellationToken.None).DefaultTimeout(); Assert.AreEqual("1", requestMessage.Name); requestMessage = await requestContent.ReadStreamedMessageAsync(NullLogger.Instance, ClientTestHelpers.ServiceMethod.RequestMarshaller.Deserializer, CancellationToken.None).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 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.ReadMessageAsync( new MemoryStream(requestData), NullLogger.Instance, ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer, "gzip", maximumMessageSize: null, GrpcProtocolConstants.DefaultCompressionProviders, singleMessage: true, 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,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); }
public void DiagnosticListener_MakeCall_ActivityWritten() { // Arrange HttpRequestMessage? requestMessage = null; HttpResponseMessage?responseMessage = null; var httpClient = ClientTestHelpers.CreateTestClient(async request => { requestMessage = request; var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout(); responseMessage = ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent, grpcStatusCode: StatusCode.Aborted); responseMessage.TrailingHeaders().Add(GrpcProtocolConstants.MessageTrailer, "value"); return(responseMessage); }); var invoker = HttpClientCallInvokerFactory.Create(httpClient); var result = new List <KeyValuePair <string, object?> >(); var dataMessageMarshaller = new Marshaller <DataMessage>(m => m.ToByteArray(), data => DataMessage.Parser.ParseFrom(data)); var dataMessageMethod = ClientTestHelpers.GetServiceMethod <DataMessage, DataMessage>( MethodType.DuplexStreaming, dataMessageMarshaller, dataMessageMarshaller); // Act HttpRequestMessage? requestMessage1 = null; HttpResponseMessage?responseMessage1 = null; HttpRequestMessage? requestMessage2 = null; HttpResponseMessage?responseMessage2 = null; using (GrpcDiagnostics.DiagnosticListener.Subscribe(new ObserverToList <KeyValuePair <string, object?> >(result))) { var c1 = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions()); c1.Dispose(); requestMessage1 = requestMessage; responseMessage1 = responseMessage; var c2 = invoker.AsyncDuplexStreamingCall <DataMessage, DataMessage>(dataMessageMethod, string.Empty, new CallOptions()); c2.Dispose(); requestMessage2 = requestMessage; responseMessage2 = responseMessage; } // Assert Assert.AreEqual(4, result.Count); // First call Assert.AreEqual(GrpcDiagnostics.ActivityStartKey, result[0].Key); Assert.AreEqual(requestMessage1, GetValueFromAnonymousType <HttpRequestMessage>(result[0].Value !, "Request")); Assert.AreEqual(GrpcDiagnostics.ActivityStopKey, result[1].Key); Assert.AreEqual(requestMessage1, GetValueFromAnonymousType <HttpRequestMessage>(result[1].Value !, "Request")); Assert.AreEqual(responseMessage1, GetValueFromAnonymousType <HttpResponseMessage>(result[1].Value !, "Response")); // Second call Assert.AreEqual(GrpcDiagnostics.ActivityStartKey, result[2].Key); Assert.AreEqual(requestMessage2, GetValueFromAnonymousType <HttpRequestMessage>(result[2].Value !, "Request")); Assert.AreEqual(GrpcDiagnostics.ActivityStopKey, result[3].Key); Assert.AreEqual(requestMessage2, GetValueFromAnonymousType <HttpRequestMessage>(result[3].Value !, "Request")); Assert.AreEqual(responseMessage2, GetValueFromAnonymousType <HttpResponseMessage>(result[3].Value !, "Response")); // Check types are expected Assert.AreEqual(typeof(GrpcCall.ActivityStartData), result[0].Value !.GetType()); Assert.AreEqual(typeof(GrpcCall.ActivityStopData), result[1].Value !.GetType()); Assert.AreEqual(result[0].Value !.GetType(), result[2].Value !.GetType()); Assert.AreEqual(result[1].Value !.GetType(), result[3].Value !.GetType()); // Check values are unique for each call Assert.AreNotEqual(result[0].Value, result[2].Value); Assert.AreNotEqual(result[1].Value, result[3].Value); }
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(); 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 AsyncClientStreamingCall_ManyParallelCalls_ReadDirectlyToRequestStream() { // Arrange var requestStreams = new List <WriterTestStream>(); var attempts = 100; var callCount = 0; var httpClient = ClientTestHelpers.CreateTestClient(async request => { WriterTestStream writerTestStream; lock (requestStreams) { Interlocked.Increment(ref callCount); writerTestStream = new WriterTestStream(); requestStreams.Add(writerTestStream); } await request.Content !.CopyToAsync(writerTestStream); 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: attempts); var invoker = HttpClientCallInvokerFactory.Create( httpClient, serviceConfig: serviceConfig, configure: o => o.MaxRetryAttempts = attempts); // Act var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions()); var writeAsyncTask = call.RequestStream.WriteAsync(new HelloRequest { Name = "World" }); // Assert await TestHelpers.AssertIsTrueRetryAsync(() => callCount == attempts, "All calls made at once."); var firstMessages = await Task.WhenAll(requestStreams.Select(s => s.WaitForDataAsync())).DefaultTimeout(); await writeAsyncTask.DefaultTimeout(); foreach (var message in firstMessages) { Assert.IsTrue(firstMessages[0].Span.SequenceEqual(message.Span)); } writeAsyncTask = call.RequestStream.WriteAsync(new HelloRequest { Name = "World 2" }); var secondMessages = await Task.WhenAll(requestStreams.Select(s => s.WaitForDataAsync())).DefaultTimeout(); await writeAsyncTask.DefaultTimeout(); foreach (var message in secondMessages) { Assert.IsTrue(secondMessages[0].Span.SequenceEqual(message.Span)); } await call.RequestStream.CompleteAsync().DefaultTimeout(); var rs = await call.ResponseAsync.DefaultTimeout(); Assert.AreEqual("Hello world", rs.Message); Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); }
public async Task AsyncClientStreamingCall_CompressMetadataSentWithRequest_RequestMessageCompressed() { // Arrange HttpRequestMessage?httpRequestMessage = null; HelloRequest? helloRequest1 = null; HelloRequest? helloRequest2 = null; bool?isRequestCompressed1 = null; bool?isRequestCompressed2 = null; var httpClient = ClientTestHelpers.CreateTestClient(async request => { httpRequestMessage = request; var requestData = await request.Content !.ReadAsByteArrayAsync().DefaultTimeout(); var requestStream = new MemoryStream(requestData); isRequestCompressed1 = requestData[0] == 1; helloRequest1 = await StreamSerializationHelper.ReadMessageAsync( requestStream, ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer, "gzip", maximumMessageSize: null, GrpcProtocolConstants.DefaultCompressionProviders, singleMessage: false, CancellationToken.None); isRequestCompressed2 = requestData[requestStream.Position] == 1; helloRequest2 = await StreamSerializationHelper.ReadMessageAsync( requestStream, ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer, "gzip", maximumMessageSize: null, GrpcProtocolConstants.DefaultCompressionProviders, singleMessage: false, CancellationToken.None); var 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); // Act var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, callOptions); await call.RequestStream.WriteAsync(new HelloRequest { Name = "Hello One" }).DefaultTimeout(); call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress); await call.RequestStream.WriteAsync(new HelloRequest { Name = "Hello Two" }).DefaultTimeout(); await call.RequestStream.CompleteAsync().DefaultTimeout(); // Assert var response = await call.ResponseAsync.DefaultTimeout(); Assert.IsNotNull(response); Assert.AreEqual("Hello world", response.Message); CompatibilityHelpers.Assert(httpRequestMessage != null); Assert.AreEqual("identity,gzip,test", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single()); Assert.AreEqual("gzip", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single()); Assert.AreEqual(false, httpRequestMessage.Headers.Contains(GrpcProtocolConstants.CompressionRequestAlgorithmHeader)); CompatibilityHelpers.Assert(helloRequest1 != null); Assert.AreEqual("Hello One", helloRequest1.Name); CompatibilityHelpers.Assert(helloRequest2 != null); Assert.AreEqual("Hello Two", helloRequest2.Name); Assert.IsTrue(isRequestCompressed1); Assert.IsFalse(isRequestCompressed2); }
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); }
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); }
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(); }
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")); }
public async Task AsyncDuplexStreamingCall_MessagesStreamed_MessagesReceived() { // Arrange var streamContent = new SyncPointMemoryStream(); 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; return(ResponseUtils.CreateResponse(HttpStatusCode.OK, new StreamContent(streamContent))); }); var invoker = HttpClientCallInvokerFactory.Create(handler, "https://localhost"); // 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 await requestContentTcs.Task.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); 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()); }