Skip to content

Commit 84b8f80

Browse files
authored
[release/7.0-rc1] HTTP/3 flaky test retries and logging (#43423)
* HTTP/3 flaky test retries and logging * Rewrite retry helper to get ports via binding port to 0
1 parent d2c7b65 commit 84b8f80

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,8 @@ public async Task StreamPool_StreamAbortedOnClient_NotPooled()
421421
public async Task StreamPool_StreamAbortedOnClientAndServer_NotPooled()
422422
{
423423
// Arrange
424+
using var httpEventSource = new HttpEventSourceListener(LoggerFactory);
425+
424426
await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory);
425427

426428
var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint);
Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,37 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Net;
5+
using System.Net.Sockets;
46
using Microsoft.Extensions.Logging;
57

68
namespace Microsoft.AspNetCore.Testing;
79

810
public static class ServerRetryHelper
911
{
12+
private const int RetryCount = 10;
13+
1014
/// <summary>
1115
/// Retry a func. Useful when a test needs an explicit port and you want to avoid port conflicts.
1216
/// </summary>
1317
public static async Task BindPortsWithRetry(Func<int, Task> retryFunc, ILogger logger)
1418
{
19+
var ports = GetFreePorts(RetryCount);
20+
1521
var retryCount = 0;
1622
while (true)
1723
{
18-
// Approx dynamic port range on Windows and Linux.
19-
var randomPort = Random.Shared.Next(35000, 60000);
2024

2125
try
2226
{
23-
await retryFunc(randomPort);
27+
await retryFunc(ports[retryCount]);
2428
break;
2529
}
2630
catch (Exception ex)
2731
{
2832
retryCount++;
2933

30-
if (retryCount >= 5)
34+
if (retryCount >= RetryCount)
3135
{
3236
throw;
3337
}
@@ -38,4 +42,35 @@ public static async Task BindPortsWithRetry(Func<int, Task> retryFunc, ILogger l
3842
}
3943
}
4044
}
45+
46+
private static int[] GetFreePorts(int count)
47+
{
48+
var sockets = new List<Socket>();
49+
50+
for (var i = 0; i < count; i++)
51+
{
52+
// Find a port that's free by binding port 0.
53+
// Note that this port should be free when the test runs, but:
54+
// - Something else could steal it before the test uses it.
55+
// - UDP port with the same number could be in use.
56+
// For that reason, some retries should be available.
57+
var ipEndPoint = new IPEndPoint(IPAddress.Loopback, 0);
58+
var listenSocket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
59+
60+
listenSocket.Bind(ipEndPoint);
61+
62+
sockets.Add(listenSocket);
63+
}
64+
65+
// Ports are calculated upfront. Rebinding with port 0 could result the same port
66+
// being returned for each retry.
67+
var ports = sockets.Select(s => (IPEndPoint)s.LocalEndPoint).Select(ep => ep.Port).ToArray();
68+
69+
foreach (var socket in sockets)
70+
{
71+
socket.Dispose();
72+
}
73+
74+
return ports;
75+
}
4176
}

src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3RequestTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ public async Task GET_ServerStreaming_ClientReadsPartialResponse(HttpProtocols p
228228
public async Task POST_ClientSendsOnlyHeaders_RequestReceivedOnServer(HttpProtocols protocol)
229229
{
230230
// Arrange
231+
using var httpEventSource = new HttpEventSourceListener(LoggerFactory);
232+
231233
var builder = CreateHostBuilder(context =>
232234
{
233235
return Task.CompletedTask;

0 commit comments

Comments
 (0)