public async Task HostActivityTags_ReturnedInTrailers_Success()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Content = new GrpcStreamContent(ms);
            httpRequest.Headers.Add("return-tags-trailers", "true");

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            var responseMessage = await response.GetSuccessfulGrpcMessageAsync <HelloReply>().DefaultTimeout();

            Assert.AreEqual("Hello World", responseMessage.Message);
            response.AssertTrailerStatus();

            var trailers = response.TrailingHeaders;

            Assert.AreEqual("0", trailers.GetValues("grpc.status_code").Single());
            Assert.AreEqual("/Greet.Greeter/SayHello", trailers.GetValues("grpc.method").Single());
        }
示例#2
0
        public async Task SendCompressedMessage_ServiceHasNoCompressionConfigured_ResponseIdentityEncoding()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage, "gzip");

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, "gzip");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            Assert.IsFalse(response.Headers.Contains(GrpcProtocolConstants.MessageEncodingHeader));

            var responseMessage = MessageHelpers.AssertReadMessage <HelloReply>(await response.Content.ReadAsByteArrayAsync().DefaultTimeout());

            Assert.AreEqual("Hello World", responseMessage.Message);
            response.AssertTrailerStatus();
        }
示例#3
0
        public async Task SendCompressedMessageWithIdentity_ReturnInternalError()
        {
            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                return(writeContext.LoggerName == "SERVER " + typeof(GreeterService).FullName &&
                       writeContext.EventId.Name == "RpcConnectionError" &&
                       writeContext.State.ToString() == "Error status code 'Internal' raised.");
            });

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage, "gzip");

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, "identity");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);

            response.AssertTrailerStatus(StatusCode.Internal, "Request sent 'identity' grpc-encoding value with compressed message.");
        }
        public async Task MultipleMessagesThenClose_SuccessResponse()
        {
            // Arrange
            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, new CounterRequest
            {
                Count = 1
            });

            var httpRequest = GrpcHttpHelper.Create("Count.Counter/AccumulateCount");

            httpRequest.Content = new PushStreamContent(
                async s =>
            {
                await s.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();
                await s.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();
                await s.WriteAsync(Array.Empty <byte>()).AsTask().DefaultTimeout();
            });

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);

            // Assert
            Assert.IsFalse(responseTask.IsCompleted, "Server should wait for client to finish streaming");


            var response = await responseTask.DefaultTimeout();

            var reply = await response.GetSuccessfulGrpcMessageAsync <CounterReply>().DefaultTimeout();

            Assert.AreEqual(2, reply.Count);
            response.AssertTrailerStatus();
        }
示例#5
0
        public async Task StreamedMessage_SuccessResponseAfterMessageReceived()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, requestMessage);

            var streamingContent = new StreamingContent();
            var httpRequest      = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Content = streamingContent;

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);

            // Assert
            Assert.IsFalse(responseTask.IsCompleted, "Server should wait for client to finish streaming");

            var requestStream = await streamingContent.GetRequestStreamAsync().DefaultTimeout();

            await requestStream.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();

            streamingContent.Complete();

            var response = await responseTask.DefaultTimeout();

            var responseMessage = await response.GetSuccessfulGrpcMessageAsync <HelloReply>().DefaultTimeout();

            Assert.AreEqual("Hello World", responseMessage.Message);
        }
示例#6
0
        public async Task UnimplementedContentType_ReturnUnimplementedForAppGrpc(string contentType, string httpMethod, HttpStatusCode httpStatusCode, StatusCode?grpcStatusCode)
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("HasMapped/Extra");

            httpRequest.Method  = new HttpMethod(httpMethod);
            httpRequest.Content = new StreamContent(requestStream);
            httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(httpStatusCode, response.StatusCode);
            if (grpcStatusCode != null)
            {
                Assert.AreEqual(grpcStatusCode.Value.ToTrailerString(), response.Headers.GetValues(GrpcProtocolConstants.StatusTrailer).Single());
            }
            else
            {
                Assert.IsFalse(response.Headers.TryGetValues(GrpcProtocolConstants.StatusTrailer, out _));
                Assert.IsFalse(response.TrailingHeaders.TryGetValues(GrpcProtocolConstants.StatusTrailer, out _));
            }
        }
