Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consistent ConfigureAwait on Loopback, RemoteExecutor.DisposeAsync #102699

Merged
merged 34 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b35b727
Add ConfigureAwait(false) to various place
liveans May 26, 2024
adb4656
Revert "Disable parallel test execution for QUIC and HTTP/3 (#101569)"
liveans May 26, 2024
e9cab4d
Disable another AltSvc test
liveans May 26, 2024
2558f17
Disable AltSvc for H/3
liveans May 27, 2024
10eeef1
Add ConfigureAwait to Loopback
liveans May 27, 2024
cc2401b
Put unwanted change back
liveans May 27, 2024
e025609
Revert "Put unwanted change back"
liveans May 27, 2024
b335fab
Delete ConfigureAwait from test code
liveans May 27, 2024
ba37b90
Increase Idle Timeout for Http3LoopbackServer
liveans May 29, 2024
f2c4731
Convert RemoteExecutor Disposal to async
liveans May 30, 2024
8ce9194
Add using
liveans May 30, 2024
9c10f97
Delete custom IdleTimeout
liveans May 30, 2024
1d8afca
Delete Async Disposal of RemoteExecutor
liveans May 30, 2024
d5b78b0
Add RemoteExecutor.DisposeAsync and use it on System.Net.Mail
liveans May 31, 2024
febf3dd
Add RemoteExecutor.DisposeAsync and use it on System.Net.
liveans May 31, 2024
e1117e2
Add RemoteExecutor.DisposeAsync and use it on System.Net.Primitives
liveans May 31, 2024
229304e
Add RemoteExecutor.DisposeAsync and use it on System.Net.Quic
liveans May 31, 2024
d6fba45
Add RemoteExecutor.DisposeAsync and use it on System.Net.Requests
liveans May 31, 2024
e52bce6
Add RemoteExecutor.DisposeAsync and use it on System.Net.Security
liveans May 31, 2024
8759f94
Add RemoteExecutor.DisposeAsync and use it on System.Net.Sockets
liveans May 31, 2024
99cd44e
Add RemoteExecutor.DisposeAsync and use it on Common System.Net
liveans May 31, 2024
e3dbb51
Add RemoteExecutor.DisposeAsync and use it on System.Net.Http - 2
liveans May 31, 2024
9c7184c
Add RemoteExecutor.DisposeAsync and use it on System.Net.Ping
liveans May 31, 2024
0e2c152
Add RemoteExecutor.DisposeAsync and use it on System.Net.Requests - 2
liveans May 31, 2024
13045c9
Add RemoteExecutor.DisposeAsync and use it on System.Net.Security - 2
liveans May 31, 2024
5c5bb53
Add RemoteExecutor.DisposeAsync and use it on System.Net.Sockets - 2
liveans May 31, 2024
3ede1e0
Add RemoteExecutor.DisposeAsync and use it on Common System.Net - 2
liveans May 31, 2024
6bd462f
Merge branch 'main' into attempt_to_fix_an_http3_test
liveans May 31, 2024
dbd5b01
Review Feedback
liveans May 31, 2024
896f0f1
Change DisposeAsync return value signature to ValueTask from Task
liveans Jun 2, 2024
6c01d86
Reapply "Disable parallel test execution for QUIC and HTTP/3 (#101569)"
liveans Jun 3, 2024
4574aa9
Put ActiveIssue's back
liveans Jun 3, 2024
fcb6d45
Delete ActiveIssue to make disable it in other pr with other changes
liveans Jun 3, 2024
e19b233
Add SkipTest back
liveans Jun 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public override async ValueTask DisposeAsync()
// Dispose the connection
// If we already waited for graceful shutdown from the client, then the connection is already closed and this will simply release the handle.
// If not, then this will silently abort the connection.
await _connection.DisposeAsync();
await _connection.DisposeAsync().ConfigureAwait(false);

// Dispose control streams so that we release their handles too.
if (_inboundControlStream is not null)
Expand All @@ -92,12 +92,12 @@ public override async ValueTask DisposeAsync()

public async ValueTask<Http3LoopbackStream> OpenUnidirectionalStreamAsync()
{
return new Http3LoopbackStream(await _connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional));
return new Http3LoopbackStream(await _connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional).ConfigureAwait(false));
}

public async ValueTask<Http3LoopbackStream> OpenBidirectionalStreamAsync()
{
return new Http3LoopbackStream(await _connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional));
return new Http3LoopbackStream(await _connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional).ConfigureAwait(false));
}

public static int GetRequestId(QuicStream stream)
Expand Down Expand Up @@ -141,10 +141,10 @@ async Task EnsureControlStreamAcceptedInternalAsync()
_delayedStreams.Enqueue(quicStream);
}

