diff --git a/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs b/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs index 264d7b61d8b9..274e37676014 100644 --- a/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs +++ b/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs @@ -22,6 +22,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task Abort_AbortAfterDispose_Ignored() { // Arrange @@ -46,6 +47,7 @@ public async Task Abort_AbortAfterDispose_Ignored() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task DisposeAsync_DisposeConnectionAfterAcceptingStream_DefaultCloseErrorCodeReported() { // Arrange @@ -74,6 +76,7 @@ public async Task DisposeAsync_DisposeConnectionAfterAcceptingStream_DefaultClos [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_CancellationThenAccept_AcceptStreamAfterCancellation() { // Arrange @@ -113,6 +116,7 @@ public async Task AcceptAsync_CancellationThenAccept_AcceptStreamAfterCancellati [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_ClientClosesConnection_ServerNotified() { // Arrange @@ -145,6 +149,7 @@ public async Task AcceptAsync_ClientClosesConnection_ServerNotified() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_ClientStartsAndStopsUnidirectionStream_ServerAccepts() { // Arrange @@ -187,6 +192,7 @@ public async Task AcceptAsync_ClientStartsAndStopsUnidirectionStream_ServerAccep [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_ClientStartsAndStopsBidirectionStream_ServerAccepts() { // Arrange @@ -237,6 +243,7 @@ public async Task AcceptAsync_ClientStartsAndStopsBidirectionStream_ServerAccept [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_ServerStartsAndStopsUnidirectionStream_ClientAccepts() { // Arrange @@ -282,6 +289,7 @@ public async Task AcceptAsync_ServerStartsAndStopsUnidirectionStream_ClientAccep [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_ClientClosesConnection_ExceptionThrown() { // Arrange @@ -308,6 +316,7 @@ public async Task AcceptAsync_ClientClosesConnection_ExceptionThrown() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task StreamPool_StreamAbortedOnServer_NotPooled() { // Arrange @@ -351,6 +360,7 @@ public async Task StreamPool_StreamAbortedOnServer_NotPooled() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task StreamPool_StreamAbortedOnServerAfterComplete_NotPooled() { // Arrange @@ -396,6 +406,7 @@ public async Task StreamPool_StreamAbortedOnServerAfterComplete_NotPooled() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task StreamPool_StreamAbortedOnClient_NotPooled() { // Arrange @@ -443,6 +454,7 @@ public async Task StreamPool_StreamAbortedOnClient_NotPooled() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task StreamPool_StreamAbortedOnClientAndServer_NotPooled() { // Arrange @@ -500,6 +512,7 @@ public async Task StreamPool_StreamAbortedOnClientAndServer_NotPooled() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task StreamPool_Heartbeat_ExpiredStreamRemoved() { // Arrange @@ -660,6 +673,7 @@ static async Task SendStream(ILogger logger, int streamIndex, RequestState reque [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task PersistentState_StreamsReused_StatePersisted() { using var httpEventSource = new HttpEventSourceListener(LoggerFactory); @@ -741,6 +755,7 @@ public async Task PersistentState_StreamsReused_StatePersisted() [MsQuicSupported] [InlineData(-1L)] // Too small [InlineData(1L << 62)] // Too big + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task IProtocolErrorFeature_InvalidErrorCode(long errorCode) { // Arrange diff --git a/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionListenerTests.cs b/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionListenerTests.cs index cad3310251e8..db6b01ccb396 100644 --- a/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionListenerTests.cs +++ b/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionListenerTests.cs @@ -40,6 +40,7 @@ public async Task AcceptAsync_AfterUnbind_ReturnNull() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_ClientCreatesConnection_ServerAccepts() { // Arrange @@ -64,6 +65,7 @@ public async Task AcceptAsync_ClientCreatesConnection_ServerAccepts() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_ClientCreatesInvalidConnection_ServerContinuesToAccept() { await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); @@ -160,6 +162,7 @@ public async Task ClientCertificate_Required_NotSent_AcceptedViaCallback() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_NoCertificateOrApplicationProtocol_Log() { // Arrange @@ -226,6 +229,7 @@ public async Task AcceptAsync_DisposeAfterCall_CleanExitAndLog() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_ErrorFromServerCallback_CleanExitAndLog() { // Arrange @@ -297,6 +301,7 @@ public async Task BindAsync_ListenersSharePortWithPlainUdpSocket_ThrowAddressInU [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_NoApplicationProtocolsInCallback_DefaultToConnectionProtocols() { // Arrange @@ -328,6 +333,7 @@ public async Task AcceptAsync_NoApplicationProtocolsInCallback_DefaultToConnecti [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_Success_RemovedFromPendingConnections() { // Arrange @@ -371,6 +377,7 @@ public async Task AcceptAsync_Success_RemovedFromPendingConnections() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_NoCertificateCallback_RemovedFromPendingConnections() { // Arrange @@ -424,6 +431,7 @@ public async Task AcceptAsync_NoCertificateCallback_RemovedFromPendingConnection [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task AcceptAsync_TlsCallback_ConnectionContextInArguments() { // Arrange diff --git a/src/Servers/Kestrel/Transport.Quic/test/QuicStreamContextTests.cs b/src/Servers/Kestrel/Transport.Quic/test/QuicStreamContextTests.cs index a3a0c1810406..a000156e03c0 100644 --- a/src/Servers/Kestrel/Transport.Quic/test/QuicStreamContextTests.cs +++ b/src/Servers/Kestrel/Transport.Quic/test/QuicStreamContextTests.cs @@ -53,6 +53,7 @@ public async Task BidirectionalStream_ServerReadsDataAndCompletes_GracefullyClos [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task BidirectionalStream_ReadAborted_NotPooled() { // Arrange @@ -99,6 +100,7 @@ public async Task BidirectionalStream_ReadAborted_NotPooled() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task BidirectionalStream_ClientAbortedAfterDisposeCalled_NotPooled() { // Arrange @@ -161,6 +163,7 @@ public async Task BidirectionalStream_ClientAbortedAfterDisposeCalled_NotPooled( [InlineData(1024)] [InlineData(1024 * 1024)] [InlineData(1024 * 1024 * 5)] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task BidirectionalStream_ServerWritesDataAndDisposes_ClientReadsData(int dataLength) { // Arrange @@ -226,6 +229,7 @@ public async Task BidirectionalStream_ServerWritesDataAndDisposes_ClientReadsDat [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task BidirectionalStream_MultipleStreamsOnConnection_ReusedFromPool() { // Arrange @@ -248,6 +252,7 @@ public async Task BidirectionalStream_MultipleStreamsOnConnection_ReusedFromPool [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task BidirectionalStream_ClientAbortWrite_ServerReceivesAbort() { // Arrange @@ -292,6 +297,7 @@ public async Task BidirectionalStream_ClientAbortWrite_ServerReceivesAbort() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ClientToServerUnidirectionalStream_ServerReadsData_GracefullyClosed() { // Arrange @@ -326,6 +332,7 @@ public async Task ClientToServerUnidirectionalStream_ServerReadsData_GracefullyC [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ClientToServerUnidirectionalStream_ClientAbort_ServerReceivesAbort() { // Arrange @@ -365,6 +372,7 @@ public async Task ClientToServerUnidirectionalStream_ClientAbort_ServerReceivesA [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ClientToServerUnidirectionalStream_CompleteWrites_PipeProvidesDataAndCompleteTogether() { // Arrange @@ -396,6 +404,7 @@ public async Task ClientToServerUnidirectionalStream_CompleteWrites_PipeProvides [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ServerToClientUnidirectionalStream_ServerWritesDataAndCompletes_GracefullyClosed() { // Arrange @@ -437,6 +446,7 @@ public async Task ServerToClientUnidirectionalStream_ServerWritesDataAndComplete [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ServerToClientUnidirectionalStream_ServerAborts_ClientGetsAbort() { // Arrange @@ -481,6 +491,7 @@ public async Task ServerToClientUnidirectionalStream_ServerAborts_ClientGetsAbor [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task StreamAbortFeature_AbortWrite_ClientReceivesAbort() { // Arrange @@ -531,6 +542,7 @@ public async Task StreamAbortFeature_AbortWrite_ClientReceivesAbort() [MsQuicSupported] [InlineData(-1L)] // Too small [InlineData(1L << 62)] // Too big + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task IProtocolErrorFeature_InvalidErrorCode(long errorCode) { // Arrange @@ -558,6 +570,7 @@ public async Task IProtocolErrorFeature_InvalidErrorCode(long errorCode) [MsQuicSupported] [InlineData(-1L)] // Too small [InlineData(1L << 62)] // Too big + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task IStreamAbortFeature_InvalidErrorCode(long errorCode) { // Arrange diff --git a/src/Servers/Kestrel/Transport.Quic/test/WebHostTests.cs b/src/Servers/Kestrel/Transport.Quic/test/WebHostTests.cs index e6c6b9832245..4fa02b3224c8 100644 --- a/src/Servers/Kestrel/Transport.Quic/test/WebHostTests.cs +++ b/src/Servers/Kestrel/Transport.Quic/test/WebHostTests.cs @@ -40,6 +40,7 @@ public void HelixPlatform_QuicListenerIsSupported() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task UseUrls_HelloWorld_ClientSuccess() { // Arrange @@ -97,6 +98,7 @@ public async Task UseUrls_HelloWorld_ClientSuccess() [MsQuicSupported] [InlineData(5002, 5003)] [InlineData(5004, 5004)] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task Listen_Http3AndSocketsCoexistOnDifferentEndpoints_ClientSuccess(int http3Port, int http1Port) { // Arrange @@ -172,6 +174,7 @@ public async Task Listen_Http3AndSocketsOnDynamicEndpoint_Http3Disabled() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task Listen_Http3AndSocketsCoexistOnSameEndpoint_ClientSuccess() { await ServerRetryHelper.BindPortsWithRetry(async port => @@ -210,6 +213,7 @@ await ServerRetryHelper.BindPortsWithRetry(async port => [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task Listen_Http3AndSocketsCoexistOnSameEndpoint_AltSvcEnabled_Upgrade() { await ServerRetryHelper.BindPortsWithRetry(async port => diff --git a/src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3RequestTests.cs b/src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3RequestTests.cs index 8fe339e066d5..94c1b76211db 100644 --- a/src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3RequestTests.cs +++ b/src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3RequestTests.cs @@ -71,6 +71,7 @@ public void CompleteStream() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_Metrics_HttpProtocolAndTlsSet() { // Arrange @@ -119,7 +120,7 @@ public async Task GET_Metrics_HttpProtocolAndTlsSet() // Verify HTTP/2 and HTTP/3 match behavior [ConditionalTheory] [MsQuicSupported] - [InlineData(HttpProtocols.Http3)] + [QuarantinedTestData("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux, HttpProtocols.Http3)] [InlineData(HttpProtocols.Http2)] public async Task GET_MiddlewareIsRunWithConnectionLoggingScopeForHttpRequests(HttpProtocols protocol) { @@ -225,8 +226,8 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except [ConditionalTheory] [MsQuicSupported] - [InlineData(HttpProtocols.Http3, 11)] - [InlineData(HttpProtocols.Http3, 1024)] + [QuarantinedTestData("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux, HttpProtocols.Http3, 11)] + [QuarantinedTestData("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux, HttpProtocols.Http3, 1024)] [InlineData(HttpProtocols.Http2, 11)] [InlineData(HttpProtocols.Http2, 1024)] public async Task GET_ServerStreaming_ClientReadsPartialResponse(HttpProtocols protocol, int clientBufferSize) @@ -271,7 +272,7 @@ public async Task GET_ServerStreaming_ClientReadsPartialResponse(HttpProtocols p [ConditionalTheory] [MsQuicSupported] - [InlineData(HttpProtocols.Http3)] + [QuarantinedTestData("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux, HttpProtocols.Http3)] [InlineData(HttpProtocols.Http2)] public async Task POST_ClientSendsOnlyHeaders_RequestReceivedOnServer(HttpProtocols protocol) { @@ -395,6 +396,7 @@ static async Task SendRequestAsync(HttpProtocols protocol, [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task POST_ServerCompletesWithoutReadingRequestBody_ClientGetsResponse() { // Arrange @@ -528,7 +530,7 @@ public async Task POST_ClientCancellationUpload_RequestAbortRaised(HttpProtocols // Verify HTTP/2 and HTTP/3 match behavior [ConditionalTheory] [MsQuicSupported] - [InlineData(HttpProtocols.Http3)] + [QuarantinedTestData("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux, HttpProtocols.Http3)] [InlineData(HttpProtocols.Http2)] public async Task POST_ServerAbort_ClientReceivesAbort(HttpProtocols protocol) { @@ -593,6 +595,7 @@ public async Task POST_ServerAbort_ClientReceivesAbort(HttpProtocols protocol) [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task POST_ServerAbortAfterWrite_ClientReceivesAbort() { // Arrange @@ -646,7 +649,7 @@ public async Task POST_ServerAbortAfterWrite_ClientReceivesAbort() // Verify HTTP/2 and HTTP/3 match behavior [ConditionalTheory] [MsQuicSupported] - [InlineData(HttpProtocols.Http3)] + [QuarantinedTestData("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux, HttpProtocols.Http3)] [InlineData(HttpProtocols.Http2)] public async Task GET_ServerAbort_ClientReceivesAbort(HttpProtocols protocol) { @@ -701,6 +704,7 @@ public async Task GET_ServerAbort_ClientReceivesAbort(HttpProtocols protocol) [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task POST_Expect100Continue_Get100Continue() { // Arrange @@ -758,6 +762,7 @@ private static Version GetProtocol(HttpProtocols protocol) [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_ConnectionsMakingMultipleRequests_AllSuccess() { // Arrange @@ -822,6 +827,7 @@ static async Task MakeRequest(HttpMessageInvoker client, string address, int cou [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_MultipleRequestsInSequence_ReusedState() { // Arrange @@ -879,6 +885,7 @@ public async Task GET_MultipleRequestsInSequence_ReusedState() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_MultipleRequests_RequestVersionOrHigher_UpgradeToHttp3() { // Arrange @@ -1153,7 +1160,7 @@ internal class MemoryPoolFeature : IMemoryPoolFeature [ConditionalTheory] [MsQuicSupported] - [InlineData(HttpProtocols.Http3)] + [QuarantinedTestData("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux, HttpProtocols.Http3)] [InlineData(HttpProtocols.Http2)] public async Task ApplicationWriteWhenConnectionClosesPreservesMemory(HttpProtocols protocol) { @@ -1280,7 +1287,7 @@ public async Task ApplicationWriteWhenConnectionClosesPreservesMemory(HttpProtoc // Verify HTTP/2 and HTTP/3 match behavior [ConditionalTheory] [MsQuicSupported] - [InlineData(HttpProtocols.Http3)] + [QuarantinedTestData("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux, HttpProtocols.Http3)] [InlineData(HttpProtocols.Http2)] public async Task GET_ClientCancellationAfterResponseHeaders_RequestAbortRaised(HttpProtocols protocol) { @@ -1334,6 +1341,7 @@ public async Task GET_ClientCancellationAfterResponseHeaders_RequestAbortRaised( [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task StreamResponseContent_DelayAndTrailers_ClientSuccess() { // Arrange @@ -1397,6 +1405,7 @@ public async Task StreamResponseContent_DelayAndTrailers_ClientSuccess() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_MultipleRequests_ConnectionAndTraceIdsUpdated() { // Arrange @@ -1450,6 +1459,7 @@ public async Task GET_MultipleRequests_ConnectionAndTraceIdsUpdated() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_MultipleRequestsInSequence_ReusedRequestHeaderStrings() { // Arrange @@ -1512,6 +1522,7 @@ public async Task GET_MultipleRequestsInSequence_ReusedRequestHeaderStrings() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task Get_CompleteAsyncAndReset_StreamNotPooled() { // Arrange @@ -1572,6 +1583,7 @@ public async Task Get_CompleteAsyncAndReset_StreamNotPooled() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_ConnectionLoggingConfigured_OutputToLogs() { // Arrange @@ -1622,6 +1634,7 @@ public async Task GET_ConnectionLoggingConfigured_OutputToLogs() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_UseHttpsCallback_ConnectionContextAvailable() { // Arrange @@ -1674,6 +1687,7 @@ public async Task GET_UseHttpsCallback_ConnectionContextAvailable() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_ClientDisconnected_ConnectionAbortRaised() { // Arrange @@ -1738,6 +1752,7 @@ public async Task GET_ClientDisconnected_ConnectionAbortRaised() [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ConnectionLifetimeNotificationFeature_RequestClose_ConnectionEnds() { // Arrange @@ -1843,6 +1858,7 @@ private HttpRequestMessage CreateHttp3Request(HttpMethod method, string url) [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_ServerAbortTransport_ConnectionAbortRaised() { // Arrange @@ -1930,6 +1946,7 @@ private async Task WaitForLogAsync(Func, bool> testLog [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task GET_ConnectionInfo_PropertiesSet() { string connectionId = null; @@ -2163,6 +2180,7 @@ public async Task GET_GracefulServerShutdown_RequestCompleteSuccessfullyInsideHo [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ServerReset_InvalidErrorCode() { var ranHandler = false; diff --git a/src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3TlsTests.cs b/src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3TlsTests.cs index 78279c042bf7..6ddc8b7f865d 100644 --- a/src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3TlsTests.cs +++ b/src/Servers/Kestrel/test/Interop.FunctionalTests/Http3/Http3TlsTests.cs @@ -75,6 +75,7 @@ public async Task ServerCertificateSelector_Invoked() [MsQuicSupported] [MaximumOSVersion(OperatingSystems.Windows, WindowsVersions.Win10_20H2, SkipReason = "Windows versions newer than 20H2 do not enable TLS 1.1: https://github.com/dotnet/aspnetcore/issues/37761")] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ClientCertificate_AllowOrRequire_Available_Accepted(ClientCertificateMode mode) { var builder = CreateHostBuilder(async context => @@ -117,6 +118,7 @@ public async Task ClientCertificate_AllowOrRequire_Available_Accepted(ClientCert [InlineData(ClientCertificateMode.NoCertificate)] [InlineData(ClientCertificateMode.DelayCertificate)] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ClientCertificate_NoOrDelayed_Available_Ignored(ClientCertificateMode mode) { var builder = CreateHostBuilder(async context => @@ -216,6 +218,7 @@ public async Task ClientCertificate_AllowOrRequire_Available_Invalid_Refused(Cli [ConditionalFact] [MsQuicSupported] + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/69582", OperatingSystems.Linux)] public async Task ClientCertificate_Allow_NotAvailable_Optional() { var builder = CreateHostBuilder(async context => diff --git a/src/Testing/src/xunit/ConditionalTheoryDiscoverer.cs b/src/Testing/src/xunit/ConditionalTheoryDiscoverer.cs index d3d10bdb9da6..8d9488efc8d4 100644 --- a/src/Testing/src/xunit/ConditionalTheoryDiscoverer.cs +++ b/src/Testing/src/xunit/ConditionalTheoryDiscoverer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Xunit.Abstractions; using Xunit.Sdk; @@ -45,6 +46,13 @@ protected override IEnumerable CreateTestCasesForTheory(ITestFra protected override IEnumerable CreateTestCasesForDataRow(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo theoryAttribute, object[] dataRow) { + QuarantinedTestData quarantinedTestData = null; + if (dataRow?.FirstOrDefault() is QuarantinedTestData quarantine) + { + quarantinedTestData = quarantine; + dataRow = dataRow.Skip(1).ToArray(); + } + var skipReason = testMethod.EvaluateSkipConditions(); if (skipReason == null && dataRow?.Length > 0) { @@ -60,9 +68,35 @@ protected override IEnumerable CreateTestCasesForDataRow(ITestFr } } - return skipReason != null ? + var testCases = (skipReason != null ? base.CreateTestCasesForSkippedDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow, skipReason) - : base.CreateTestCasesForDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow); + : base.CreateTestCasesForDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow)).ToArray(); + + if (quarantinedTestData is not null) + { + foreach (var testCase in testCases) + { + AddQuarantinedTrait(testCase.Traits, quarantinedTestData.Attribute); + } + } + + return testCases; + } + + internal static void AddQuarantinedTrait(IDictionary> traits, QuarantinedTestAttribute attribute) + { + if (!QuarantinedTestTraitDiscoverer.IsQuarantined(attribute)) + { + return; + } + + if (!traits.TryGetValue("Quarantined", out var values)) + { + values = new List(); + traits.Add("Quarantined", values); + } + + values.Add("true"); } protected override IEnumerable CreateTestCasesForSkippedDataRow( diff --git a/src/Testing/src/xunit/QuarantinedTestAttribute.cs b/src/Testing/src/xunit/QuarantinedTestAttribute.cs index 8df34d685cb9..f45c08d86eac 100644 --- a/src/Testing/src/xunit/QuarantinedTestAttribute.cs +++ b/src/Testing/src/xunit/QuarantinedTestAttribute.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.InternalTesting; /// /// /// [Fact] -/// [QuarantinedTest("Github Url")] +/// [QuarantinedTest("GitHub URL")] /// public void FlakyTest() /// { /// // Flakiness @@ -44,12 +44,28 @@ public sealed class QuarantinedTestAttribute : Attribute, ITraitAttribute /// public string Reason { get; } + /// + /// Gets the operating systems where the test is quarantined, or when the test is quarantined on all operating systems. + /// + public OperatingSystems? OperatingSystems { get; } + /// /// Initializes a new instance of the class with an optional . /// - /// A reason that this test is quarantined. Preferably a Github issue Url. + /// A reason that this test is quarantined. Preferably a GitHub issue URL. public QuarantinedTestAttribute(string reason) { Reason = reason; } + + /// + /// Initializes a new instance of the class for the specified operating systems. + /// + /// A reason that this test is quarantined. Preferably a GitHub issue URL. + /// The operating systems where the test is quarantined. + public QuarantinedTestAttribute(string reason, OperatingSystems operatingSystems) + { + Reason = reason; + OperatingSystems = operatingSystems; + } } diff --git a/src/Testing/src/xunit/QuarantinedTestDataAttribute.cs b/src/Testing/src/xunit/QuarantinedTestDataAttribute.cs new file mode 100644 index 000000000000..73610945f309 --- /dev/null +++ b/src/Testing/src/xunit/QuarantinedTestDataAttribute.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Reflection; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace Microsoft.AspNetCore.InternalTesting; + +/// +/// Supplies a data row that is quarantined on the specified operating systems. +/// +[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] +public sealed class QuarantinedTestDataAttribute : DataAttribute +{ + private readonly object[] _data; + + /// + /// Initializes a new instance of the class for use with . + /// + /// A reason that this test data row is quarantined. Preferably a GitHub issue URL. + /// The operating systems where the test data row is quarantined. + /// The data values to pass to the theory. + public QuarantinedTestDataAttribute(string reason, OperatingSystems operatingSystems, params object[] data) + { + Reason = reason; + OperatingSystems = operatingSystems; + _data = data; + } + + /// + /// Gets the reason for quarantining the test data row. + /// + public string Reason { get; } + + /// + /// Gets the operating systems where the test data row is quarantined. + /// + public OperatingSystems OperatingSystems { get; } + + /// + public override IEnumerable GetData(MethodInfo testMethod) + { + var data = new object[_data.Length + 1]; + data[0] = new QuarantinedTestData(Reason, OperatingSystems); + Array.Copy(_data, 0, data, 1, _data.Length); + + yield return data; + } +} + +internal sealed class QuarantinedTestData : IXunitSerializable +{ + private string _reason; + private OperatingSystems _operatingSystems; + + public QuarantinedTestData() + { + } + + public QuarantinedTestData(string reason, OperatingSystems operatingSystems) + { + _reason = reason; + _operatingSystems = operatingSystems; + } + + public QuarantinedTestAttribute Attribute => new(_reason, _operatingSystems); + + public void Deserialize(IXunitSerializationInfo info) + { + _reason = info.GetValue(nameof(_reason)); + _operatingSystems = info.GetValue(nameof(_operatingSystems)); + } + + public void Serialize(IXunitSerializationInfo info) + { + info.AddValue(nameof(_reason), _reason); + info.AddValue(nameof(_operatingSystems), _operatingSystems); + } +} diff --git a/src/Testing/src/xunit/QuarantinedTestTraitDiscoverer.cs b/src/Testing/src/xunit/QuarantinedTestTraitDiscoverer.cs index 58f243df3c1a..2130f92eb9e1 100644 --- a/src/Testing/src/xunit/QuarantinedTestTraitDiscoverer.cs +++ b/src/Testing/src/xunit/QuarantinedTestTraitDiscoverer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using Xunit.Abstractions; using Xunit.Sdk; @@ -13,13 +14,45 @@ public class QuarantinedTestTraitDiscoverer : ITraitDiscoverer { public IEnumerable> GetTraits(IAttributeInfo traitAttribute) { - if (traitAttribute is ReflectionAttributeInfo { Attribute: QuarantinedTestAttribute }) + if (traitAttribute is ReflectionAttributeInfo { Attribute: QuarantinedTestAttribute attribute }) { - yield return new KeyValuePair("Quarantined", "true"); + if (IsQuarantined(attribute, GetCurrentOperatingSystem())) + { + yield return new KeyValuePair("Quarantined", "true"); + } } else { throw new InvalidOperationException("The 'QuarantinedTest' attribute is only supported via reflection."); } } + + internal static bool IsQuarantined(QuarantinedTestAttribute attribute, OperatingSystems currentOperatingSystem) + { + return attribute.OperatingSystems is null + || (attribute.OperatingSystems.Value & currentOperatingSystem) == currentOperatingSystem; + } + + internal static bool IsQuarantined(QuarantinedTestAttribute attribute) + { + return IsQuarantined(attribute, GetCurrentOperatingSystem()); + } + + private static OperatingSystems GetCurrentOperatingSystem() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return OperatingSystems.Windows; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return OperatingSystems.Linux; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return OperatingSystems.MacOSX; + } + + throw new PlatformNotSupportedException(); + } } diff --git a/src/Testing/test/ConditionalTheoryTest.cs b/src/Testing/test/ConditionalTheoryTest.cs index 36273ecebc68..d9ce9d509df9 100644 --- a/src/Testing/test/ConditionalTheoryTest.cs +++ b/src/Testing/test/ConditionalTheoryTest.cs @@ -44,6 +44,15 @@ public void ConditionalTheoriesShouldPreserveTraits(int arg) Assert.True(true); } + [ConditionalTheory] + [QuarantinedTestData("No issue, used to verify operating system-specific theory data quarantine", OperatingSystems.Windows, OperatingSystems.Windows)] + [QuarantinedTestData("No issue, used to verify operating system-specific theory data quarantine", OperatingSystems.Linux, OperatingSystems.Linux)] + [QuarantinedTestData("No issue, used to verify operating system-specific theory data quarantine", OperatingSystems.MacOSX, OperatingSystems.MacOSX)] + public void QuarantinedTestData_AppliesTraitToSelectedRow(OperatingSystems operatingSystem) + { + Assert.True(Enum.IsDefined(typeof(OperatingSystems), operatingSystem)); + } + [ConditionalTheory(Skip = "Skip this")] [MemberData(nameof(GetInts))] public void ConditionalTheoriesWithSkippedMemberData(int arg) diff --git a/src/Testing/test/QuarantinedTestAttributeTest.cs b/src/Testing/test/QuarantinedTestAttributeTest.cs index dfbe40083aea..e081cc9bcc25 100644 --- a/src/Testing/test/QuarantinedTestAttributeTest.cs +++ b/src/Testing/test/QuarantinedTestAttributeTest.cs @@ -9,6 +9,51 @@ namespace Microsoft.AspNetCore.InternalTesting.Tests; public class QuarantinedTestAttributeTest { + [Fact] + public void QuarantinedTest_AppliesToAllOperatingSystemsByDefault() + { + Assert.True(QuarantinedTestTraitDiscoverer.IsQuarantined( + new QuarantinedTestAttribute("reason"), + OperatingSystems.Windows)); + } + + [Fact] + public void QuarantinedTest_AppliesToSelectedOperatingSystems() + { + var attribute = new QuarantinedTestAttribute("reason", OperatingSystems.Linux); + + Assert.True(QuarantinedTestTraitDiscoverer.IsQuarantined(attribute, OperatingSystems.Linux)); + Assert.False(QuarantinedTestTraitDiscoverer.IsQuarantined(attribute, OperatingSystems.Windows)); + } + + [Fact] + public void QuarantinedTestData_AddsTraitOnlyOnSelectedOperatingSystems() + { + var traits = new Dictionary>(); + var currentOperatingSystem = TestPlatformHelper.IsWindows + ? OperatingSystems.Windows + : TestPlatformHelper.IsLinux + ? OperatingSystems.Linux + : OperatingSystems.MacOSX; + + ConditionalTheoryDiscoverer.AddQuarantinedTrait( + traits, + new QuarantinedTestAttribute("reason", currentOperatingSystem)); + + Assert.Equal(["true"], traits["Quarantined"]); + + traits.Clear(); + var otherOperatingSystem = currentOperatingSystem == OperatingSystems.Windows + ? OperatingSystems.Linux + : OperatingSystems.Windows; + + ConditionalTheoryDiscoverer.AddQuarantinedTrait( + traits, + new QuarantinedTestAttribute("reason", otherOperatingSystem)); + + Assert.Empty(traits); + } + [Fact(Skip = "These tests are nice when you need them but annoying when on all the time.")] [QuarantinedTest("No issue")] public void AlwaysFlakyInCI()