示例#7
0
        public async Task SendCompressedMessageAndReturnResultWithNoCompressFlag_ResponseNotCompressed()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage, "gzip");

            var httpRequest = GrpcHttpHelper.Create("Compression.CompressionService/WriteMessageWithoutCompression");

            httpRequest.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, "gzip");
            httpRequest.Headers.Add(GrpcProtocolConstants.MessageAcceptEncodingHeader, "gzip");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);

            // The overall encoding is gzip but the actual response does not use compression
            Assert.AreEqual("gzip", response.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single());

            var responseMessage = MessageHelpers.AssertReadMessage <HelloReply>(await response.Content.ReadAsByteArrayAsync().DefaultTimeout());

            Assert.AreEqual("Hello World", responseMessage.Message);
            response.AssertTrailerStatus();
        }
        public async Task CallAuthorizedServiceWithToken_Success()
        {
            // Arrange
            var tokenResponse = await Fixture.Client.GetAsync("generateJwtToken").DefaultTimeout();

            var token = await tokenResponse.Content.ReadAsStringAsync().DefaultTimeout();

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("Authorize.AuthorizedGreeter/SayHello");

            httpRequest.Headers.Add("Authorization", $"Bearer {token}");
            httpRequest.Content = new GrpcStreamContent(ms);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            var responseMessage = await response.GetSuccessfulGrpcMessageAsync <HelloReply>().DefaultTimeout();

            Assert.AreEqual("Hello World", responseMessage.Message);
            response.AssertTrailerStatus();
        }
示例#9
0
        public async Task SendIdentityGrpcAcceptEncodingToServiceWithCompression_ResponseUncompressed()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("Compression.CompressionService/SayHello");

            httpRequest.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, "identity");
            httpRequest.Headers.Add(GrpcProtocolConstants.MessageAcceptEncodingHeader, "identity");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            Assert.AreEqual("identity", response.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single());

            var responseMessage = MessageHelpers.AssertReadMessage <HelloReply>(await response.Content.ReadAsByteArrayAsync().DefaultTimeout());

            Assert.AreEqual("Hello World", responseMessage.Message);
            response.AssertTrailerStatus();
        }
