Skip to content
Merged
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Debug)

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs#L26

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs(26,47): error IDE1006: (NETCORE_ENGINEERING_TELEMETRY=Build) Naming rule violation: Prefix 's_' is not expected (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006)

Check failure on line 26 in src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Debug)

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs#L26

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs(26,47): error SA1311: (NETCORE_ENGINEERING_TELEMETRY=Build) Static readonly fields should begin with upper-case letter (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md)

Check failure on line 26 in src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Release)

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs#L26

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs(26,47): error IDE1006: (NETCORE_ENGINEERING_TELEMETRY=Build) Naming rule violation: Prefix 's_' is not expected (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006)

Check failure on line 26 in src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Linux Release)

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs#L26

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs(26,47): error SA1311: (NETCORE_ENGINEERING_TELEMETRY=Build) Static readonly fields should begin with upper-case letter (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md)

Check failure on line 26 in src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs#L26

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs(26,47): error IDE1006: (NETCORE_ENGINEERING_TELEMETRY=Build) Naming rule violation: Prefix 's_' is not expected (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006)

Check failure on line 26 in src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs#L26

src/TestFramework/TestFramework/Attributes/TestMethod/OSConditionAttribute.cs(26,47): error SA1311: (NETCORE_ENGINEERING_TELEMETRY=Build) Static readonly fields should begin with upper-case letter (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md)
#endif

private readonly OperatingSystems _operatingSystems;

/// <summary>
Expand Down Expand Up @@ -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
{
get
{
// If we couldn't detect the OS via reflection, assume Windows
OperatingSystems currentOS = s_detectedOS ?? OperatingSystems.Windows;
return (_operatingSystems & currentOS) != 0;
}
}
#else
{
get
Expand All @@ -79,6 +90,82 @@
}
#endif

#if NETFRAMEWORK
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;
}

MethodInfo? isOSPlatformMethod = runtimeInformationType.GetMethod("IsOSPlatform", BindingFlags.Public | BindingFlags.Static);
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;
}

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>
Expand Down
Loading