diff --git a/src/Microsoft.DotNet.Build.Tasks.Packaging/src/RuntimeVersion.cs b/src/Microsoft.DotNet.Build.Tasks.Packaging/src/RuntimeVersion.cs index 977ba6800b23..66b444391211 100644 --- a/src/Microsoft.DotNet.Build.Tasks.Packaging/src/RuntimeVersion.cs +++ b/src/Microsoft.DotNet.Build.Tasks.Packaging/src/RuntimeVersion.cs @@ -50,7 +50,12 @@ public int CompareTo(object obj) public int CompareTo(RuntimeVersion other) { - int versionResult = version.CompareTo(other.version); + if (other == null) + { + return 1; + } + + int versionResult = version.CompareTo(other?.version); if (versionResult == 0) { @@ -73,7 +78,8 @@ public int CompareTo(RuntimeVersion other) public bool Equals(RuntimeVersion other) { return object.ReferenceEquals(other, this) || - versionString.Equals(other.versionString, StringComparison.Ordinal); + (other != null && + versionString.Equals(other.versionString, StringComparison.Ordinal)); } public override bool Equals(object obj) diff --git a/src/Microsoft.DotNet.Build.Tasks.Packaging/tests/RidTests.cs b/src/Microsoft.DotNet.Build.Tasks.Packaging/tests/RidTests.cs index cc66ac9f31eb..762309bd79a0 100644 --- a/src/Microsoft.DotNet.Build.Tasks.Packaging/tests/RidTests.cs +++ b/src/Microsoft.DotNet.Build.Tasks.Packaging/tests/RidTests.cs @@ -1,14 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using NuGet.Frameworks; -using NuGet.RuntimeModel; -using System.IO; -using Xunit; -using Xunit.Abstractions; -using FluentAssertions; -using Microsoft.DotNet.Build.Tasks.Packaging; using System.Collections.Generic; +using Xunit; namespace Microsoft.DotNet.Build.Tasks.Packaging.Tests { @@ -21,8 +15,9 @@ public static IEnumerable ValidRIDData() yield return new object[] { "linux", new RID() { BaseRID = "linux" } }; yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" } }; yield return new object[] { "linux-x64", new RID() { BaseRID = "linux", Architecture = "x64" } }; - yield return new object[] { "debian.10-x64", new RID() { BaseRID = "debian", Version = new RuntimeVersion("10"), Architecture = "x64" } }; + yield return new object[] { "debian.10-x64", new RID() { BaseRID = "debian", Version = new RuntimeVersion("10"), Architecture = "x64" } }; yield return new object[] { "linuxmint.19.2-x64", new RID() { BaseRID = "linuxmint", Version = new RuntimeVersion("19.2"), Architecture = "x64" } }; + yield return new object[] { "ubuntu.14.04-x64", new RID() { BaseRID = "ubuntu", Version = new RuntimeVersion("14.04"), Architecture = "x64" } }; yield return new object[] { "foo-bar.42-arm", new RID() { BaseRID = "foo-bar", Version = new RuntimeVersion("42"), Architecture = "arm" } }; yield return new object[] { "foo-bar-arm", new RID() { BaseRID = "foo", Architecture = "bar", Qualifier = "arm" } }; // demonstrates ambiguity, avoid using `-` in base } diff --git a/src/Microsoft.DotNet.Build.Tasks.Packaging/tests/RuntimeVersionTests.cs b/src/Microsoft.DotNet.Build.Tasks.Packaging/tests/RuntimeVersionTests.cs new file mode 100644 index 000000000000..579f14cf0f7a --- /dev/null +++ b/src/Microsoft.DotNet.Build.Tasks.Packaging/tests/RuntimeVersionTests.cs @@ -0,0 +1,233 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Xunit; + +namespace Microsoft.DotNet.Build.Tasks.Packaging.Tests +{ + public class RuntimeVersionTests + { + public enum Comparison + { + LessThan, + Equal, + GreaterThan + } + + public static IEnumerable ComparisonData() + { + yield return new object[] { "0.0", "00.0", Comparison.LessThan }; + yield return new object[] { "2.0", "1.0", Comparison.GreaterThan }; + yield return new object[] { "2", "1.0", Comparison.GreaterThan }; + yield return new object[] { "2", "1", Comparison.GreaterThan }; + yield return new object[] { "10", "10.0", Comparison.LessThan }; + yield return new object[] { "10", "10.00", Comparison.LessThan }; + yield return new object[] { "10.0", "10.0", Comparison.Equal }; + yield return new object[] { "10.0", null, Comparison.GreaterThan }; + yield return new object[] { "8", "8", Comparison.Equal }; + } + + [MemberData(nameof(ComparisonData))] + [Theory] + public static void CompareTo(string vs1, string vs2, Comparison expected) + { + RuntimeVersion v1 = new RuntimeVersion(vs1); + RuntimeVersion v2 = vs2 == null ? null : new RuntimeVersion(vs2); + int actual = v1.CompareTo(v2); + int invActual = v2?.CompareTo(v1) ?? -1; + + switch (expected) + { + case Comparison.LessThan: + Assert.True(actual < 0); + Assert.True(invActual > 0); + break; + case Comparison.Equal: + Assert.Equal(0, actual); + Assert.Equal(0, invActual); + break; + case Comparison.GreaterThan: + Assert.True(actual > 0); + Assert.True(invActual < 0); + break; + } + } + + [MemberData(nameof(ComparisonData))] + [Theory] + public static void GreaterThan(string vs1, string vs2, Comparison expected) + { + RuntimeVersion v1 = new RuntimeVersion(vs1); + RuntimeVersion v2 = vs2 == null ? null : new RuntimeVersion(vs2); + bool actual = v1 > v2; + bool invActual = v2 > v1; + + switch (expected) + { + case Comparison.LessThan: + Assert.False(actual); + Assert.True(invActual); + break; + case Comparison.Equal: + Assert.False(actual); + Assert.False(invActual); + break; + case Comparison.GreaterThan: + Assert.True(actual); + Assert.False(invActual); + break; + } + } + + [MemberData(nameof(ComparisonData))] + [Theory] + public static void GreaterThanOrEqual(string vs1, string vs2, Comparison expected) + { + RuntimeVersion v1 = new RuntimeVersion(vs1); + RuntimeVersion v2 = vs2 == null ? null : new RuntimeVersion(vs2); + bool actual = v1 >= v2; + bool invActual = v2 >= v1; + + switch (expected) + { + case Comparison.LessThan: + Assert.False(actual); + Assert.True(invActual); + break; + case Comparison.Equal: + Assert.True(actual); + Assert.True(invActual); + break; + case Comparison.GreaterThan: + Assert.True(actual); + Assert.False(invActual); + break; + } + } + + [MemberData(nameof(ComparisonData))] + [Theory] + public static void LessThan(string vs1, string vs2, Comparison expected) + { + RuntimeVersion v1 = new RuntimeVersion(vs1); + RuntimeVersion v2 = vs2 == null ? null : new RuntimeVersion(vs2); + bool actual = v1 < v2; + bool invActual = v2 < v1; + + switch (expected) + { + case Comparison.LessThan: + Assert.True(actual); + Assert.False(invActual); + break; + case Comparison.Equal: + Assert.False(actual); + Assert.False(invActual); + break; + case Comparison.GreaterThan: + Assert.False(actual); + Assert.True(invActual); + break; + } + } + + [MemberData(nameof(ComparisonData))] + [Theory] + public static void LessThanOrEqual(string vs1, string vs2, Comparison expected) + { + RuntimeVersion v1 = new RuntimeVersion(vs1); + RuntimeVersion v2 = vs2 == null ? null : new RuntimeVersion(vs2); + bool actual = v1 <= v2; + bool invActual = v2 <= v1; + + switch (expected) + { + case Comparison.LessThan: + Assert.True(actual); + Assert.False(invActual); + break; + case Comparison.Equal: + Assert.True(actual); + Assert.True(invActual); + break; + case Comparison.GreaterThan: + Assert.False(actual); + Assert.True(invActual); + break; + } + } + + [MemberData(nameof(ComparisonData))] + [Theory] + public static void Equal(string vs1, string vs2, Comparison expected) + { + RuntimeVersion v1 = new RuntimeVersion(vs1); + RuntimeVersion v2 = vs2 == null ? null : new RuntimeVersion(vs2); + bool actual = v1 == v2; + bool invActual = v2 == v1; + + switch (expected) + { + case Comparison.LessThan: + Assert.False(actual); + Assert.False(invActual); + break; + case Comparison.Equal: + Assert.True(actual); + Assert.True(invActual); + break; + case Comparison.GreaterThan: + Assert.False(actual); + Assert.False(invActual); + break; + } + } + + [MemberData(nameof(ComparisonData))] + [Theory] + public static void GetHashCodeUnique(string vs1, string vs2, Comparison expected) + { + RuntimeVersion v1 = new RuntimeVersion(vs1); + RuntimeVersion v2 = vs2 == null ? null : new RuntimeVersion(vs2); + int h1 = v1.GetHashCode(); + int h2 = v2?.GetHashCode() ?? 0; + + switch (expected) + { + case Comparison.LessThan: + Assert.NotEqual(h1, h2); + break; + case Comparison.Equal: + Assert.Equal(h1, h2); + break; + case Comparison.GreaterThan: + Assert.NotEqual(h1, h2); + break; + } + } + public static IEnumerable ValidVersions() + { + yield return new object[] { "0" }; + yield return new object[] { "00" }; + yield return new object[] { "000" }; + yield return new object[] { "1" }; + yield return new object[] { "1.0" }; + yield return new object[] { "1.1" }; + yield return new object[] { "1.01" }; + yield return new object[] { "1.2.3.4" }; + yield return new object[] { "1.02.03.04" }; + } + + + [MemberData(nameof(ValidVersions))] + [Theory] + public static void RoundTripToString(string expected) + { + RuntimeVersion version = new RuntimeVersion(expected); + string actual = version.ToString(); + Assert.Equal(expected, actual); + } + + } +}