Fix Send_TimeoutResponseContent_Throws (#44356)
authorStephen Toub <stoub@microsoft.com>
Fri, 6 Nov 2020 21:51:41 +0000 (16:51 -0500)
committerGitHub <noreply@github.com>
Fri, 6 Nov 2020 21:51:41 +0000 (16:51 -0500)
If the client times out too quickly, the server may never have a connection to accept and will hang forever.

src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientTest.cs

index 94a15be..a267ced 100644 (file)
@@ -1076,42 +1076,33 @@ namespace System.Net.Http.Functional.Tests
 
         [Fact]
         [OuterLoop]
-        public async Task Send_TimeoutResponseContent_Throws()
+        public void Send_TimeoutResponseContent_Throws()
         {
-            string content = "Test content";
+            const string Content = "Test content";
 
-            await LoopbackServer.CreateClientAndServerAsync(
-                async uri =>
-                {
-                    var sendTask = Task.Run(() => {
-                        using HttpClient httpClient = CreateHttpClient();
-                        httpClient.Timeout = TimeSpan.FromSeconds(0.5);
-                        HttpResponseMessage response = httpClient.Send(new HttpRequestMessage(HttpMethod.Get, uri));
-                    });
+            using var server = new LoopbackServer();
 
-                    TaskCanceledException ex = await Assert.ThrowsAsync<TaskCanceledException>(() => sendTask);
-                    Assert.IsType<TimeoutException>(ex.InnerException);
-                },
-                async server =>
+            // Ignore all failures from the server. This includes being disposed of before ever accepting a connection,
+            // which is possible if the client times out so quickly that it hasn't initiated a connection yet.
+            _ = server.AcceptConnectionAsync(async connection =>
+            {
+                await connection.ReadRequestDataAsync();
+                await connection.SendResponseAsync(headers: new[] { new HttpHeaderData("Content-Length", (Content.Length * 100).ToString()) });
+                for (int i = 0; i < 100; ++i)
                 {
-                    await server.AcceptConnectionAsync(async connection =>
-                    {
-                        try
-                        {
-                            await connection.ReadRequestDataAsync();
-                            await connection.SendResponseAsync(headers: new List<HttpHeaderData>() {
-                                new HttpHeaderData("Content-Length", (content.Length * 100).ToString())
-                            });
-                            for (int i = 0; i < 100; ++i)
-                            {
-                                await connection.Writer.WriteLineAsync(content);
-                                await connection.Writer.FlushAsync();
-                                await Task.Delay(TimeSpan.FromSeconds(0.1));
-                            }
-                        }
-                        catch { }
-                    });
-                }); 
+                    await connection.Writer.WriteLineAsync(Content);
+                    await connection.Writer.FlushAsync();
+                    await Task.Delay(TimeSpan.FromSeconds(0.1));
+                }
+            });
+
+            TaskCanceledException ex = Assert.Throws<TaskCanceledException>(() =>
+            {
+                using HttpClient httpClient = CreateHttpClient();
+                httpClient.Timeout = TimeSpan.FromSeconds(0.5);
+                HttpResponseMessage response = httpClient.Send(new HttpRequestMessage(HttpMethod.Get, server.Address));
+            });
+            Assert.IsType<TimeoutException>(ex.InnerException);
         }
 
         public static IEnumerable<object[]> VersionSelectionMemberData()