From 01dbb52836bd2aea04b407fc0e3adabfb2f0e0ae Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Sun, 7 May 2023 00:42:19 +0200 Subject: [PATCH 1/9] Added necessary test for ALPN Change on QUIC --- .../FunctionalTests/QuicListenerTests.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index 51d2b23fce26c..b28ae6811c44e 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -372,5 +372,63 @@ await Task.WhenAll( await connection.DisposeAsync(); }).WaitAsync(TimeSpan.FromSeconds(5))); } + + [Fact] + public async Task Listener_AlpnChange_Success() { + var listenerOptions = new QuicListenerOptions() + { + ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), + ApplicationProtocols = new List() + { + new SslApplicationProtocol("foo"), + new SslApplicationProtocol("bar"), + new SslApplicationProtocol("test"), + }, + ConnectionOptionsCallback = (_, _, _) => + { + var options = CreateQuicServerOptions(); + options.ServerAuthenticationOptions.ApplicationProtocols = new() + { + new SslApplicationProtocol("bar"), + new SslApplicationProtocol("test"), + }; + return ValueTask.FromResult(options); + } + }; + await using QuicListener listener = await CreateQuicListener(listenerOptions); + + QuicClientConnectionOptions clientOptions1 = CreateQuicClientOptions(listener.LocalEndPoint); + clientOptions1.ClientAuthenticationOptions.ApplicationProtocols = new() + { + new SslApplicationProtocol("bar"), + }; + ValueTask connectTask1 = CreateQuicConnection(clientOptions1); + await using QuicConnection serverConnection1 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + await using QuicConnection clientConnection1 = await connectTask1.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + + Assert.Equal(clientConnection1.NegotiatedApplicationProtocol, new SslApplicationProtocol("bar")); + + QuicClientConnectionOptions clientOptions2 = CreateQuicClientOptions(listener.LocalEndPoint); + clientOptions2.ClientAuthenticationOptions.ApplicationProtocols = new() + { + new SslApplicationProtocol("test"), + }; + ValueTask connectTask2 = CreateQuicConnection(clientOptions2); + await using QuicConnection serverConnection2 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + await using QuicConnection clientConnection2 = await connectTask1.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + + Assert.Equal(clientConnection2.NegotiatedApplicationProtocol, new SslApplicationProtocol("test")); + + QuicClientConnectionOptions clientOptions3 = CreateQuicClientOptions(listener.LocalEndPoint); + clientOptions3.ClientAuthenticationOptions.ApplicationProtocols = new() + { + new SslApplicationProtocol("foo"), + }; + ValueTask connectTask3 = CreateQuicConnection(clientOptions3); + await using QuicConnection serverConnection3 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + await using QuicConnection clientConnection3 = await connectTask1.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + + Assert.NotEqual(clientConnection3.NegotiatedApplicationProtocol, new SslApplicationProtocol("foo")); + } } } From 28a2efe94e6c6dd1002800009403cbfec7bc2d7b Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Tue, 23 May 2023 21:54:18 +0200 Subject: [PATCH 2/9] Alpn test fix --- .../FunctionalTests/QuicListenerTests.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index b28ae6811c44e..d1ad5109b96a1 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -374,7 +374,7 @@ await Task.WhenAll( } [Fact] - public async Task Listener_AlpnChange_Success() { + public async Task Listener_AlpnChange() { var listenerOptions = new QuicListenerOptions() { ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), @@ -386,6 +386,7 @@ public async Task Listener_AlpnChange_Success() { }, ConnectionOptionsCallback = (_, _, _) => { + // Narrowing down alpn list to more specific. var options = CreateQuicServerOptions(); options.ServerAuthenticationOptions.ApplicationProtocols = new() { @@ -397,38 +398,41 @@ public async Task Listener_AlpnChange_Success() { }; await using QuicListener listener = await CreateQuicListener(listenerOptions); + // Successful connection with bar ALPN QuicClientConnectionOptions clientOptions1 = CreateQuicClientOptions(listener.LocalEndPoint); clientOptions1.ClientAuthenticationOptions.ApplicationProtocols = new() { + new SslApplicationProtocol("foo"), new SslApplicationProtocol("bar"), }; ValueTask connectTask1 = CreateQuicConnection(clientOptions1); await using QuicConnection serverConnection1 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30)); await using QuicConnection clientConnection1 = await connectTask1.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); - Assert.Equal(clientConnection1.NegotiatedApplicationProtocol, new SslApplicationProtocol("bar")); + Assert.Equal(new SslApplicationProtocol("bar"), clientConnection1.NegotiatedApplicationProtocol); + // Successful connection with test ALPN QuicClientConnectionOptions clientOptions2 = CreateQuicClientOptions(listener.LocalEndPoint); clientOptions2.ClientAuthenticationOptions.ApplicationProtocols = new() { + new SslApplicationProtocol("foo"), new SslApplicationProtocol("test"), }; ValueTask connectTask2 = CreateQuicConnection(clientOptions2); await using QuicConnection serverConnection2 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30)); - await using QuicConnection clientConnection2 = await connectTask1.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + await using QuicConnection clientConnection2 = await connectTask2.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); - Assert.Equal(clientConnection2.NegotiatedApplicationProtocol, new SslApplicationProtocol("test")); + Assert.Equal(new SslApplicationProtocol("test"), clientConnection2.NegotiatedApplicationProtocol); + // Failure case should throw QuicException QuicClientConnectionOptions clientOptions3 = CreateQuicClientOptions(listener.LocalEndPoint); clientOptions3.ClientAuthenticationOptions.ApplicationProtocols = new() { new SslApplicationProtocol("foo"), }; ValueTask connectTask3 = CreateQuicConnection(clientOptions3); - await using QuicConnection serverConnection3 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30)); - await using QuicConnection clientConnection3 = await connectTask1.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); - - Assert.NotEqual(clientConnection3.NegotiatedApplicationProtocol, new SslApplicationProtocol("foo")); + await Assert.ThrowsAsync(() => listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30))); + await Assert.ThrowsAsync(() => connectTask3.AsTask().WaitAsync(TimeSpan.FromSeconds(30))); } } } From 9ca6e7cbcbc76cd2c3504dbb783a0b05be36c203 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Tue, 23 May 2023 22:40:44 +0200 Subject: [PATCH 3/9] Update src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs Co-authored-by: Natalia Kondratyeva --- .../System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index d1ad5109b96a1..f73b59efadc43 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -374,7 +374,7 @@ await Task.WhenAll( } [Fact] - public async Task Listener_AlpnChange() { + public async Task Listener_AlpnNarrowingDown() { var listenerOptions = new QuicListenerOptions() { ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), From 77ec3bd0551f3eb446c0beb65146e60289ca0b58 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Wed, 24 May 2023 14:36:01 +0200 Subject: [PATCH 4/9] Review feedback and marking failure case with active issue --- .../FunctionalTests/QuicListenerTests.cs | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index f73b59efadc43..33cd658121cf1 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -374,7 +374,7 @@ await Task.WhenAll( } [Fact] - public async Task Listener_AlpnNarrowingDown() { + public async Task Listener_AlpnNarrowingDown_Success() { var listenerOptions = new QuicListenerOptions() { ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), @@ -423,16 +423,42 @@ public async Task Listener_AlpnNarrowingDown() { await using QuicConnection clientConnection2 = await connectTask2.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); Assert.Equal(new SslApplicationProtocol("test"), clientConnection2.NegotiatedApplicationProtocol); + } + + [ActiveIssue("https://github.com/dotnet/runtime/issues/86701")] + [Fact] + public async Task Listener_AlpnNarrowingDown_Failure() { + var listenerOptions = new QuicListenerOptions() + { + ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), + ApplicationProtocols = new List() + { + new SslApplicationProtocol("foo"), + new SslApplicationProtocol("bar"), + new SslApplicationProtocol("test"), + }, + ConnectionOptionsCallback = (_, _, _) => + { + // Narrowing down alpn list to more specific. + var options = CreateQuicServerOptions(); + options.ServerAuthenticationOptions.ApplicationProtocols = new() + { + new SslApplicationProtocol("bar"), + new SslApplicationProtocol("test"), + }; + return ValueTask.FromResult(options); + } + }; + await using QuicListener listener = await CreateQuicListener(listenerOptions); - // Failure case should throw QuicException - QuicClientConnectionOptions clientOptions3 = CreateQuicClientOptions(listener.LocalEndPoint); - clientOptions3.ClientAuthenticationOptions.ApplicationProtocols = new() + QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(listener.LocalEndPoint); + clientOptions.ClientAuthenticationOptions.ApplicationProtocols = new() { new SslApplicationProtocol("foo"), }; - ValueTask connectTask3 = CreateQuicConnection(clientOptions3); - await Assert.ThrowsAsync(() => listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30))); - await Assert.ThrowsAsync(() => connectTask3.AsTask().WaitAsync(TimeSpan.FromSeconds(30))); + ValueTask connectTask = CreateQuicConnection(clientOptions); + await Assert.ThrowsAsync(() => listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30))); + await Assert.ThrowsAsync(() => connectTask.AsTask().WaitAsync(TimeSpan.FromSeconds(30))); } } } From ab28064de1925ee218fa1c8dbcc241d42ce46e14 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Wed, 24 May 2023 16:28:44 +0200 Subject: [PATCH 5/9] Change test to theory and add not existing data as alpn --- .../tests/FunctionalTests/QuicListenerTests.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index 33cd658121cf1..204e4c9863caf 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -426,8 +426,10 @@ public async Task Listener_AlpnNarrowingDown_Success() { } [ActiveIssue("https://github.com/dotnet/runtime/issues/86701")] - [Fact] - public async Task Listener_AlpnNarrowingDown_Failure() { + [Theory] + [InlineData("foo")] + [InlineData("not_existing")] + public async Task Listener_AlpnNarrowingDown_Failure(string alpn) { var listenerOptions = new QuicListenerOptions() { ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), @@ -454,7 +456,7 @@ public async Task Listener_AlpnNarrowingDown_Failure() { QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(listener.LocalEndPoint); clientOptions.ClientAuthenticationOptions.ApplicationProtocols = new() { - new SslApplicationProtocol("foo"), + new SslApplicationProtocol(alpn), }; ValueTask connectTask = CreateQuicConnection(clientOptions); await Assert.ThrowsAsync(() => listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30))); From b90b87289bcc8d61e31256f129ccf9ffdde82d77 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Thu, 25 May 2023 12:41:18 +0200 Subject: [PATCH 6/9] Review Feedback --- .../FunctionalTests/QuicListenerTests.cs | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index 204e4c9863caf..7a6231f23ec12 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -17,6 +17,7 @@ namespace System.Net.Quic.Tests [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] public sealed class QuicListenerTests : QuicTestBase { + private const int PassingTestTimeout = 30; public QuicListenerTests(ITestOutputHelper output) : base(output) { } [Fact] @@ -374,7 +375,11 @@ await Task.WhenAll( } [Fact] - public async Task Listener_AlpnNarrowingDown_Success() { + public async Task Listener_AlpnNarrowingDown_Success() + { + using CancellationTokenSource testTimeoutCts = new CancellationTokenSource(PassingTestTimeout); + CancellationToken timeoutToken = testTimeoutCts.Token; + var listenerOptions = new QuicListenerOptions() { ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), @@ -406,8 +411,8 @@ public async Task Listener_AlpnNarrowingDown_Success() { new SslApplicationProtocol("bar"), }; ValueTask connectTask1 = CreateQuicConnection(clientOptions1); - await using QuicConnection serverConnection1 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30)); - await using QuicConnection clientConnection1 = await connectTask1.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + await using QuicConnection serverConnection1 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(timeoutToken); + await using QuicConnection clientConnection1 = await connectTask1.AsTask().WaitAsync(timeoutToken); Assert.Equal(new SslApplicationProtocol("bar"), clientConnection1.NegotiatedApplicationProtocol); @@ -419,8 +424,8 @@ public async Task Listener_AlpnNarrowingDown_Success() { new SslApplicationProtocol("test"), }; ValueTask connectTask2 = CreateQuicConnection(clientOptions2); - await using QuicConnection serverConnection2 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30)); - await using QuicConnection clientConnection2 = await connectTask2.AsTask().WaitAsync(TimeSpan.FromSeconds(30)); + await using QuicConnection serverConnection2 = await listener.AcceptConnectionAsync().AsTask().WaitAsync(timeoutToken); + await using QuicConnection clientConnection2 = await connectTask2.AsTask().WaitAsync(timeoutToken); Assert.Equal(new SslApplicationProtocol("test"), clientConnection2.NegotiatedApplicationProtocol); } @@ -429,7 +434,11 @@ public async Task Listener_AlpnNarrowingDown_Success() { [Theory] [InlineData("foo")] [InlineData("not_existing")] - public async Task Listener_AlpnNarrowingDown_Failure(string alpn) { + public async Task Listener_AlpnNarrowingDown_Failure(string alpn) + { + using CancellationTokenSource testTimeoutCts = new CancellationTokenSource(PassingTestTimeout); + CancellationToken timeoutToken = testTimeoutCts.Token; + var listenerOptions = new QuicListenerOptions() { ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), @@ -459,8 +468,8 @@ public async Task Listener_AlpnNarrowingDown_Failure(string alpn) { new SslApplicationProtocol(alpn), }; ValueTask connectTask = CreateQuicConnection(clientOptions); - await Assert.ThrowsAsync(() => listener.AcceptConnectionAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(30))); - await Assert.ThrowsAsync(() => connectTask.AsTask().WaitAsync(TimeSpan.FromSeconds(30))); + await Assert.ThrowsAsync(() => listener.AcceptConnectionAsync().AsTask().WaitAsync(timeoutToken)); + await Assert.ThrowsAsync(() => connectTask.AsTask().WaitAsync(timeoutToken)); } } } From ac8199a9f2c70395ec2439e8c470c630f5d26db4 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Thu, 25 May 2023 13:44:06 +0200 Subject: [PATCH 7/9] fix compilation --- .../System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index 7a6231f23ec12..abdb2649a3e30 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -17,7 +17,6 @@ namespace System.Net.Quic.Tests [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] public sealed class QuicListenerTests : QuicTestBase { - private const int PassingTestTimeout = 30; public QuicListenerTests(ITestOutputHelper output) : base(output) { } [Fact] From 87e7c7af62935ccf87d6437828e65dbe7a00f601 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Wed, 21 Jun 2023 22:53:18 +0300 Subject: [PATCH 8/9] Delete ActiveIssue attribute --- .../System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index abdb2649a3e30..7f35b32a4ea75 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -429,7 +429,6 @@ public async Task Listener_AlpnNarrowingDown_Success() Assert.Equal(new SslApplicationProtocol("test"), clientConnection2.NegotiatedApplicationProtocol); } - [ActiveIssue("https://github.com/dotnet/runtime/issues/86701")] [Theory] [InlineData("foo")] [InlineData("not_existing")] From cbcd94981976a80ddc43060d6cfdbd6c9845df12 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Thu, 22 Jun 2023 00:14:54 +0300 Subject: [PATCH 9/9] Put ActiveIssue back --- .../System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index 7f35b32a4ea75..abdb2649a3e30 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -429,6 +429,7 @@ public async Task Listener_AlpnNarrowingDown_Success() Assert.Equal(new SslApplicationProtocol("test"), clientConnection2.NegotiatedApplicationProtocol); } + [ActiveIssue("https://github.com/dotnet/runtime/issues/86701")] [Theory] [InlineData("foo")] [InlineData("not_existing")]