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); }
public async Task BidirectionalStreaming(string scheme) { var hostBuilder = new HostBuilder() .ConfigureWebHost(webHostBuilder => { ConfigureKestrel(webHostBuilder, scheme); webHostBuilder.ConfigureServices(AddTestLogging) .Configure(app => app.Run(async context => { var reader = context.Request.BodyReader; // Read Hello World and echo it back to the client, twice for (var i = 0; i < 2; i++) { var readResult = await reader.ReadAsync().DefaultTimeout(); while (!readResult.IsCompleted && readResult.Buffer.Length < "Hello World".Length) { reader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End); readResult = await reader.ReadAsync().DefaultTimeout(); } var sequence = readResult.Buffer.Slice(0, "Hello World".Length); Assert.True(sequence.IsSingleSegment); await context.Response.BodyWriter.WriteAsync(sequence.First).DefaultTimeout(); reader.AdvanceTo(sequence.End); } var finalResult = await reader.ReadAsync().DefaultTimeout(); Assert.True(finalResult.IsCompleted && finalResult.Buffer.Length == 0); })); }); using var host = await hostBuilder.StartAsync().DefaultTimeout(); var url = host.MakeUrl(scheme); using var client = CreateClient(); client.DefaultRequestHeaders.ExpectContinue = true; var streamingContent = new StreamingContent(); var request = CreateRequestMessage(HttpMethod.Post, url, streamingContent); var responseTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout(); // The server won't send headers until it gets the first message await streamingContent.SendAsync("Hello World").DefaultTimeout(); var response = await responseTask; Assert.Equal(HttpVersion.Version20, response.Version); var stream = await response.Content.ReadAsStreamAsync().DefaultTimeout(); await ReadStreamHelloWorld(stream); await streamingContent.SendAsync("Hello World").DefaultTimeout(); streamingContent.Complete(); await ReadStreamHelloWorld(stream); Assert.Equal(0, await stream.ReadAsync(new byte[10], 0, 10).DefaultTimeout()); await host.StopAsync().DefaultTimeout(); }
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 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(); }
public async Task ReverseEcho(string scheme) { var clientEcho = new TaskCompletionSource <string>(TaskCreationOptions.RunContinuationsAsynchronously); var hostBuilder = new HostBuilder() .ConfigureWebHost(webHostBuilder => { ConfigureKestrel(webHostBuilder, scheme); webHostBuilder.ConfigureServices(AddTestLogging) .Configure(app => app.Run(async context => { // Prime it? // var readTask = context.Request.BodyReader.ReadAsync(); context.Response.ContentType = "text/plain"; await context.Response.WriteAsync("Hello World"); await context.Response.CompleteAsync().DefaultTimeout(); try { // var readResult = await readTask; // context.Request.BodyReader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End); using var streamReader = new StreamReader(context.Request.Body); var read = await streamReader.ReadToEndAsync().DefaultTimeout(); clientEcho.SetResult(read); } catch (Exception ex) { clientEcho.SetException(ex); } })); }); using var host = await hostBuilder.StartAsync().DefaultTimeout(); var url = host.MakeUrl(scheme); using var client = CreateClient(); // client.DefaultRequestHeaders.ExpectContinue = true; var streamingContent = new StreamingContent(); var request = CreateRequestMessage(HttpMethod.Post, url, streamingContent); using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout(); Assert.Equal(HttpVersion.Version20, response.Version); // Read Hello World and echo it back to the server. /* https://github.com/dotnet/corefx/issues/39404 * var read = await response.Content.ReadAsStringAsync().DefaultTimeout(); * Assert.Equal("Hello World", read); */ var stream = await response.Content.ReadAsStreamAsync().DefaultTimeout(); await ReadStreamHelloWorld(stream).DefaultTimeout(); Assert.Equal(0, await stream.ReadAsync(new byte[10], 0, 10).DefaultTimeout()); stream.Dispose(); // https://github.com/dotnet/corefx/issues/39404 can be worked around by commenting out this Dispose await streamingContent.SendAsync("Hello World").DefaultTimeout(); streamingContent.Complete(); Assert.Equal("Hello World", await clientEcho.Task.DefaultTimeout()); await host.StopAsync().DefaultTimeout(); }
public async Task BidirectionalStreamingMoreClientData(string scheme) { var lastPacket = new TaskCompletionSource <string>(TaskCreationOptions.RunContinuationsAsynchronously); var hostBuilder = new HostBuilder() .ConfigureWebHost(webHostBuilder => { ConfigureKestrel(webHostBuilder, scheme); webHostBuilder.ConfigureServices(AddTestLogging) .Configure(app => app.Run(async context => { var reader = context.Request.BodyReader; var readResult = await reader.ReadAsync().DefaultTimeout(); while (!readResult.IsCompleted && readResult.Buffer.Length < "Hello World".Length) { reader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End); readResult = await reader.ReadAsync().DefaultTimeout(); } var sequence = readResult.Buffer.Slice(0, "Hello World".Length); Assert.True(sequence.IsSingleSegment); await context.Response.BodyWriter.WriteAsync(sequence.First).DefaultTimeout(); reader.AdvanceTo(sequence.End); await context.Response.CompleteAsync().DefaultTimeout(); try { // The client sends one more packet after the server completes readResult = await reader.ReadAsync().DefaultTimeout(); while (!readResult.IsCompleted && readResult.Buffer.Length < "Hello World".Length) { reader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.End); readResult = await reader.ReadAsync().DefaultTimeout(); } Assert.True(readResult.Buffer.IsSingleSegment); var result = Encoding.UTF8.GetString(readResult.Buffer.FirstSpan); reader.AdvanceTo(readResult.Buffer.End); var finalResult = await reader.ReadAsync().DefaultTimeout(); Assert.True(finalResult.IsCompleted && finalResult.Buffer.Length == 0); lastPacket.SetResult(result); } catch (Exception ex) { lastPacket.SetException(ex); } })); }); using var host = await hostBuilder.StartAsync().DefaultTimeout(); var url = host.MakeUrl(scheme); using var client = CreateClient(); client.DefaultRequestHeaders.ExpectContinue = true; var streamingContent = new StreamingContent(); var request = CreateRequestMessage(HttpMethod.Post, url, streamingContent); var responseTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).DefaultTimeout(); // The server doesn't respond until we send the first set of data await streamingContent.SendAsync("Hello World").DefaultTimeout(); var response = await responseTask; Assert.Equal(HttpVersion.Version20, response.Version); var stream = await response.Content.ReadAsStreamAsync(); await ReadStreamHelloWorld(stream); Assert.Equal(0, await stream.ReadAsync(new byte[10], 0, 10).DefaultTimeout()); stream.Dispose(); // https://github.com/dotnet/corefx/issues/39404 can be worked around by commenting out this Dispose // Send one more message after the server has finished. await streamingContent.SendAsync("Hello World").DefaultTimeout(); streamingContent.Complete(); var lastData = await lastPacket.Task.DefaultTimeout(); Assert.Equal("Hello World", lastData); await host.StopAsync().DefaultTimeout(); }