示例#10
0
        public async Task HttpContextExtensionMethod_ReturnContextInTrailer()
        {
            // Arrange
            var url = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>((request, context) =>
            {
                var httpContext = context.GetHttpContext();
                context.ResponseTrailers.Add("Test-HttpContext-PathAndQueryString", httpContext.Request.Path + httpContext.Request.QueryString);

                return(Task.FromResult(new HelloReply {
                    Message = "Hello " + request.Name
                }));
            });

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create($"{url}?query=extra");

            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            response.AssertIsSuccessfulGrpcRequest();
            response.AssertTrailerStatus();
            Assert.AreEqual($"{url}?query=extra", response.TrailingHeaders.GetValues("Test-HttpContext-PathAndQueryString").Single());
        }
        public async Task CompleteThenIncompleteMessage_ErrorResponse()
        {
            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                if (writeContext.LoggerName == "SERVER " + typeof(CounterService).FullName &&
                    writeContext.EventId.Name == "RpcConnectionError" &&
                    writeContext.State.ToString() == "Error status code 'Internal' raised." &&
                    GetRpcExceptionDetail(writeContext.Exception) == "Incomplete message.")
                {
                    return(true);
                }

                if (writeContext.LoggerName == "SERVER " + typeof(CounterService).FullName &&
                    writeContext.EventId.Name == "ErrorReadingMessage" &&
                    writeContext.State.ToString() == "Error reading message." &&
                    GetRpcExceptionDetail(writeContext.Exception) == "Incomplete message.")
                {
                    return(true);
                }

                return(false);
            });

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, new CounterRequest
            {
                Count = 1
            });

            var httpRequest = GrpcHttpHelper.Create("Count.Counter/AccumulateCount");

            httpRequest.Content = new PushStreamContent(
                async s =>
            {
                // Complete message
                await s.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();
                await s.FlushAsync().DefaultTimeout();

                // Incomplete message and finish
                await s.WriteAsync(ms.ToArray().AsSpan().Slice(0, (int)ms.Length - 1).ToArray()).AsTask().DefaultTimeout();
                await s.FlushAsync().DefaultTimeout();
            });

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);

            // Assert
            Assert.IsFalse(responseTask.IsCompleted, "Server should wait for client to finish streaming");

            var response = await responseTask.DefaultTimeout();

            // Read to end of response so headers are available
            await response.Content.CopyToAsync(new MemoryStream()).DefaultTimeout();

            response.AssertTrailerStatus(StatusCode.Internal, "Incomplete message.");
        }
        private static HttpRequestMessage CreateRequestMessage(string path)
        {
            var httpRequestMessage = GrpcHttpHelper.Create(path, HttpMethod.Options);

            httpRequestMessage.Headers.Add("Origin", "http://localhost");
            httpRequestMessage.Headers.Add("Access-Control-Request-Method", "POST");

            return(httpRequestMessage);
        }
        public async Task SendCompressedMessageWithUnsupportedEncoding_ReturnUnimplemented()
        {
            // Arrange
            var expectedError =
#if NET6_0_OR_GREATER
                "Unsupported grpc-encoding value 'DOES_NOT_EXIST'. Supported encodings: identity, gzip, deflate";
#else
                "Unsupported grpc-encoding value 'DOES_NOT_EXIST'. Supported encodings: identity, gzip";
#endif

            SetExpectedErrorsFilter(writeContext =>
            {
                if (writeContext.LoggerName == TestConstants.ServerCallHandlerTestName &&
                    writeContext.EventId.Name == "ErrorReadingMessage" &&
                    writeContext.State.ToString() == "Error reading message." &&
                    GetRpcExceptionDetail(writeContext.Exception) == expectedError)
                {
                    return(true);
                }

                return(false);
            });

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();
            MessageHelpers.WriteMessage(
                requestStream,
                requestMessage,
                "DOES_NOT_EXIST",
                new List <ICompressionProvider>
            {
                new DoesNotExistCompressionProvider()
            });

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");
            httpRequest.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, "DOES_NOT_EXIST");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
#if NET6_0_OR_GREATER
            Assert.AreEqual("identity,gzip,deflate", response.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single());
#else
            Assert.AreEqual("identity,gzip", response.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single());
#endif

            response.AssertTrailerStatus(StatusCode.Unimplemented, expectedError);

            AssertHasLogRpcConnectionError(StatusCode.Unimplemented, expectedError);
        }
