From 8e8143ec8754773fb2b34e5165ca92c2fdeb98ac Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Thu, 24 Oct 2024 11:18:13 +0200 Subject: [PATCH] Fix `IsOSVersionAtLeast` when build or revision are not provided (#108748) * Unspecified build/revision components are to be treated as zeros * Normalize build component to 0 if undefined --------- Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> Co-authored-by: Jan Kotas --- .../Environment.OSVersion.MacCatalyst.cs | 10 +++++++ .../src/System/OperatingSystem.cs | 14 +++++++--- .../System/OperatingSystemTests.cs | 28 ++++++++++++++++--- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.MacCatalyst.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.MacCatalyst.cs index 609dddcf5922e6..a5476a2514737b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.MacCatalyst.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.OSVersion.MacCatalyst.cs @@ -8,6 +8,16 @@ public static partial class Environment private static OperatingSystem GetOSVersion() { Version version = new Version(Interop.Sys.iOSSupportVersion()); + + int major = version.Major; + int minor = version.Minor; + // Normalize the build component to 0 if undefined + // to match iOS behavior + int build = version.Build < 0 ? 0 : version.Build; + + // The revision component is always set to -1, + // as it is not specified on MacCatalyst or iOS + version = new Version(major, minor, build); return new OperatingSystem(PlatformID.Unix, version); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs b/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs index e7da2f788fa0de..8dca64953b18e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs +++ b/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs @@ -335,13 +335,19 @@ private static bool IsOSVersionAtLeast(int major, int minor, int build, int revi { return current.Minor > minor; } - if (current.Build != build) + // Unspecified build component is to be treated as zero + int currentBuild = current.Build < 0 ? 0 : current.Build; + build = build < 0 ? 0 : build; + if (currentBuild != build) { - return current.Build > build; + return currentBuild > build; } - return current.Revision >= revision - || (current.Revision == -1 && revision == 0); // it is unavailable on OSX and Environment.OSVersion.Version.Revision returns -1 + // Unspecified revision component is to be treated as zero + int currentRevision = current.Revision < 0 ? 0 : current.Revision; + revision = revision < 0 ? 0 : revision; + + return currentRevision >= revision; } } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/OperatingSystemTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/OperatingSystemTests.cs index 3776ce04478f98..a5a8636008a3cf 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/OperatingSystemTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/OperatingSystemTests.cs @@ -236,11 +236,18 @@ private static void TestIsOSVersionAtLeast(string currentOSName) isCurrentOS = true; } + // Four-parameter overload AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName, major, minor, build, revision)); AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName.ToLower(), major, minor, build, revision)); AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName.ToUpper(), major, minor, build, revision)); + + // Three-parameter overload + AssertVersionChecks(isCurrentOS, (major, minor, build) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName, major, minor, build)); + + // Two-parameter overload + AssertVersionChecks(isCurrentOS, (major, minor) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName, major, minor)); } - + AssertVersionChecks(currentOSName.Equals("Android", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsAndroidVersionAtLeast); AssertVersionChecks(currentOSName == "MacCatalyst" || currentOSName.Equals("iOS", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsIOSVersionAtLeast); AssertVersionChecks(currentOSName.Equals("macOS", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsMacOSVersionAtLeast); @@ -256,8 +263,8 @@ private static void AssertVersionChecks(bool isCurrentOS, Func isOSVersionAtLeast) + { + Version current = Environment.OSVersion.Version; + + Assert.False(isOSVersionAtLeast(current.Major + 1, current.Minor)); + Assert.False(isOSVersionAtLeast(current.Major, current.Minor + 1)); + + Assert.Equal(isCurrentOS, isOSVersionAtLeast(current.Major, current.Minor)); + + Assert.Equal(isCurrentOS, isOSVersionAtLeast(current.Major - 1, current.Minor)); + Assert.Equal(isCurrentOS, isOSVersionAtLeast(current.Major, current.Minor - 1)); + } } }