From f5004b6c08d6ee50f9e9f4a9550c09290d52f1a6 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 29 Jan 2026 13:57:20 -0800 Subject: [PATCH 1/6] Fix XUnitWrapperGenerator handling of SkipOnCoreClrAttribute with no runtime test modes Add check to skip tests if all RuntimeTestModes are skipped Fixes https://github.com/dotnet/runtime/issues/105964 --- .../Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 424a04fb39ec63..523134daaceb84 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -961,6 +961,12 @@ private static ImmutableArray DecorateWithSkipOnCoreClrConfiguration( conditions.Add($"!{ConditionClass}.IsGCStressC"); } + if (conditions.Count == 0) + { + // If all configurations are skipped, just skip the test as a whole + return ImmutableArray.Empty; + } + return ImmutableArray.CreateRange(testInfos.Select(t => new ConditionalTest(t, string.Join(" && ", conditions)))); } From bed5c1d8ffd6f9b2aef54b86cdc5ede2eb87a587 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 29 Jan 2026 14:27:33 -0800 Subject: [PATCH 2/6] Refactor skipped test handling in XUnitWrapperGenerator Updated skipped test platform and configuration handling to use 'Any' instead of 0 values as the default skip rules (matches the implementation in arcade) --- .../XUnitWrapperGenerator/XUnitWrapperGenerator.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 523134daaceb84..651f67cb1ed4b5 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -847,9 +847,9 @@ private static IEnumerable GetTestMethodInfosForMethod(IMethodSymbol continue; } - Xunit.TestPlatforms skippedTestPlatforms = 0; - Xunit.RuntimeConfiguration skippedConfigurations = 0; - Xunit.RuntimeTestModes skippedTestModes = 0; + Xunit.TestPlatforms skippedTestPlatforms = Xunit.TestPlatforms.Any; + Xunit.RuntimeConfiguration skippedConfigurations = Xunit.RuntimeConfiguration.Any; + Xunit.RuntimeTestModes skippedTestModes = Xunit.RuntimeTestModes.Any; for (int i = 1; i < filterAttribute.ConstructorArguments.Length; i++) { @@ -961,12 +961,6 @@ private static ImmutableArray DecorateWithSkipOnCoreClrConfiguration( conditions.Add($"!{ConditionClass}.IsGCStressC"); } - if (conditions.Count == 0) - { - // If all configurations are skipped, just skip the test as a whole - return ImmutableArray.Empty; - } - return ImmutableArray.CreateRange(testInfos.Select(t => new ConditionalTest(t, string.Join(" && ", conditions)))); } From aa941d12d546d3fada9c1eb8f9c13f0bba9a9590 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 29 Jan 2026 14:50:08 -0800 Subject: [PATCH 3/6] Fix conditions to combine all of the cases. --- .../Common/XUnitWrapperGenerator/ITestInfo.cs | 17 ++++++++++++++++- .../XUnitWrapperGenerator.cs | 16 ++++++---------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs index 2f1237dc44403d..59a064dd0ed795 100644 --- a/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs +++ b/src/tests/Common/XUnitWrapperGenerator/ITestInfo.cs @@ -147,12 +147,17 @@ public ConditionalTest(ITestInfo innerTest, string condition) _innerTest = innerTest; _condition = condition; - } + } public ConditionalTest(ITestInfo innerTest, Xunit.TestPlatforms platform) : this(innerTest, GetPlatformConditionFromTestPlatform(platform)) { } + + public ConditionalTest(ITestInfo innerTest, string condition, Xunit.TestPlatforms platform) + :this(innerTest, $"{(condition.Length == 0 ? "true" : condition)} && ({GetPlatformConditionFromTestPlatform(platform)})") + { + } public string TestNameExpression { get; } public string DisplayNameForFiltering { get; } @@ -207,6 +212,16 @@ private static string GetPlatformConditionFromTestPlatform(Xunit.TestPlatforms p { List platformCheckConditions = new(); + if (platform == Xunit.TestPlatforms.Any) + { + return "false"; + } + + if (platform == 0) + { + return "true"; + } + if (platform.HasFlag(Xunit.TestPlatforms.Windows)) { platformCheckConditions.Add("global::System.OperatingSystem.IsWindows()"); diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 651f67cb1ed4b5..9c9a44e3d03a5f 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -875,12 +875,13 @@ void ReadSkippedInformationFromSkipOnCoreClrAttributeArgument(TypedConstant argu } } - if (skippedTestModes == Xunit.RuntimeTestModes.Any) + if (skippedTestModes == Xunit.RuntimeTestModes.Any + && skippedConfigurations == Xunit.RuntimeConfigurations.Any + && skippedTestPlatforms == Xunit.TestPlatforms.Any) { testInfos = FilterForSkippedRuntime(testInfos, (int)Xunit.TestRuntimes.CoreCLR, options); } - testInfos = DecorateWithSkipOnPlatform(testInfos, (int)skippedTestPlatforms, options); - testInfos = DecorateWithSkipOnCoreClrConfiguration(testInfos, skippedTestModes, skippedConfigurations); + testInfos = DecorateWithSkipOnCoreClrConfiguration(testInfos, skippedTestModes, skippedConfigurations, skippedTestPlatforms, options); break; } @@ -889,15 +890,10 @@ void ReadSkippedInformationFromSkipOnCoreClrAttributeArgument(TypedConstant argu return testInfos; } - private static ImmutableArray DecorateWithSkipOnCoreClrConfiguration(ImmutableArray testInfos, Xunit.RuntimeTestModes skippedTestModes, Xunit.RuntimeConfiguration skippedConfigurations) + private static ImmutableArray DecorateWithSkipOnCoreClrConfiguration(ImmutableArray testInfos, Xunit.RuntimeTestModes skippedTestModes, Xunit.RuntimeConfiguration skippedConfigurations, Xunit.TestPlatforms skippedTestPlatforms) { const string ConditionClass = "TestLibrary.CoreClrConfigurationDetection"; List conditions = new(); - if (skippedConfigurations.HasFlag(Xunit.RuntimeConfiguration.Debug | Xunit.RuntimeConfiguration.Checked | Xunit.RuntimeConfiguration.Release)) - { - // If all configurations are skipped, just skip the test as a whole - return ImmutableArray.Empty; - } if (skippedConfigurations.HasFlag(Xunit.RuntimeConfiguration.Debug)) { @@ -961,7 +957,7 @@ private static ImmutableArray DecorateWithSkipOnCoreClrConfiguration( conditions.Add($"!{ConditionClass}.IsGCStressC"); } - return ImmutableArray.CreateRange(testInfos.Select(t => new ConditionalTest(t, string.Join(" && ", conditions)))); + return ImmutableArray.CreateRange(testInfos.Select(t => new ConditionalTest(t, string.Join(" && ", conditions), ~skippedTestPlatforms))); } private static ImmutableArray FilterForSkippedTargetFrameworkMonikers(ImmutableArray testInfos, int v) From 4bebc7b376cac32479abe1a5bae7800e9ec4cfe9 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 30 Jan 2026 11:59:40 -0800 Subject: [PATCH 4/6] Apply suggestion from @jkoritzinsky --- src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 9c9a44e3d03a5f..f5646ea4cca644 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -876,7 +876,7 @@ void ReadSkippedInformationFromSkipOnCoreClrAttributeArgument(TypedConstant argu } if (skippedTestModes == Xunit.RuntimeTestModes.Any - && skippedConfigurations == Xunit.RuntimeConfigurations.Any + && skippedConfigurations == Xunit.RuntimeConfiguration.Any && skippedTestPlatforms == Xunit.TestPlatforms.Any) { testInfos = FilterForSkippedRuntime(testInfos, (int)Xunit.TestRuntimes.CoreCLR, options); From 92e3cce81fc6ba6c22c77d630ef53a1f1a8e6c3c Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 30 Jan 2026 12:01:33 -0800 Subject: [PATCH 5/6] Fix target platform handling in test generation --- .../XUnitWrapperGenerator.cs | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index f5646ea4cca644..05fd19ef916ded 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -956,8 +956,11 @@ private static ImmutableArray DecorateWithSkipOnCoreClrConfiguration( { conditions.Add($"!{ConditionClass}.IsGCStressC"); } + + options.GlobalOptions.TryGetValue("build_property.TargetOS", out string? targetOS); + Xunit.TestPlatforms targetPlatform = GetPlatformForTargetOS(targetOS); - return ImmutableArray.CreateRange(testInfos.Select(t => new ConditionalTest(t, string.Join(" && ", conditions), ~skippedTestPlatforms))); + return ImmutableArray.CreateRange(testInfos.Select(t => new ConditionalTest(t, string.Join(" && ", conditions), targetPlatform & ~skippedTestPlatforms))); } private static ImmutableArray FilterForSkippedTargetFrameworkMonikers(ImmutableArray testInfos, int v) @@ -1075,28 +1078,28 @@ private static ImmutableArray DecorateWithSkipOnPlatform(ImmutableArr // The target platform is not mentioned in the attribute, just run it as-is. return testInfos; } + } - static Xunit.TestPlatforms GetPlatformForTargetOS(string? targetOS) + private static Xunit.TestPlatforms GetPlatformForTargetOS(string? targetOS) + { + return targetOS?.ToLowerInvariant() switch { - return targetOS?.ToLowerInvariant() switch - { - "windows" => Xunit.TestPlatforms.Windows, - "linux" => Xunit.TestPlatforms.Linux, - "osx" => Xunit.TestPlatforms.OSX, - "illumos" => Xunit.TestPlatforms.illumos, - "solaris" => Xunit.TestPlatforms.Solaris, - "android" => Xunit.TestPlatforms.Android, - "ios" => Xunit.TestPlatforms.iOS, - "tvos" => Xunit.TestPlatforms.tvOS, - "maccatalyst" => Xunit.TestPlatforms.MacCatalyst, - "browser" => Xunit.TestPlatforms.Browser, - "wasi" => Xunit.TestPlatforms.Wasi, - "freebsd" => Xunit.TestPlatforms.FreeBSD, - "netbsd" => Xunit.TestPlatforms.NetBSD, - null or "" or "anyos" => Xunit.TestPlatforms.Any, - _ => 0 - }; - } + "windows" => Xunit.TestPlatforms.Windows, + "linux" => Xunit.TestPlatforms.Linux, + "osx" => Xunit.TestPlatforms.OSX, + "illumos" => Xunit.TestPlatforms.illumos, + "solaris" => Xunit.TestPlatforms.Solaris, + "android" => Xunit.TestPlatforms.Android, + "ios" => Xunit.TestPlatforms.iOS, + "tvos" => Xunit.TestPlatforms.tvOS, + "maccatalyst" => Xunit.TestPlatforms.MacCatalyst, + "browser" => Xunit.TestPlatforms.Browser, + "wasi" => Xunit.TestPlatforms.Wasi, + "freebsd" => Xunit.TestPlatforms.FreeBSD, + "netbsd" => Xunit.TestPlatforms.NetBSD, + null or "" or "anyos" => Xunit.TestPlatforms.Any, + _ => 0 + }; } private static ImmutableArray DecorateWithUserDefinedCondition( From 091dcb76f9d5c4a6c8d3b188417b1e14ab16762b Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 30 Jan 2026 12:02:13 -0800 Subject: [PATCH 6/6] Add options parameter to DecorateWithSkipOnCoreClrConfiguration --- src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs index 05fd19ef916ded..a893e2381d9c3c 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.cs @@ -890,7 +890,7 @@ void ReadSkippedInformationFromSkipOnCoreClrAttributeArgument(TypedConstant argu return testInfos; } - private static ImmutableArray DecorateWithSkipOnCoreClrConfiguration(ImmutableArray testInfos, Xunit.RuntimeTestModes skippedTestModes, Xunit.RuntimeConfiguration skippedConfigurations, Xunit.TestPlatforms skippedTestPlatforms) + private static ImmutableArray DecorateWithSkipOnCoreClrConfiguration(ImmutableArray testInfos, Xunit.RuntimeTestModes skippedTestModes, Xunit.RuntimeConfiguration skippedConfigurations, Xunit.TestPlatforms skippedTestPlatforms, AnalyzerConfigOptionsProvider options) { const string ConditionClass = "TestLibrary.CoreClrConfigurationDetection"; List conditions = new();