示例#14
0
        public async Task AdditionalDataAfterStreamedMessage_ErrorResponse()
        {
            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                if (writeContext.LoggerName == TestConstants.ServerCallHandlerTestName &&
                    writeContext.EventId.Name == "RpcConnectionError" &&
                    writeContext.State.ToString() == "Error status code 'Internal' raised.")
                {
                    return(true);
                }

                if (writeContext.LoggerName == TestConstants.ServerCallHandlerTestName &&
                    writeContext.EventId.Name == "ErrorReadingMessage" &&
                    writeContext.State.ToString() == "Error reading message.")
                {
                    return(true);
                }

                return(false);
            });

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, requestMessage);

            var streamingContent = new StreamingContent();
            var httpRequest      = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Content = streamingContent;

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);

            // Assert
            Assert.IsFalse(responseTask.IsCompleted, "Server should wait for client to finish streaming");

            var requestStream = await streamingContent.GetRequestStreamAsync().DefaultTimeout();

            await requestStream.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();

            await requestStream.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();

            streamingContent.Complete();

            var response = await responseTask.DefaultTimeout();

            // Read to end of response so headers are available
            await response.Content.CopyToAsync(new MemoryStream()).DefaultTimeout();

            response.AssertTrailerStatus(StatusCode.Internal, "Additional data after the message received.");
        }
        public async Task UnaryMethodDeadlineExceeded(bool throwErrorOnCancellation)
        {
            async Task <HelloReply> WaitUntilDeadline(HelloRequest request, ServerCallContext context)
            {
                try
                {
                    await Task.Delay(1000, context.CancellationToken);
                }
                catch (OperationCanceledException) when(!throwErrorOnCancellation)
                {
                    // nom nom nom
                }

                return(new HelloReply());
            }

            SetExpectedErrorsFilter(writeContext =>
            {
                if (writeContext.LoggerName == TestConstants.ServerCallHandlerTestName)
                {
                    // Deadline happened before write
                    if (writeContext.EventId.Name == "ErrorExecutingServiceMethod" &&
                        writeContext.State.ToString() == "Error when executing service method 'WaitUntilDeadline-True'.")
                    {
                        return(true);
                    }
                }

                return(false);
            });

            var method = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>(WaitUntilDeadline, $"{nameof(WaitUntilDeadline)}-{throwErrorOnCancellation}");

            var grpcWebClient = CreateGrpcWebClient();

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Headers.Add(GrpcProtocolConstants.TimeoutHeader, "100m");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await grpcWebClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout();

            // Assert
            response.AssertIsSuccessfulGrpcRequest();
            response.AssertTrailerStatus(StatusCode.DeadlineExceeded, "Deadline Exceeded");
        }
示例#16
0
        public async Task WriteUntilDeadline_SuccessResponsesStreamed_CoreAsync(ServerStreamingServerMethod <HelloRequest, HelloReply> callHandler)
        {
            // Arrange
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <HelloRequest, HelloReply>(callHandler);

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Headers.Add(GrpcProtocolConstants.TimeoutHeader, "200m");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout();

            // Assert
            response.AssertIsSuccessfulGrpcRequest();

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            var messageCount = 0;

            var readTask = Task.Run(async() =>
            {
                while (true)
                {
                    var greeting = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader).DefaultTimeout();

                    if (greeting != null)
                    {
                        Assert.AreEqual($"How are you World? {messageCount}", greeting.Message);
                        messageCount++;
                    }
                    else
                    {
                        break;
                    }
                }
            });

            await readTask.DefaultTimeout();

            Assert.AreNotEqual(0, messageCount);

            response.AssertTrailerStatus(StatusCode.DeadlineExceeded, "Deadline Exceeded");
        }
示例#17
0
        public async Task SendCompressedMessageWithUnsupportedEncoding_ReturnUnimplemented()
        {
            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                if (writeContext.LoggerName == "SERVER " + typeof(GreeterService).FullName &&
                    writeContext.EventId.Name == "RpcConnectionError" &&
                    writeContext.State.ToString() == "Error status code 'Unimplemented' raised." &&
                    GetRpcExceptionDetail(writeContext.Exception) == "Unsupported grpc-encoding value 'DOES_NOT_EXIST'. Supported encodings: gzip")
                {
                    return(true);
                }

                if (writeContext.LoggerName == "SERVER " + typeof(GreeterService).FullName &&
                    writeContext.EventId.Name == "ErrorReadingMessage" &&
                    writeContext.State.ToString() == "Error reading message." &&
                    GetRpcExceptionDetail(writeContext.Exception) == "Unsupported grpc-encoding value 'DOES_NOT_EXIST'. Supported encodings: gzip")
                {
                    return(true);
                }

                return(false);
            });

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(
                requestStream,
                requestMessage,
                "DOES_NOT_EXIST",
                new List <ICompressionProvider>
            {
                new DoesNotExistCompressionProvider()
            });

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, "DOES_NOT_EXIST");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            Assert.AreEqual("gzip", response.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single());

            response.AssertTrailerStatus(StatusCode.Unimplemented, "Unsupported grpc-encoding value 'DOES_NOT_EXIST'. Supported encodings: gzip");
        }