long? streamType = await controlStream.ReadIntegerAsync();
long? streamType = await controlStream.ReadIntegerAsync().ConfigureAwait(false);
Assert.Equal(Http3LoopbackStream.ControlStream, streamType);

List<(long settingId, long settingValue)> settings = await controlStream.ReadSettingsAsync();
List<(long settingId, long settingValue)> settings = await controlStream.ReadSettingsAsync().ConfigureAwait(false);
(long settingId, long settingValue) = Assert.Single(settings);

Assert.Equal(Http3LoopbackStream.MaxHeaderListSize, settingId);
Expand Down Expand Up @@ -177,17 +177,17 @@ public async Task<Http3LoopbackStream> AcceptRequestStreamAsync()

public async Task<(Http3LoopbackStream clientControlStream, Http3LoopbackStream requestStream)> AcceptControlAndRequestStreamAsync()
{
Http3LoopbackStream requestStream = await AcceptRequestStreamAsync();
Http3LoopbackStream requestStream = await AcceptRequestStreamAsync().ConfigureAwait(false);
Http3LoopbackStream controlStream = _inboundControlStream;

return (controlStream, requestStream);
}

public async Task EstablishControlStreamAsync(SettingsEntry[] settingsEntries)
{
_outboundControlStream = await OpenUnidirectionalStreamAsync();
await _outboundControlStream.SendUnidirectionalStreamTypeAsync(Http3LoopbackStream.ControlStream);
await _outboundControlStream.SendSettingsFrameAsync(settingsEntries);
_outboundControlStream = await OpenUnidirectionalStreamAsync().ConfigureAwait(false);
await _outboundControlStream.SendUnidirectionalStreamTypeAsync(Http3LoopbackStream.ControlStream).ConfigureAwait(false);
await _outboundControlStream.SendSettingsFrameAsync(settingsEntries).ConfigureAwait(false);
}

