-
Notifications
You must be signed in to change notification settings - Fork 289
Fix OSConditionAttribute to detect OS via reflection for .NET Framework on Mono #7001
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
Changes from 5 commits
ad58b6d
612208f
573b07c
9ea40f9
70f93bf
7128c0a
9c64263
09af2d3
449e696
c49219a
7f4999d
bf1c2cb
a729167
64512ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,11 @@ | |
| #endif | ||
| #endif | ||
|
|
||
| #if NETFRAMEWORK | ||
| // Cache the detected OS to avoid repeated reflection calls | ||
| private static readonly OperatingSystems? s_detectedOS = DetectCurrentOS(); | ||
|
Check failure on line 26 in src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs
|
||
Evangelink marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| #endif | ||
|
|
||
| private readonly OperatingSystems _operatingSystems; | ||
|
|
||
| /// <summary> | ||
|
|
@@ -50,9 +55,15 @@ | |
| /// Gets a value indicating whether the test method or test class should be ignored. | ||
| /// </summary> | ||
| public override bool IsConditionMet | ||
| #if NET462 | ||
| // On .NET Framework, we are sure we are running on Windows. | ||
| => (_operatingSystems & OperatingSystems.Windows) != 0; | ||
| #if NETFRAMEWORK | ||
Evangelink marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| get | ||
| { | ||
| // If we couldn't detect the OS via reflection, assume Windows | ||
| OperatingSystems currentOS = s_detectedOS ?? OperatingSystems.Windows; | ||
Evangelink marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return (_operatingSystems & currentOS) != 0; | ||
| } | ||
| } | ||
| #else | ||
| { | ||
| get | ||
|
|
@@ -79,6 +90,82 @@ | |
| } | ||
| #endif | ||
|
|
||
| #if NETFRAMEWORK | ||
Evangelink marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| private static OperatingSystems? DetectCurrentOS() | ||
| { | ||
| // RuntimeInformation.IsOSPlatform is available in .NET Framework 4.7.1+. | ||
| // For older .NET Framework versions or environments where the API is not available, | ||
| // we return null to fall back to assuming Windows. | ||
| // This also handles Mono which supports RuntimeInformation API and can run on non-Windows platforms. | ||
| Type? runtimeInformationType = Type.GetType("System.Runtime.InteropServices.RuntimeInformation, System.Runtime.InteropServices.RuntimeInformation") | ||
| ?? Type.GetType("System.Runtime.InteropServices.RuntimeInformation, mscorlib"); | ||
|
|
||
| if (runtimeInformationType is null) | ||
| { | ||
| return null; | ||
Evangelink marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| MethodInfo? isOSPlatformMethod = runtimeInformationType.GetMethod("IsOSPlatform", BindingFlags.Public | BindingFlags.Static); | ||
Evangelink marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if (isOSPlatformMethod is null) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| Type? osPlatformType = Type.GetType("System.Runtime.InteropServices.OSPlatform, System.Runtime.InteropServices.RuntimeInformation") | ||
| ?? Type.GetType("System.Runtime.InteropServices.OSPlatform, mscorlib"); | ||
|
|
||
| if (osPlatformType is null) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| MethodInfo? createMethod = osPlatformType.GetMethod("Create", BindingFlags.Public | BindingFlags.Static); | ||
| if (createMethod is null) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| if (IsOSPlatformViaReflection(isOSPlatformMethod, createMethod, "Windows")) | ||
| { | ||
| return OperatingSystems.Windows; | ||
| } | ||
| else if (IsOSPlatformViaReflection(isOSPlatformMethod, createMethod, "Linux")) | ||
| { | ||
| return OperatingSystems.Linux; | ||
| } | ||
| else if (IsOSPlatformViaReflection(isOSPlatformMethod, createMethod, "OSX")) | ||
| { | ||
| return OperatingSystems.OSX; | ||
| } | ||
| else if (IsOSPlatformViaReflection(isOSPlatformMethod, createMethod, "FreeBSD")) | ||
| { | ||
| return OperatingSystems.FreeBSD; | ||
| } | ||
|
|
||
| return null; | ||
Evangelink marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| private static bool IsOSPlatformViaReflection(MethodInfo isOSPlatformMethod, MethodInfo createMethod, string osName) | ||
| { | ||
| try | ||
| { | ||
| object? osPlatform = createMethod.Invoke(null, new object[] { osName }); | ||
| if (osPlatform is null) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| object? result = isOSPlatformMethod.Invoke(null, new object[] { osPlatform }); | ||
| return result is true; | ||
| } | ||
| catch | ||
| { | ||
| // Reflection invocation failed, treat as OS not matching | ||
| return false; | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| /// <summary> | ||
| /// Gets the group name for this attribute. | ||
| /// </summary> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.