示例#18
0
        public async Task SendCompressedMessage_UnaryEnabledInCallWithInvalidSetting_UncompressedMessageReturned()
        {
            async Task <HelloReply> UnaryEnableCompression(HelloRequest request, ServerCallContext context)
            {
                var headers = new Metadata {
                    new Metadata.Entry("grpc-internal-encoding-request", "PURPLE_MONKEY_DISHWASHER")
                };
                await context.WriteResponseHeadersAsync(headers);

                return(new HelloReply {
                    Message = "Hello " + request.Name
                });
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>(UnaryEnableCompression);

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, new HelloRequest
            {
                Name = "World"
            });

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Content = new PushStreamContent(
                async s =>
            {
                await s.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();
                await s.FlushAsync().DefaultTimeout();
            });

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest);

            // Assert
            var response = await responseTask.DefaultTimeout();

            response.AssertIsSuccessfulGrpcRequest();

            // Because the client didn't send this encoding in accept, the server has sent the message uncompressed.
            Assert.AreEqual("PURPLE_MONKEY_DISHWASHER", response.Headers.GetValues("grpc-encoding").Single());

            var returnedMessageData = await response.Content.ReadAsByteArrayAsync().DefaultTimeout();

            Assert.AreEqual(0, returnedMessageData[0]);

            var responseMessage = MessageHelpers.AssertReadMessage <HelloReply>(returnedMessageData);

            Assert.AreEqual("Hello World", responseMessage.Message);
            response.AssertTrailerStatus();
        }
        public async Task WriteResponseHeadersAsyncCore_FlushesHeadersToClient()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHellosSendHeadersFirst");

            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout();

            // Assert
            response.AssertIsSuccessfulGrpcRequest();

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            for (var i = 0; i < 3; i++)
            {
                var greetingTask = MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

                // The headers are already sent
                // All responses are streamed
                Assert.False(greetingTask.IsCompleted);

                var greeting = await greetingTask.DefaultTimeout();

                Assert.AreEqual($"How are you World? {i}", greeting.Message);
            }

            var goodbyeTask = MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.False(goodbyeTask.IsCompleted);
            Assert.AreEqual("Goodbye World!", (await goodbyeTask.DefaultTimeout()).Message);

            var finishedTask = MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.IsNull(await finishedTask.DefaultTimeout());
        }
示例#20
0
        public async Task SendCompressedMessageWithoutEncodingHeader_ServerErrorResponse()
        {
            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                if (writeContext.LoggerName == TestConstants.ServerCallHandlerTestName &&
                    writeContext.EventId.Name == "RpcConnectionError" &&
                    writeContext.State.ToString() == "Error status code 'Internal' raised." &&
                    GetRpcExceptionDetail(writeContext.Exception) == "Request did not include grpc-encoding value with compressed message.")
                {
                    return(true);
                }

                if (writeContext.LoggerName == TestConstants.ServerCallHandlerTestName &&
                    writeContext.EventId.Name == "ErrorReadingMessage" &&
                    writeContext.State.ToString() == "Error reading message." &&
                    GetRpcExceptionDetail(writeContext.Exception) == "Request did not include grpc-encoding value with compressed message.")
                {
                    return(true);
                }

                return(false);
            });


            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage, "gzip");

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            response.AssertTrailerStatus(StatusCode.Internal, "Request did not include grpc-encoding value with compressed message.");
        }
        public async Task SendCompressedMessageWithIdentity_ReturnInternalError(string algorithmName)
        {
            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                if (writeContext.LoggerName == TestConstants.ServerCallHandlerTestName &&
                    writeContext.EventId.Name == "ErrorReadingMessage" &&
                    writeContext.State.ToString() == "Error reading message.")
                {
                    return(true);
                }

                return(false);
            });

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage, algorithmName);

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, "identity");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);

            response.AssertTrailerStatus(StatusCode.Internal, "Request sent 'identity' grpc-encoding value with compressed message.");

            AssertHasLogRpcConnectionError(StatusCode.Internal, "Request sent 'identity' grpc-encoding value with compressed message.");
        }
