public async Task Deadline_HandleCallAsyncWaitsForDeadlineToFinish() { // Arrange Task?handleCallTask = null; bool?isHandleCallTaskCompleteDuringDeadline = null; var httpContext = HttpContextHelpers.CreateContext(completeAsyncAction: async() => { await Task.Delay(200); isHandleCallTaskCompleteDuringDeadline = handleCallTask?.IsCompleted; }); httpContext.Request.Headers[GrpcProtocolConstants.TimeoutHeader] = "50m"; var call = CreateHandler(MethodType.ClientStreaming, handlerAction: () => Task.Delay(100)); // Act handleCallTask = call.HandleCallAsync(httpContext).DefaultTimeout(); await handleCallTask; // Assert var serverCallContext = httpContext.Features.Get <IServerCallContextFeature>() !; Assert.AreEqual(StatusCode.DeadlineExceeded, serverCallContext.ServerCallContext.Status.StatusCode); Assert.IsFalse(isHandleCallTaskCompleteDuringDeadline); }
public async Task Invoke_ThrowExceptionAwaitedRelease_ReleaseCalledAndErrorThrown() { // Arrange var releaseTcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously); var serviceActivator = new TcsGrpcServiceActivator <TestService>(releaseTcs); var thrownException = new Exception("Exception!"); var invoker = new UnaryServerMethodInvoker <TestService, TestMessage, TestMessage>( (service, reader, context) => throw thrownException, new Method <TestMessage, TestMessage>(MethodType.Unary, "test", "test", _marshaller, _marshaller), HttpContextServerCallContextHelper.CreateMethodOptions(), serviceActivator); var httpContext = HttpContextHelpers.CreateContext(); // Act var task = invoker.Invoke(httpContext, HttpContextServerCallContextHelper.CreateServerCallContext(), new TestMessage()); Assert.False(task.IsCompleted); releaseTcs.SetResult(null); try { await task; Assert.Fail(); } catch (Exception ex) { // Assert Assert.True(serviceActivator.Released); Assert.AreEqual(thrownException, ex); } }
public async Task Invoke_AwaitedSuccess_ReleaseCalled() { // Arrange var methodTcs = new TaskCompletionSource <TestMessage>(TaskCreationOptions.RunContinuationsAsynchronously); var methodResult = new TestMessage(); var serviceActivator = new TestGrpcServiceActivator <TestService>(); var invoker = new UnaryServerMethodInvoker <TestService, TestMessage, TestMessage>( (service, reader, context) => methodTcs.Task, new Method <TestMessage, TestMessage>(MethodType.Unary, "test", "test", _marshaller, _marshaller), HttpContextServerCallContextHelper.CreateMethodOptions(), serviceActivator); var httpContext = HttpContextHelpers.CreateContext(); // Act var task = invoker.Invoke(httpContext, HttpContextServerCallContextHelper.CreateServerCallContext(), new TestMessage()); Assert.False(task.IsCompleted); methodTcs.SetResult(methodResult); var awaitedResult = await task; // Assert Assert.AreEqual(methodResult, awaitedResult); Assert.True(serviceActivator.Released); }
public async Task MaxRequestBodySizeFeature_MethodType_HasMaxRequestBodySize(MethodType methodType, bool hasMaxRequestBodySize) { // Arrange var httpContext = HttpContextHelpers.CreateContext(); var call = CreateHandler(methodType); // Act await call.HandleCallAsync(httpContext).DefaultTimeout(); // Assert Assert.AreEqual(hasMaxRequestBodySize, httpContext.Features.Get <IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize != null); }
public async Task SetResponseTrailers_FeatureMissing_ThrowError() { // Arrange var testSink = new TestSink(); var testLoggerFactory = new TestLoggerFactory(testSink, true); var httpContext = HttpContextHelpers.CreateContext(skipTrailerFeatureSet: true); var call = CreateHandler(MethodType.ClientStreaming, testLoggerFactory); // Act var ex = await ExceptionAssert.ThrowsAsync <InvalidOperationException>(() => call.HandleCallAsync(httpContext)).DefaultTimeout(); // Assert Assert.AreEqual("Trailers are not supported for this response. The server may not support gRPC.", ex.Message); }
public async Task StatusDebugException_ErrorInHandler_SetInDebugException() { // Arrange var ex = new Exception("Test exception"); var httpContext = HttpContextHelpers.CreateContext(); var call = CreateHandler(MethodType.ClientStreaming, handlerAction: () => throw ex); // Act await call.HandleCallAsync(httpContext).DefaultTimeout(); // Assert var serverCallContext = httpContext.Features.Get <IServerCallContextFeature>(); Assert.AreEqual(ex, serverCallContext.ServerCallContext.Status.DebugException); }
public async Task MaxRequestBodySizeFeature_FeatureIsReadOnly_FailureLogged() { // Arrange var testSink = new TestSink(); var testLoggerFactory = new TestLoggerFactory(testSink, true); var httpContext = HttpContextHelpers.CreateContext(isMaxRequestBodySizeFeatureReadOnly: true); var call = CreateHandler(MethodType.ClientStreaming, testLoggerFactory); // Act await call.HandleCallAsync(httpContext).DefaultTimeout(); // Assert Assert.AreEqual(true, httpContext.Features.Get <IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize != null); Assert.IsTrue(testSink.Writes.Any(w => w.EventId.Name == "UnableToDisableMaxRequestBodySizeLimit")); }
public async Task ProtocolValidation_IISHttp2Protocol_Success() { // Arrange var testSink = new TestSink(); var testLoggerFactory = new TestLoggerFactory(testSink, true); var httpContext = HttpContextHelpers.CreateContext(protocol: GrpcProtocolConstants.Http20Protocol); var call = CreateHandler(MethodType.ClientStreaming, testLoggerFactory); // Act await call.HandleCallAsync(httpContext).DefaultTimeout(); // Assert var log = testSink.Writes.SingleOrDefault(w => w.EventId.Name == "UnsupportedRequestProtocol"); Assert.IsNull(log); }
public async Task ProtocolValidation_InvalidProtocol_FailureLogged() { // Arrange var testSink = new TestSink(); var testLoggerFactory = new TestLoggerFactory(testSink, true); var httpContext = HttpContextHelpers.CreateContext(protocol: "HTTP/1.1"); var call = CreateHandler(MethodType.ClientStreaming, testLoggerFactory); // Act await call.HandleCallAsync(httpContext).DefaultTimeout(); // Assert var log = testSink.Writes.SingleOrDefault(w => w.EventId.Name == "UnsupportedRequestProtocol"); Assert.IsNotNull(log); Assert.AreEqual("Request protocol of 'HTTP/1.1' is not supported.", log.Message); }
public async Task ContentTypeValidation_InvalidContentType_FailureLogged() { // Arrange var testSink = new TestSink(); var testLoggerFactory = new TestLoggerFactory(testSink, true); var httpContext = HttpContextHelpers.CreateContext(contentType: "text/plain"); var call = CreateHandler(MethodType.ClientStreaming, testLoggerFactory); // Act await call.HandleCallAsync(httpContext).DefaultTimeout(); // Assert var log = testSink.Writes.SingleOrDefault(w => w.EventId.Name == "UnsupportedRequestContentType"); Assert.IsNotNull(log); Assert.AreEqual("Request content-type of 'text/plain' is not supported.", log.Message); }
public async Task OnServiceMethodDiscovery_ServiceWithDuplicateMethodNames_Success() { // Arrange var services = new ServiceCollection(); services.AddSingleton <GreeterServiceWithDuplicateNames>(); var serverCallHandlerFactory = new ServerCallHandlerFactory <GreeterServiceWithDuplicateNames>( NullLoggerFactory.Instance, Options.Create <GrpcServiceOptions>(new GrpcServiceOptions()), Options.Create <GrpcServiceOptions <GreeterServiceWithDuplicateNames> >(new GrpcServiceOptions <GreeterServiceWithDuplicateNames>()), new TestGrpcServiceActivator <GreeterServiceWithDuplicateNames>()); var provider = new BinderServiceMethodProvider <GreeterServiceWithDuplicateNames>(NullLoggerFactory.Instance); var context = new ServiceMethodProviderContext <GreeterServiceWithDuplicateNames>(serverCallHandlerFactory); var httpContext = HttpContextHelpers.CreateContext(); httpContext.RequestServices = services.BuildServiceProvider(); // Act provider.OnServiceMethodDiscovery(context); // Assert Assert.AreEqual(2, context.Methods.Count); var methodModel = context.Methods[0]; Assert.AreEqual("SayHello", methodModel.Method.Name); var ms = new MemoryStream(); MessageHelpers.WriteMessage(ms, new HelloRequest { Name = "World" }); ms.Seek(0, SeekOrigin.Begin); httpContext.Request.Body = ms; await methodModel.RequestDelegate(httpContext); // Expect 12 (unimplemented) from base type Assert.AreEqual("12", httpContext.Response.Headers["grpc-status"]); }
public void Invoke_ThrowException_ReleaseCalledAndErrorThrown() { // Arrange var serviceActivator = new TestGrpcServiceActivator <TestService>(); var ex = new Exception("Exception!"); var invoker = new UnaryServerMethodInvoker <TestService, TestMessage, TestMessage>( (service, reader, context) => throw ex, new Method <TestMessage, TestMessage>(MethodType.Unary, "test", "test", _marshaller, _marshaller), HttpContextServerCallContextHelper.CreateMethodOptions(), serviceActivator); var httpContext = HttpContextHelpers.CreateContext(); // Act var task = invoker.Invoke(httpContext, HttpContextServerCallContextHelper.CreateServerCallContext(), new TestMessage()); // Assert Assert.True(serviceActivator.Released); Assert.True(task.IsFaulted); Assert.AreEqual(ex, task.Exception !.InnerException); }
public async Task Invoke_SuccessAwaitedRelease_ReleaseCalled() { // Arrange var releaseTcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously); var serviceActivator = new TcsGrpcServiceActivator <TestService>(releaseTcs); var invoker = new UnaryServerMethodInvoker <TestService, TestMessage, TestMessage>( (service, reader, context) => Task.FromResult(new TestMessage()), new Method <TestMessage, TestMessage>(MethodType.Unary, "test", "test", _marshaller, _marshaller), HttpContextServerCallContextHelper.CreateMethodOptions(), serviceActivator); var httpContext = HttpContextHelpers.CreateContext(); // Act var task = invoker.Invoke(httpContext, HttpContextServerCallContextHelper.CreateServerCallContext(), new TestMessage()); Assert.False(task.IsCompleted); releaseTcs.SetResult(null); await task; // Assert Assert.True(serviceActivator.Released); }