public async Task DisposeCurrentStream()
Expand All @@ -213,7 +213,7 @@ public override async Task<HttpRequestData> ReadRequestDataAsync(bool readBody =

public override async Task SendResponseAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList<HttpHeaderData> headers = null, string content = "", bool isFinal = true)
{
await _currentStream.SendResponseAsync(statusCode, headers, content, isFinal);
await _currentStream.SendResponseAsync(statusCode, headers, content, isFinal).ConfigureAwait(false);
if (isFinal)
{
await DisposeCurrentStream().ConfigureAwait(false);
Expand All @@ -222,7 +222,7 @@ public override async Task SendResponseAsync(HttpStatusCode statusCode = HttpSta

public override async Task SendResponseBodyAsync(byte[] content, bool isFinal = true)
{
await _currentStream.SendResponseBodyAsync(content, isFinal);
await _currentStream.SendResponseBodyAsync(content, isFinal).ConfigureAwait(false);
if (isFinal)
{
await DisposeCurrentStream().ConfigureAwait(false);
Expand All @@ -249,11 +249,11 @@ public override async Task<HttpRequestData> HandleRequestAsync(HttpStatusCode st
// So, send a GOAWAY frame now so the client won't inadvertantly try to reuse the connection.
// Note that in HTTP3 (unlike HTTP2) there is no strict ordering between the GOAWAY and the response below;
// so the client may race in processing them and we need to handle this.
await _outboundControlStream.SendGoAwayFrameAsync(stream.StreamId + 4);
await _outboundControlStream.SendGoAwayFrameAsync(stream.StreamId + 4).ConfigureAwait(false);

await stream.SendResponseAsync(statusCode, headers, content).ConfigureAwait(false);

await WaitForClientDisconnectAsync();
await WaitForClientDisconnectAsync().ConfigureAwait(false);

return request;
}
Expand All @@ -263,7 +263,7 @@ public async Task ShutdownAsync(bool failCurrentRequest = false)
try
{
long firstInvalidStreamId = failCurrentRequest ? _currentStreamId : _currentStreamId + 4;
await _outboundControlStream.SendGoAwayFrameAsync(firstInvalidStreamId);
await _outboundControlStream.SendGoAwayFrameAsync(firstInvalidStreamId).ConfigureAwait(false);
}
catch (QuicException abortException) when (abortException.QuicError == QuicError.ConnectionAborted && abortException.ApplicationErrorCode == H3_NO_ERROR)
{
Expand All @@ -283,7 +283,7 @@ public async Task ShutdownAsync(bool failCurrentRequest = false)
return;
}

await WaitForClientDisconnectAsync();
await WaitForClientDisconnectAsync().ConfigureAwait(false);
}

// Wait for the client to close the connection, e.g. after we send a GOAWAY, or after the HttpClient is disposed.
Expand Down Expand Up @@ -315,10 +315,10 @@ public async Task WaitForClientDisconnectAsync(bool refuseNewRequests = true)

// The client's control stream should throw QuicConnectionAbortedException, indicating that it was
// aborted because the connection was closed (and was not explicitly closed or aborted prior to the connection being closed)
QuicException ex = await Assert.ThrowsAsync<QuicException>(async () => await _inboundControlStream.ReadFrameAsync());
QuicException ex = await Assert.ThrowsAsync<QuicException>(async () => await _inboundControlStream.ReadFrameAsync().ConfigureAwait(false));
Assert.Equal(QuicError.ConnectionAborted, ex.QuicError);

await CloseAsync(H3_NO_ERROR);
await CloseAsync(H3_NO_ERROR).ConfigureAwait(false);
}

public override async Task WaitForCancellationAsync(bool ignoreIncomingData = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.IO;
using System.Net.Quic;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

Expand Down Expand Up @@ -71,13 +70,13 @@ private async Task<Http3LoopbackConnection> EstablishHttp3ConnectionAsync(params
QuicConnection con = await _listener.AcceptConnectionAsync().ConfigureAwait(false);
Http3LoopbackConnection connection = new Http3LoopbackConnection(con);

await connection.EstablishControlStreamAsync(settingsEntries);
await connection.EstablishControlStreamAsync(settingsEntries).ConfigureAwait(false);
return connection;
}

public override async Task<GenericLoopbackConnection> EstablishGenericConnectionAsync()
{
return await EstablishHttp3ConnectionAsync();
return await EstablishHttp3ConnectionAsync().ConfigureAwait(false);
}

public Task<Http3LoopbackConnection> EstablishConnectionAsync(params SettingsEntry[] settingsEntries)
Expand All @@ -89,12 +88,12 @@ public override async Task AcceptConnectionAsync(Func<GenericLoopbackConnection,
{
await using Http3LoopbackConnection con = await EstablishHttp3ConnectionAsync().ConfigureAwait(false);
await funcAsync(con).ConfigureAwait(false);
await con.ShutdownAsync();
await con.ShutdownAsync().ConfigureAwait(false);
}

public override async Task<HttpRequestData> HandleRequestAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList<HttpHeaderData> headers = null, string content = "")
{
await using Http3LoopbackConnection con = (Http3LoopbackConnection)await EstablishGenericConnectionAsync().ConfigureAwait(false);
await using Http3LoopbackConnection con = await EstablishHttp3ConnectionAsync().ConfigureAwait(false);
return await con.HandleRequestAsync(statusCode, headers, content).ConfigureAwait(false);
}
}
Expand All @@ -113,7 +112,7 @@ public override GenericLoopbackServer CreateServer(GenericLoopbackOptions option
public override async Task CreateServerAsync(Func<GenericLoopbackServer, Uri, Task> funcAsync, int millisecondsTimeout = LoopbackServerTimeoutMilliseconds, GenericLoopbackOptions options = null)
{
using GenericLoopbackServer server = CreateServer(options);
await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout));
await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout)).ConfigureAwait(false);
}