示例#22
0
        public async Task HttpContextAccessor_ReturnContextInTrailer()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHelloWithHttpContextAccessor?query=extra");

            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            response.AssertIsSuccessfulGrpcRequest();
            response.AssertTrailerStatus();
            Assert.AreEqual("/Greet.Greeter/SayHelloWithHttpContextAccessor?query=extra", response.TrailingHeaders.GetValues("Test-HttpContext-PathAndQueryString").Single());
        }
        public async Task CallAuthorizedServiceWithInvalidToken_ReturnUnauthorized()
        {
            // Arrange

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("Authorize.AuthorizedGreeter/SayHello");

            httpRequest.Headers.Add("Authorization", $"Bearer SomeInvalidTokenHere");
            httpRequest.Content = new GrpcStreamContent(ms);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode);
        }
示例#24
0
        public async Task SendUnsupportedEncodingHeaderWithUncompressedMessage_ReturnUncompressedMessage()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("Greet.Greeter/SayHello");

            httpRequest.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, "DOES_NOT_EXIST");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            response.AssertTrailerStatus();
        }
示例#25
0
        public async Task HttpContextExtensionMethod_ReturnContextInTrailer()
        {
            // Arrange
            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create("Greet.ServiceDoesNotExist/Method");

            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest).DefaultTimeout();

            // Assert
            response.AssertIsSuccessfulGrpcRequest();

            response.AssertTrailerStatus(StatusCode.Unimplemented, "Service is unimplemented.");
        }
示例#26
0
        public async Task WriteUntilDeadline_SuccessResponsesStreamed_CoreAsync(ServerStreamingServerMethod <HelloRequest, HelloReply> callHandler)
        {
            // Arrange
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <HelloRequest, HelloReply>(callHandler);

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Headers.Add(GrpcProtocolConstants.TimeoutHeader, "200m");
            httpRequest.Content = new GrpcStreamContent(requestStream);

            try
            {
                // Act
                var response = await Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout();

                // Assert
                response.AssertIsSuccessfulGrpcRequest();

                var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

                var pipeReader = PipeReader.Create(responseStream);

                var messageCount = 0;

                var readTask = Task.Run(async() =>
                {
                    while (true)
                    {
                        var greeting = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader).DefaultTimeout();

                        if (greeting != null)
                        {
                            Assert.AreEqual($"How are you World? {messageCount}", greeting.Message);
                            messageCount++;
                        }
                        else
                        {
                            break;
                        }
                    }
                });

                await readTask.DefaultTimeout();

                Assert.AreNotEqual(0, messageCount);

                response.AssertTrailerStatus(StatusCode.DeadlineExceeded, "Deadline Exceeded");
            }
            catch (Exception ex) when(Net.Client.Internal.GrpcProtocolHelpers.ResolveRpcExceptionStatusCode(ex) == StatusCode.Cancelled)
            {
                // Ignore exception from deadline abort
            }

            Assert.True(HasLog(LogLevel.Debug, "DeadlineExceeded", "Request with timeout of 00:00:00.2000000 has exceeded its deadline."));

            await TestHelpers.AssertIsTrueRetryAsync(
                () => HasLog(LogLevel.Trace, "DeadlineStopped", "Request deadline stopped."),
                "Missing deadline stopped log.").DefaultTimeout();
        }
