Fix SendAsync_No100ContinueReceived_RequestBodySentEventually test flakiness (dotnet...
authorStephen Toub <stoub@microsoft.com>
Thu, 2 May 2019 18:56:19 +0000 (14:56 -0400)
committerGitHub <noreply@github.com>
Thu, 2 May 2019 18:56:19 +0000 (14:56 -0400)
The server in the test was sending down the entire response and then trying to read the data from the client.  If the client sent its whole payload and read the response before the server go around to doing the read, the client might close the connection, in which case the read might fail.  The fix just changes the server code to only send down the headers, then read the data from the client, and only then finish the response, at which point it's fine if the client closes the connection.

Commit migrated from https://github.com/dotnet/corefx/commit/772aa2d1029caa8be3b360168b63dadd42ae788b

src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs
src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs

index c2c0e3d..b6a20b4 100644 (file)
@@ -305,13 +305,16 @@ namespace System.Net.Test.Common
         }
 
         public static string GetHttpResponse(HttpStatusCode statusCode = HttpStatusCode.OK, string additionalHeaders = null, string content = null, bool connectionClose = false) =>
+            GetHttpResponseHeaders(statusCode, additionalHeaders, content, connectionClose) +
+            content;
+
+        public static string GetHttpResponseHeaders(HttpStatusCode statusCode = HttpStatusCode.OK, string additionalHeaders = null, string content = null, bool connectionClose = false) =>
             $"HTTP/1.1 {(int)statusCode} {GetStatusDescription(statusCode)}\r\n" +
             (connectionClose ? "Connection: close\r\n" : "") +
             $"Date: {DateTimeOffset.UtcNow:R}\r\n" +
             $"Content-Length: {(content == null ? 0 : content.Length)}\r\n" +
             additionalHeaders +
-            "\r\n" +
-            content;
+            "\r\n";
 
         public static string GetSingleChunkHttpResponse(HttpStatusCode statusCode = HttpStatusCode.OK, string additionalHeaders = null, string content = null, bool connectionClose = false) =>
             $"HTTP/1.1 {(int)statusCode} {GetStatusDescription(statusCode)}\r\n" +
@@ -571,9 +574,14 @@ namespace System.Net.Test.Common
                 return lines;
             }
 
+            public async Task SendResponseAsync(string response)
+            {
+                await _writer.WriteAsync(response).ConfigureAwait(false);
+            }
+
             public async Task SendResponseAsync(HttpStatusCode statusCode = HttpStatusCode.OK, string additionalHeaders = null, string content = null)
             {
-                await _writer.WriteAsync(GetHttpResponse(statusCode, additionalHeaders, content)).ConfigureAwait(false);
+                await SendResponseAsync(GetHttpResponse(statusCode, additionalHeaders, content)).ConfigureAwait(false);
             }
 
             public async Task<List<string>> ReadRequestHeaderAndSendCustomResponseAsync(string response)
index 04b5736..883db8b 100644 (file)
@@ -2064,30 +2064,36 @@ namespace System.Net.Http.Functional.Tests
             if (IsCurlHandler) return;
 
             var clientFinished = new TaskCompletionSource<bool>();
-            const string TestString = "test";
+            const string RequestString = "request";
+            const string ResponseString = "response";
 
             await LoopbackServer.CreateClientAndServerAsync(async uri =>
             {
                 using (HttpClient client = CreateHttpClient())
                 {
                     HttpRequestMessage initialMessage = new HttpRequestMessage(HttpMethod.Post, uri) { Version = VersionFromUseHttp2 };
-                    initialMessage.Content = new StringContent(TestString);
+                    initialMessage.Content = new StringContent(RequestString);
                     initialMessage.Headers.ExpectContinue = true;
-                    HttpResponseMessage response = await client.SendAsync(initialMessage);
+                    using (HttpResponseMessage response = await client.SendAsync(initialMessage))
+                    {
+                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+                        Assert.Equal(ResponseString, await response.Content.ReadAsStringAsync());
+                    }
 
-                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                     clientFinished.SetResult(true);
                 }
             }, async server =>
             {
                 await server.AcceptConnectionAsync(async connection =>
                 {
-                    // Send final status code 200.
-                    await connection.ReadRequestHeaderAndSendResponseAsync();
+                    await connection.ReadRequestHeaderAsync();
+                    await connection.SendResponseAsync(LoopbackServer.GetHttpResponseHeaders(HttpStatusCode.OK, content: ResponseString));
 
-                    var result = new char[TestString.Length];
-                    await connection.ReadBlockAsync(result, 0, TestString.Length);
-                    Assert.Equal(TestString, new string(result));
+                    var result = new char[RequestString.Length];
+                    await connection.ReadBlockAsync(result, 0, RequestString.Length);
+                    Assert.Equal(RequestString, new string(result));
+
+                    await connection.SendResponseAsync(ResponseString);
 
                     await clientFinished.Task;
                 });