public override Task<GenericLoopbackConnection> CreateConnectionAsync(SocketWrapper socket, Stream stream, GenericLoopbackOptions options = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ private async Task SendPartialHeadersFrameAsync(HttpStatusCode? statusCode, IEnu
{
Memory<byte> payload = ConstructHeadersPayload(statusCode, headers);

await SendFrameHeaderAsync(HeadersFrame, payload.Length);
await SendFrameHeaderAsync(HeadersFrame, payload.Length).ConfigureAwait(false);

// Slice off final byte so the payload is not complete
payload = payload.Slice(0, payload.Length - 1);
Expand All @@ -144,7 +144,7 @@ public async Task SendGoAwayFrameAsync(long firstInvalidStreamId)
int bytesWritten = 0;

bytesWritten += EncodeHttpInteger(firstInvalidStreamId, buffer);
await SendFrameAsync(GoAwayFrame, buffer.AsMemory(0, bytesWritten));
await SendFrameAsync(GoAwayFrame, buffer.AsMemory(0, bytesWritten)).ConfigureAwait(false);
}

private async Task SendFrameHeaderAsync(long frameType, int payloadLength)
Expand Down Expand Up @@ -367,11 +367,11 @@ async Task WaitForReadCancellation()
{
if (ignoreIncomingData)
{
await DrainResponseData();
await DrainResponseData().ConfigureAwait(false);
}
else
{
int bytesRead = await _stream.ReadAsync(new byte[1]);
int bytesRead = await _stream.ReadAsync(new byte[1]).ConfigureAwait(false);
if (bytesRead != 0)
{
throw new Exception($"Unexpected data received while waiting for client cancllation.");
Expand All @@ -388,15 +388,15 @@ async Task WaitForWriteCancellation()
{
try
{
await _stream.WritesClosed;
await _stream.WritesClosed.ConfigureAwait(false);
}
catch (QuicException ex) when (ex.QuicError == QuicError.StreamAborted && ex.ApplicationErrorCode == Http3LoopbackConnection.H3_REQUEST_CANCELLED)
{
writeCanceled = true;
}
}

await Task.WhenAll(WaitForReadCancellation(), WaitForWriteCancellation());
await Task.WhenAll(WaitForReadCancellation(), WaitForWriteCancellation()).ConfigureAwait(false);

if (!readCanceled && !writeCanceled)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ public async Task ProxySetViaEnvironmentVariable_DefaultProxyCredentialsUsed(boo
const string ExpectedPassword = "rightpassword";
LoopbackServer.Options options = new LoopbackServer.Options { IsProxy = true, Username = ExpectedUsername, Password = ExpectedPassword };

await LoopbackServer.CreateClientAndServerAsync(uri => Task.Run(() =>
await LoopbackServer.CreateClientAndServerAsync(uri => Task.Run(async () =>
{
var psi = new ProcessStartInfo();
psi.Environment.Add("http_proxy", $"http://{uri.Host}:{uri.Port}");

RemoteExecutor.Invoke(async (useProxyString, useVersionString, uriString) =>
await RemoteExecutor.Invoke(async (useProxyString, useVersionString, uriString) =>
{
using (HttpClientHandler handler = CreateHttpClientHandler(useVersionString))
using (HttpClient client = CreateHttpClient(handler, useVersionString))
Expand All @@ -111,7 +111,7 @@ await LoopbackServer.CreateClientAndServerAsync(uri => Task.Run(() =>
}, useProxy.ToString(), UseVersion.ToString(),
// If proxy is used , the url does not matter. We set it to be different to avoid confusion.
useProxy ? Configuration.Http.RemoteEchoServer.ToString() : uri.ToString(),
new RemoteInvokeOptions { StartInfo = psi }).Dispose();
new RemoteInvokeOptions { StartInfo = psi }).DisposeAsync();
}),
server => server.AcceptConnectionAsync(async connection =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ public async Task PostAsync_Post_ChannelBinding_ConfiguredCorrectly()

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[PlatformSpecific(TestPlatforms.Linux)]
public void HttpClientUsesSslCertEnvironmentVariables()
public async Task HttpClientUsesSslCertEnvironmentVariables()
{
// We set SSL_CERT_DIR and SSL_CERT_FILE to empty locations.
// The HttpClient should fail to validate the server certificate.
Expand All @@ -395,7 +395,7 @@ public void HttpClientUsesSslCertEnvironmentVariables()
File.WriteAllText(sslCertFile, "");
psi.Environment.Add("SSL_CERT_FILE", sslCertFile);

RemoteExecutor.Invoke(async (useVersionString, allowAllCertificatesString) =>
await RemoteExecutor.Invoke(async (useVersionString, allowAllCertificatesString) =>
{
const string Url = "https://www.microsoft.com";
var version = Version.Parse(useVersionString);
Expand All @@ -405,7 +405,7 @@ public void HttpClientUsesSslCertEnvironmentVariables()
using HttpClient client = CreateHttpClient(handler, useVersionString);

await Assert.ThrowsAsync<HttpRequestException>(() => client.GetAsync(Url));
}, UseVersion.ToString(), AllowAllCertificates.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose();
}, UseVersion.ToString(), AllowAllCertificates.ToString(), new RemoteInvokeOptions { StartInfo = psi }).DisposeAsync();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Sockets;
#if !NETFRAMEWORK
using System.Net.Quic;
#endif
Expand Down
15 changes: 15 additions & 0 deletions src/libraries/Common/tests/System/Net/RemoteExecutorExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading.Tasks;
using Microsoft.DotNet.RemoteExecutor;

namespace Microsoft.DotNet.RemoteExecutor;

internal static class RemoteExecutorExtensions
{
public static async ValueTask DisposeAsync(this RemoteInvokeHandle handle)
{
await Task.Run(handle.Dispose);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
Link="Common\System\Net\EventSourceTestLogging.cs" />
<Compile Include="$(CommonTestPath)System\Net\HttpsTestServer.cs"
Link="Common\System\Net\HttpsTestServer.cs" />
<Compile Include="$(CommonTestPath)System\Net\RemoteExecutorExtensions.cs"
Link="Common\System\Net\RemoteExecutorExtensions.cs" />
<Compile Include="$(CommonTestPath)System\Net\RemoteServerQuery.cs"
Link="Common\System\Net\RemoteServerQuery.cs" />
<Compile Include="$(CommonTestPath)System\Net\VerboseTestLogging.cs"
Expand Down
Loading
Loading