public async Task AsyncUnaryCall_SubdirectoryHandlerConfigured_RequestUriChanged() { // Arrange HttpRequestMessage?httpRequestMessage = null; var handler = TestHttpMessageHandler.Create(async r => { httpRequestMessage = r; var reply = new HelloReply { Message = "Hello world" }; var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout(); return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent)); }); var httpClient = new HttpClient(new SubdirectoryHandler(handler, "/TestSubdirectory")); httpClient.BaseAddress = new Uri("https://localhost"); var invoker = HttpClientCallInvokerFactory.Create(httpClient); // Act var rs = await invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest()); // Assert Assert.AreEqual("Hello world", rs.Message); Assert.IsNotNull(httpRequestMessage); Assert.AreEqual(new Version(2, 0), httpRequestMessage !.Version); Assert.AreEqual(HttpMethod.Post, httpRequestMessage.Method); Assert.AreEqual(new Uri("https://localhost/TestSubdirectory/ServiceName/MethodName"), httpRequestMessage.RequestUri); }
public async Task MoveNext_StreamThrowsIOException_ThrowErrorUnavailable() { // Arrange var handler = TestHttpMessageHandler.Create(request => { var stream = new TestStream(); var content = new StreamContent(stream); return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK, content))); }); var testSink = new TestSink(e => e.LogLevel >= LogLevel.Error); var testLoggerFactory = new TestLoggerFactory(testSink, enabled: true); var channel = CreateChannel(handler, "http://localhost", loggerFactory: testLoggerFactory); var call = CreateGrpcCall(channel); call.StartServerStreaming(new HelloRequest()); // Act var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ClientStreamReader !.MoveNext(CancellationToken.None)).DefaultTimeout(); // Assert Assert.AreEqual(StatusCode.Unavailable, ex.StatusCode); Assert.AreEqual("Error reading next message. IOException: Test", ex.Status.Detail); }
public async Task ResolverReturnsNoAddresses_DeadlineWhileWaitForReady_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(deadline: DateTime.UtcNow.AddSeconds(0.2)).WithWaitForReady(); var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, callOptions, new HelloRequest()); var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout(); Assert.AreEqual(StatusCode.DeadlineExceeded, ex.StatusCode); Assert.AreEqual(string.Empty, ex.Status.Detail); }
public void GlobalSetup() { _content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at ligula nec orci placerat mollis. " + "Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut aliquet non nunc id lobortis. " + "In tincidunt ac sapien sit amet consequat. Interdum et malesuada fames ac ante ipsum primis in faucibus. " + "Duis vel tristique ipsum, eget hendrerit justo. Donec accumsan, purus quis cursus auctor, sapien nisi " + "lacinia ligula, ut vehicula lorem augue vel est. Vestibulum finibus ornare vulputate."; var requestMessage = GetMessageData(new HelloReply { Message = _content }); var handler = TestHttpMessageHandler.Create(async r => { await r.Content.CopyToAsync(Stream.Null); var content = new ByteArrayContent(requestMessage); content.Headers.ContentType = new MediaTypeHeaderValue("application/grpc"); return(ResponseUtils.CreateResponse(HttpStatusCode.OK, content, grpcEncoding: ResponseCompressionAlgorithm)); }); var channel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions { HttpHandler = handler, CompressionProviders = CompressionProviders }); _client = new Greeter.GreeterClient(channel); }
public async Task AsyncUnaryCall_Success_RequestContentSent() { // Arrange HttpContent?content = null; var handler = TestHttpMessageHandler.Create(async request => { content = request.Content; 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 rs = await invoker.AsyncUnaryCall <HelloRequest, HelloReply>( ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest { Name = "World" }).ResponseAsync.DefaultTimeout(); // Assert Assert.AreEqual("Hello world", rs.Message); Assert.IsNotNull(content); var requestContent = await content !.ReadAsStreamAsync().DefaultTimeout(); var requestMessage = await StreamSerializationHelper.ReadMessageAsync( requestContent, ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer, GrpcProtocolConstants.IdentityGrpcEncoding, maximumMessageSize : null, GrpcProtocolConstants.DefaultCompressionProviders, singleMessage : true, CancellationToken.None).DefaultTimeout(); Assert.AreEqual("World", requestMessage !.Name); }
public async Task AsyncUnaryCall_NoTrailers_WinHttpHandler_ThrowsError() { // Arrange var httpMessageHandler = TestHttpMessageHandler.Create(async request => { var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout(); var response = ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent); response.RequestMessage.Properties.Remove("__ResponseTrailers"); response.Headers.Add("custom", "ABC"); return response; }); var invoker = HttpClientCallInvokerFactory.Create(new WinHttpHandler(httpMessageHandler), "https://localhost"); // 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.Cancelled, ex.StatusCode); Assert.AreEqual("No grpc-status found on response. Using gRPC with WinHttp has Windows and package version requirements. See https://aka.ms/aspnet/grpc/netstandard for details.", ex.Status.Detail); Assert.AreEqual(0, ex.Trailers.Count); }
public void GlobalSetup() { var ms = new MemoryStream(); MessageHelpers.WriteMessage(ms, new HelloReply()); var requestMessage = ms.ToArray(); var handler = TestHttpMessageHandler.Create(r => { var content = new ByteArrayContent(requestMessage); content.Headers.ContentType = new MediaTypeHeaderValue("application/grpc"); return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK, content))); }); var httpClient = new HttpClient(handler); var channel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions { HttpClient = httpClient }); _client = new Greeter.GreeterClient(channel); }
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()); }