示例#27
0
        public async Task SendCompressedMessage_ServerStreamingEnabledInCall_CompressedMessageReturned()
        {
            async Task ServerStreamingEnableCompression(HelloRequest request, IServerStreamWriter <HelloReply> responseStream, ServerCallContext context)
            {
                var headers = new Metadata {
                    new Metadata.Entry("grpc-internal-encoding-request", "gzip")
                };
                await context.WriteResponseHeadersAsync(headers);

                await responseStream.WriteAsync(new HelloReply { Message = "Hello 1" });

                responseStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress);
                await responseStream.WriteAsync(new HelloReply { Message = "Hello 2" });
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <HelloRequest, HelloReply>(ServerStreamingEnableCompression);

            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, new HelloRequest
            {
                Name = "World"
            });

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Content = new PushStreamContent(
                async s =>
            {
                await s.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();
                await s.FlushAsync().DefaultTimeout();
            });

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest);

            // Assert
            var response = await responseTask.DefaultTimeout();

            response.AssertIsSuccessfulGrpcRequest();

            Assert.AreEqual("gzip", response.Headers.GetValues("grpc-encoding").Single());

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            ReadResult readResult;

            readResult = await pipeReader.ReadAsync();

            Assert.AreEqual(1, readResult.Buffer.FirstSpan[0]); // Message is compressed
            var greeting1 = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader, "gzip").DefaultTimeout();

            Assert.AreEqual($"Hello 1", greeting1.Message);

            readResult = await pipeReader.ReadAsync();

            Assert.AreEqual(0, readResult.Buffer.FirstSpan[0]); // Message is uncompressed
            var greeting2 = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader, "gzip").DefaultTimeout();

            Assert.AreEqual($"Hello 2", greeting2.Message);

            var finishedTask = MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.IsNull(await finishedTask.DefaultTimeout());
        }
示例#28
0
        public async Task NoBuffering_SuccessResponsesStreamed()
        {
            using var httpEventSource = new HttpEventSourceListener(LoggerFactory);

            var methodWrapper = new MethodWrapper
            {
                Logger    = Logger,
                SyncPoint = new SyncPoint(runContinuationsAsynchronously: true)
            };

            async Task SayHellos(HelloRequest request, IServerStreamWriter <HelloReply> responseStream, ServerCallContext context)
            {
                // Explicitly send the response headers before any streamed content
                Metadata responseHeaders = new Metadata();

                responseHeaders.Add("test-response-header", "value");
                await context.WriteResponseHeadersAsync(responseHeaders);

                await methodWrapper.SayHellosAsync(request, responseStream);
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <HelloRequest, HelloReply>(SayHellos);

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var response = await Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout();

            // Assert
            response.AssertIsSuccessfulGrpcRequest();

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            for (var i = 0; i < 3; i++)
            {
                var greetingTask = MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

                Assert.IsFalse(greetingTask.IsCompleted);

                await methodWrapper.SyncPoint.WaitForSyncPoint().DefaultTimeout();

                var currentSyncPoint = methodWrapper.SyncPoint;
                methodWrapper.SyncPoint = new SyncPoint(runContinuationsAsynchronously: true);
                currentSyncPoint.Continue();

                var greeting = (await greetingTask.DefaultTimeout()) !;

                Assert.AreEqual($"How are you World? {i}", greeting.Message);
            }

            var goodbyeTask = MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.False(goodbyeTask.IsCompleted);

            await methodWrapper.SyncPoint.WaitForSyncPoint().DefaultTimeout();

            methodWrapper.SyncPoint.Continue();

            Assert.AreEqual("Goodbye World!", (await goodbyeTask.DefaultTimeout()) !.Message);

            var finishedTask = MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader);

            Assert.IsNull(await finishedTask.DefaultTimeout());
        }
        public async Task MultipleMessagesFromOneClient_SuccessResponses()
        {
            // Arrange
            var ms = new MemoryStream();

            MessageHelpers.WriteMessage(ms, new ChatMessage
            {
                Name    = "John",
                Message = "Hello Jill"
            });

            var streamingContent = new StreamingContent();
            var httpRequest      = GrpcHttpHelper.Create("Chat.Chatter/Chat");

            httpRequest.Content = streamingContent;

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);

            // Assert
            Assert.IsFalse(responseTask.IsCompleted, "Server should wait for first message from client");

            var requestStream = await streamingContent.GetRequestStreamAsync().DefaultTimeout();

            await requestStream.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();

            await requestStream.FlushAsync().DefaultTimeout();

            var response = await responseTask.DefaultTimeout();

            response.AssertIsSuccessfulGrpcRequest();

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            var message1Task = MessageHelpers.AssertReadStreamMessageAsync <ChatMessage>(pipeReader);
            var message1     = await message1Task.DefaultTimeout();

            Assert.AreEqual("John", message1.Name);
            Assert.AreEqual("Hello Jill", message1.Message);

            var message2Task = MessageHelpers.AssertReadStreamMessageAsync <ChatMessage>(pipeReader);

            Assert.IsFalse(message2Task.IsCompleted, "Server is waiting for messages from client");

            ms = new MemoryStream();
            MessageHelpers.WriteMessage(ms, new ChatMessage
            {
                Name    = "Jill",
                Message = "Hello John"
            });

            await requestStream.WriteAsync(ms.ToArray()).AsTask().DefaultTimeout();

            await requestStream.FlushAsync().DefaultTimeout();

            var message2 = await message2Task.DefaultTimeout();

            Assert.AreEqual("Jill", message2.Name);
            Assert.AreEqual("Hello John", message2.Message);

            var finishedTask = MessageHelpers.AssertReadStreamMessageAsync <ChatMessage>(pipeReader);

            Assert.IsFalse(finishedTask.IsCompleted, "Server is waiting for client to end streaming");

            // Complete request stream
            streamingContent.Complete();

            await finishedTask.DefaultTimeout();

            response.AssertTrailerStatus();
        }
