diff --git a/eng/test-configuration.json b/eng/test-configuration.json index adea26ddb23335..abbbdf47600543 100644 --- a/eng/test-configuration.json +++ b/eng/test-configuration.json @@ -3,7 +3,6 @@ "defaultOnFailure": "fail", "localRerunCount": 2, "retryOnRules": [ - { "testAssembly": { "wildcard": "System.Net.*" } }, { "failureMessage": { "regex": ".*Timed out after .* waiting for the browser to be ready.*" } }, { "failureMessage": { "regex": "System.IO.IOException : Process for .*chrome.*unexpectedly exited.* during startup" } } ] diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Cancellation.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Cancellation.cs index ae1669c18e68b8..68646e95861fb0 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Cancellation.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Cancellation.cs @@ -4,12 +4,14 @@ using System.Diagnostics; using System.IO; using System.Net.Sockets; +using System.Linq; using System.Net.Test.Common; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.RemoteExecutor; using Xunit; using Xunit.Abstractions; +using TestUtilities; namespace System.Net.Http.Functional.Tests { @@ -107,7 +109,21 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => options: new GenericLoopbackOptions() { UseSsl = false }); } - [OuterLoop] + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection2() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection3() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection4() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection5() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection6() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection7() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection8() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection9() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection10() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection11() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection12() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection13() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection14() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection15() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Theory] [InlineData(true)] [InlineData(false)] @@ -125,18 +141,19 @@ public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSu return; } + using var listener = new TestEventListener(_output, TestEventListener.NetworkingEvents); + await LoopbackServerFactory.CreateClientAndServerAsync(async uri => { int connectCount = 0; - TaskCompletionSource tcsFirstConnectionInitiated = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - TaskCompletionSource tcsFirstRequestCanceled = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcsFirstConnectionInitiated = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcsFirstRequestCanceled = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using (var handler = CreateHttpClientHandler(allowAllCertificates: true)) - using (var client = CreateHttpClient(handler)) + using (HttpClientHandler handler = CreateHttpClientHandler()) + using (HttpClient client = CreateHttpClient(handler)) { - var socketsHandler = GetUnderlyingSocketsHttpHandler(handler); - socketsHandler.ConnectCallback = async (context, token) => + GetUnderlyingSocketsHttpHandler(handler).ConnectCallback = async (context, token) => { // Note we force serialization of connection creation by waiting on tcsFirstConnectionInitiated below, // so we don't need to worry about concurrent access to connectCount. @@ -145,6 +162,8 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => Assert.True(connectCount <= 2); + _output.WriteLine($"Connection count {connectCount}"); + if (isFirstConnection) { tcsFirstConnectionInitiated.SetResult(); @@ -157,6 +176,8 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => // Wait until first request is cancelled and has completed await tcsFirstRequestCanceled.Task; + _output.WriteLine($"After tcsFirstRequestCanceled {isFirstConnection}"); + if (isFirstConnection) { // Fail the first connection attempt @@ -170,27 +191,34 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => }; using CancellationTokenSource cts = new CancellationTokenSource(); - Task t1 = client.SendAsync(new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion, VersionPolicy = HttpVersionPolicy.RequestVersionExact }, cts.Token); + Task t1 = client.SendAsync(CreateRequest(HttpMethod.Get, uri, UseVersion, exactVersion: true), cts.Token); + _output.WriteLine("t1"); // Wait for the connection attempt to be initiated before we send the second request, to avoid races in connection creation - await tcsFirstConnectionInitiated.Task; - Task t2 = client.SendAsync(new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion, VersionPolicy = HttpVersionPolicy.RequestVersionExact }, default); + await tcsFirstConnectionInitiated.Task.WaitAsync(TestHelper.PassingTestTimeout); + Task t2 = client.SendAsync(CreateRequest(HttpMethod.Get, uri, UseVersion, exactVersion: true), CancellationToken.None); + _output.WriteLine("t2"); // Cancel the first message and wait for it to complete cts.Cancel(); - await Assert.ThrowsAnyAsync(() => t1); + await Assert.ThrowsAnyAsync(() => t1).WaitAsync(TestHelper.PassingTestTimeout); + _output.WriteLine("ThrowsAnyAsync"); // Signal connections to proceed tcsFirstRequestCanceled.SetResult(); // Second request should succeed, even though the first connection failed - HttpResponseMessage resp2 = await t2; + HttpResponseMessage resp2 = await t2.WaitAsync(TestHelper.PassingTestTimeout); + _output.WriteLine("resp2"); Assert.Equal(HttpStatusCode.OK, resp2.StatusCode); - Assert.Equal("Hello world", await resp2.Content.ReadAsStringAsync()); + Assert.Equal("Hello world", await resp2.Content.ReadAsStringAsync().WaitAsync(TestHelper.PassingTestTimeout)); + + Assert.True(connectCount == 2); } }, async server => { - await server.AcceptConnectionSendResponseAndCloseAsync(content: "Hello world"); + await server.HandleRequestAsync(content: "Hello world").WaitAsync(TestHelper.PassingTestTimeout); + _output.WriteLine("Server done"); }, options: new GenericLoopbackOptions() { UseSsl = useSsl }); }