From 35a136c673ad3b8aa5209b776c4b906536a1b818 Mon Sep 17 00:00:00 2001 From: Miha Zupan Date: Mon, 24 Jun 2024 18:47:46 +0200 Subject: [PATCH] Test --- .../tests/FunctionalTests/DiagnosticsTests.cs | 1 + .../SocketsHttpHandlerTest.Cancellation.cs | 60 +++++++++++++------ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs index 9059a05d49f6b..af1b3cedb6fc6 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs @@ -18,6 +18,7 @@ namespace System.Net.Http.Functional.Tests { + [ActiveIssue("Foo")] public abstract class DiagnosticsTest : HttpClientHandlerTestBase { private const string EnableActivityPropagationEnvironmentVariableSettingName = "DOTNET_SYSTEM_NET_HTTP_ENABLEACTIVITYPROPAGATION"; 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 ae1669c18e68b..4d983302d8791 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Cancellation.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Cancellation.cs @@ -10,6 +10,7 @@ using Microsoft.DotNet.RemoteExecutor; using Xunit; using Xunit.Abstractions; +using TestUtilities; namespace System.Net.Http.Functional.Tests { @@ -18,6 +19,11 @@ public abstract class SocketsHttpHandler_Cancellation_Test : HttpClientHandler_C { protected SocketsHttpHandler_Cancellation_Test(ITestOutputHelper output) : base(output) { } + [Fact] public async Task ValidateConnectTimeout2() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ValidateConnectTimeout3() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact][OuterLoop] public async Task ValidateConnectTimeout4() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact][OuterLoop] public async Task ValidateConnectTimeout5() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + private async Task ValidateConnectTimeout(HttpMessageInvoker invoker, Uri uri, int minElapsed, int maxElapsed) { var sw = Stopwatch.StartNew(); @@ -81,6 +87,11 @@ public async Task ConnectTimeout_ConnectCallbackTimesOut_Throws(bool useSsl) options: new GenericLoopbackOptions() { UseSsl = useSsl }); } + [Fact] public async Task ConnectTimeout_PlaintextStreamFilterTimesOut_Throws2() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task ConnectTimeout_PlaintextStreamFilterTimesOut_Throws3() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact][OuterLoop] public async Task ConnectTimeout_PlaintextStreamFilterTimesOut_Throws4() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact][OuterLoop] public async Task ConnectTimeout_PlaintextStreamFilterTimesOut_Throws5() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [OuterLoop] [Fact] public async Task ConnectTimeout_PlaintextStreamFilterTimesOut_Throws() @@ -107,36 +118,35 @@ public async Task ConnectTimeout_PlaintextStreamFilterTimesOut_Throws() 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][OuterLoop] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection4() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact][OuterLoop] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection5() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Theory] [InlineData(true)] [InlineData(false)] public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(bool useSsl) { - if (UseVersion == HttpVersion.Version30) + if (UseVersion.Major != 1 || !TestAsync || !useSsl) { - // HTTP3 does not support ConnectCallback return; } - if (!TestAsync) - { - // Test relies on ordering of async operations, so we can't test the sync case - 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 +155,8 @@ public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSu Assert.True(connectCount <= 2); + _output.WriteLine($"Connection count {connectCount}"); + if (isFirstConnection) { tcsFirstConnectionInitiated.SetResult(); @@ -157,6 +169,8 @@ public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSu // 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 +184,34 @@ public async Task ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSu }; 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); + 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); + _output.WriteLine("ThrowsAnyAsync"); // Signal connections to proceed tcsFirstRequestCanceled.SetResult(); // Second request should succeed, even though the first connection failed HttpResponseMessage resp2 = await t2; + _output.WriteLine("resp2"); Assert.Equal(HttpStatusCode.OK, resp2.StatusCode); Assert.Equal("Hello world", await resp2.Content.ReadAsStringAsync()); + + Assert.True(connectCount == 2); } }, async server => { - await server.AcceptConnectionSendResponseAndCloseAsync(content: "Hello world"); + await server.HandleRequestAsync(content: "Hello world"); + _output.WriteLine("Server done"); }, options: new GenericLoopbackOptions() { UseSsl = useSsl }); } @@ -393,6 +414,11 @@ public async Task PendingConnectionTimeout_HighValue_PendingConnectionIsNotCance }, UseVersion.ToString(), timeout.ToString()).DisposeAsync(); } + [Fact] public async Task PendingConnectionTimeout_HighValue_PendingConnectionIsNotCancelled2() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] public async Task PendingConnectionTimeout_HighValue_PendingConnectionIsNotCancelled3() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] [OuterLoop] public async Task PendingConnectionTimeout_HighValue_PendingConnectionIsNotCancelled4() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + [Fact] [OuterLoop] public async Task PendingConnectionTimeout_HighValue_PendingConnectionIsNotCancelled5() => await ConnectionFailure_AfterInitialRequestCancelled_SecondRequestSucceedsOnNewConnection(true); + private sealed class SetTcsContent : StreamContent { private readonly TaskCompletionSource _tcs;