示例#30
0
        public async Task Buffering_SuccessResponsesStreamed()
        {
            var methodWrapper = new MethodWrapper
            {
                Logger    = Logger,
                SyncPoint = new SyncPoint(runContinuationsAsynchronously: true)
            };

            Task SayHellosBufferHint(HelloRequest request, IServerStreamWriter <HelloReply> responseStream, ServerCallContext context)
            {
                context.WriteOptions = new WriteOptions(WriteFlags.BufferHint);

                return(methodWrapper.SayHellosAsync(request, responseStream));
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <HelloRequest, HelloReply>(SayHellosBufferHint);

            var requestMessage = new HelloRequest
            {
                Name = "World"
            };

            var requestStream = new MemoryStream();

            MessageHelpers.WriteMessage(requestStream, requestMessage);

            var httpRequest = GrpcHttpHelper.Create(method.FullName);

            httpRequest.Content = new GrpcStreamContent(requestStream);

            // Act
            var responseTask = Fixture.Client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout();

            // Assert
            Assert.IsFalse(responseTask.IsCompleted, "Server should wait for first message from client");

            await methodWrapper.SyncPoint.WaitForSyncPoint().DefaultTimeout();

            methodWrapper.SyncPoint.Continue();

            var response = await responseTask.DefaultTimeout();

            response.AssertIsSuccessfulGrpcRequest();

            var responseStream = await response.Content.ReadAsStreamAsync().DefaultTimeout();

            var pipeReader = PipeReader.Create(responseStream);

            for (var i = 0; i < 3; i++)
            {
                var greeting = (await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader).DefaultTimeout()) !;

                Assert.AreEqual($"How are you World? {i}", greeting.Message);
            }

            var goodbye = await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader).DefaultTimeout();

            Assert.AreEqual("Goodbye World!", goodbye !.Message);

            Assert.IsNull(await MessageHelpers.AssertReadStreamMessageAsync <HelloReply>(pipeReader).DefaultTimeout());

            response.AssertTrailerStatus();
        }