From 713d3b79a68ed9368ec77190c590776650ca059c Mon Sep 17 00:00:00 2001 From: Adam Reeve Date: Thu, 13 May 2021 20:51:37 +0100 Subject: [PATCH] Add an includePrerelease option for Range.IsSatisfied and related methods (#51) --- README.md | 16 +++++- src/SemanticVersioning/Comparator.cs | 51 +++++++++++------ src/SemanticVersioning/ComparatorSet.cs | 10 ++-- src/SemanticVersioning/Desugarer.cs | 25 +++++---- src/SemanticVersioning/Range.cs | 44 +++++++++------ src/SemanticVersioning/Version.cs | 5 ++ .../AdvancedRanges.cs | 56 ++++++++++++------- .../PreReleaseRanges.cs | 45 +++++++++++++++ test/SemanticVersioning.Tests/RangeEquals.cs | 10 ++-- .../RangeOperations.cs | 2 +- .../StaticRangeMethods.cs | 47 ++++++++++++++++ 11 files changed, 234 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 79b8dc2..a4dd399 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ Examples: Pre-Release Versions -------------------- -Versions with a pre-release can only satisfy ranges that contain +Versions with a pre-release can normally only satisfy ranges that contain a comparator with a pre-release version, and the comparator version's major, minor and patch components must match those of the version being tested. @@ -148,6 +148,20 @@ var range2 = new Range(">=1.2.3"); range2.IsSatisfied("1.2.4-alpha"); // false ``` +To change this behaviour and allow any pre-release version to satisfy a range, +you can set the `includePrerelease` argument to true: + +```C# +var range = new Range(">=1.2.3-beta.2"); +range.IsSatisfied("1.2.4-beta.5", includePrerelease=true); // true + +var range2 = new Range(">=1.2.3"); +range2.IsSatisfied("1.2.4-alpha", includePrerelease=true); // true +``` + +The `Range.Satisfying` and `Range.MaxSatisfying` methods similarly support +an `includePrerelease` argument to allow any pre-release version. + Version Comparisons ------------------- diff --git a/src/SemanticVersioning/Comparator.cs b/src/SemanticVersioning/Comparator.cs index e0c5d8a..d90c282 100644 --- a/src/SemanticVersioning/Comparator.cs +++ b/src/SemanticVersioning/Comparator.cs @@ -58,7 +58,7 @@ public Comparator(string input) } break; case Operator.GreaterThan: - ComparatorType = Operator.GreaterThanOrEqual; + ComparatorType = Operator.GreaterThanOrEqualIncludingPrereleases; if (!partialVersion.Major.HasValue) { // >* is unsatisfiable, so use <0.0.0 @@ -76,9 +76,17 @@ public Comparator(string input) Version = new Version(partialVersion.Major.Value, partialVersion.Minor.Value + 1, 0); } break; + case Operator.LessThan: + // <1.2.x means <1.2.0 but not allowing 1.2.0 prereleases if includePrereleases is used + ComparatorType = Operator.LessThanExcludingPrereleases; + Version = partialVersion.ToZeroVersion(); + break; + case Operator.GreaterThanOrEqual: + // >=1.2.x means >=1.2.0 and includes 1.2.0 prereleases if includePrereleases is used + ComparatorType = Operator.GreaterThanOrEqualIncludingPrereleases; + Version = partialVersion.ToZeroVersion(); + break; default: - // <1.2.x means <1.2.0 - // >=1.2.x means >=1.2.0 Version = partialVersion.ToZeroVersion(); break; } @@ -137,16 +145,20 @@ public bool IsSatisfied(Version version) { switch(ComparatorType) { - case(Operator.Equal): + case Operator.Equal: return version == Version; - case(Operator.LessThan): + case Operator.LessThan: return version < Version; - case(Operator.LessThanOrEqual): + case Operator.LessThanOrEqual: return version <= Version; - case(Operator.GreaterThan): + case Operator.GreaterThan: return version > Version; - case(Operator.GreaterThanOrEqual): + case Operator.GreaterThanOrEqual: return version >= Version; + case Operator.GreaterThanOrEqualIncludingPrereleases: + return version >= Version || (version.IsPreRelease && version.BaseVersion() == Version); + case Operator.LessThanExcludingPrereleases: + return version < Version && !(version.IsPreRelease && version.BaseVersion() == Version); default: throw new InvalidOperationException("Comparator type not recognised."); } @@ -156,12 +168,15 @@ public bool Intersects(Comparator other) { Func operatorIsGreaterThan = c => c.ComparatorType == Operator.GreaterThan || - c.ComparatorType == Operator.GreaterThanOrEqual; + c.ComparatorType == Operator.GreaterThanOrEqual || + c.ComparatorType == Operator.GreaterThanOrEqualIncludingPrereleases; Func operatorIsLessThan = c => c.ComparatorType == Operator.LessThan || - c.ComparatorType == Operator.LessThanOrEqual; + c.ComparatorType == Operator.LessThanOrEqual || + c.ComparatorType == Operator.LessThanExcludingPrereleases; Func operatorIncludesEqual = c => c.ComparatorType == Operator.GreaterThanOrEqual || + c.ComparatorType == Operator.GreaterThanOrEqualIncludingPrereleases || c.ComparatorType == Operator.Equal || c.ComparatorType == Operator.LessThanOrEqual; @@ -188,6 +203,8 @@ public enum Operator LessThanOrEqual, GreaterThan, GreaterThanOrEqual, + GreaterThanOrEqualIncludingPrereleases, + LessThanExcludingPrereleases, } public override string ToString() @@ -195,19 +212,21 @@ public override string ToString() string operatorString = null; switch(ComparatorType) { - case(Operator.Equal): + case Operator.Equal: operatorString = "="; break; - case(Operator.LessThan): + case Operator.LessThan: + case Operator.LessThanExcludingPrereleases: operatorString = "<"; break; - case(Operator.LessThanOrEqual): + case Operator.LessThanOrEqual: operatorString = "<="; break; - case(Operator.GreaterThan): + case Operator.GreaterThan: operatorString = ">"; break; - case(Operator.GreaterThanOrEqual): + case Operator.GreaterThanOrEqual: + case Operator.GreaterThanOrEqualIncludingPrereleases: operatorString = ">="; break; default: @@ -232,7 +251,7 @@ public override bool Equals(object other) public override int GetHashCode() { - return ToString().GetHashCode(); + return new { ComparatorType, Version }.GetHashCode(); } } } diff --git a/src/SemanticVersioning/ComparatorSet.cs b/src/SemanticVersioning/ComparatorSet.cs index dafba5a..ac8ce2f 100644 --- a/src/SemanticVersioning/ComparatorSet.cs +++ b/src/SemanticVersioning/ComparatorSet.cs @@ -64,10 +64,10 @@ private ComparatorSet(IEnumerable comparators) _comparators = comparators.ToList(); } - public bool IsSatisfied(Version version) + public bool IsSatisfied(Version version, bool includePrerelease = false) { bool satisfied = _comparators.All(c => c.IsSatisfied(version)); - if (version.PreRelease != null) + if (version.PreRelease != null && !includePrerelease) { // If the version is a pre-release, then one of the // comparators must have the same version and also include @@ -86,10 +86,12 @@ public ComparatorSet Intersect(ComparatorSet other) { Func operatorIsGreaterThan = c => c.ComparatorType == Comparator.Operator.GreaterThan || - c.ComparatorType == Comparator.Operator.GreaterThanOrEqual; + c.ComparatorType == Comparator.Operator.GreaterThanOrEqual || + c.ComparatorType == Comparator.Operator.GreaterThanOrEqualIncludingPrereleases; Func operatorIsLessThan = c => c.ComparatorType == Comparator.Operator.LessThan || - c.ComparatorType == Comparator.Operator.LessThanOrEqual; + c.ComparatorType == Comparator.Operator.LessThanOrEqual || + c.ComparatorType == Comparator.Operator.LessThanExcludingPrereleases; var maxOfMins = _comparators.Concat(other._comparators) .Where(operatorIsGreaterThan) diff --git a/src/SemanticVersioning/Desugarer.cs b/src/SemanticVersioning/Desugarer.cs index 35d81a2..d7fd43d 100644 --- a/src/SemanticVersioning/Desugarer.cs +++ b/src/SemanticVersioning/Desugarer.cs @@ -41,7 +41,7 @@ public static Tuple TildeRange(string spec) return Tuple.Create( match.Length, - minMaxComparators(minVersion, maxVersion)); + MinMaxComparators(minVersion, maxVersion)); } // Allows changes that do not modify the left-most non-zero digit @@ -95,7 +95,7 @@ public static Tuple CaretRange(string spec) return Tuple.Create( match.Length, - minMaxComparators(minVersion, maxVersion)); + MinMaxComparators(minVersion, maxVersion, minOperator: Comparator.Operator.GreaterThanOrEqualIncludingPrereleases)); } public static Tuple HyphenRange(string spec) @@ -128,7 +128,7 @@ public static Tuple HyphenRange(string spec) var minVersion = minPartialVersion.ToZeroVersion(); Comparator.Operator maxOperator = maxPartialVersion.IsFull() - ? Comparator.Operator.LessThanOrEqual : Comparator.Operator.LessThan; + ? Comparator.Operator.LessThanOrEqual : Comparator.Operator.LessThanExcludingPrereleases; Version maxVersion = null; @@ -153,7 +153,10 @@ public static Tuple HyphenRange(string spec) } return Tuple.Create( match.Length, - minMaxComparators(minVersion, maxVersion, maxOperator)); + MinMaxComparators( + minVersion, maxVersion, + minOperator: Comparator.Operator.GreaterThanOrEqualIncludingPrereleases, + maxOperator: maxOperator)); } public static Tuple StarRange(string spec) @@ -206,23 +209,21 @@ public static Tuple StarRange(string spec) return Tuple.Create( match.Length, - minMaxComparators(minVersion, maxVersion)); + MinMaxComparators(minVersion, maxVersion)); } - private static Comparator[] minMaxComparators(Version minVersion, Version maxVersion, - Comparator.Operator maxOperator=Comparator.Operator.LessThan) + private static Comparator[] MinMaxComparators(Version minVersion, Version maxVersion, + Comparator.Operator minOperator=Comparator.Operator.GreaterThanOrEqual, + Comparator.Operator maxOperator=Comparator.Operator.LessThanExcludingPrereleases) { - var minComparator = new Comparator( - Comparator.Operator.GreaterThanOrEqual, - minVersion); + var minComparator = new Comparator(minOperator, minVersion); if (maxVersion == null) { return new [] { minComparator }; } else { - var maxComparator = new Comparator( - maxOperator, maxVersion); + var maxComparator = new Comparator(maxOperator, maxVersion); return new [] { minComparator, maxComparator }; } } diff --git a/src/SemanticVersioning/Range.cs b/src/SemanticVersioning/Range.cs index ceb9378..6a6f1b4 100644 --- a/src/SemanticVersioning/Range.cs +++ b/src/SemanticVersioning/Range.cs @@ -36,10 +36,11 @@ private Range(IEnumerable comparatorSets) /// Determine whether the given version satisfies this range. /// /// The version to check. + /// When true, allow prerelease versions to satisfy the range. /// true if the range is satisfied by the version. - public bool IsSatisfied(Version version) + public bool IsSatisfied(Version version, bool includePrerelease = false) { - return _comparatorSets.Any(s => s.IsSatisfied(version)); + return _comparatorSets.Any(s => s.IsSatisfied(version, includePrerelease: includePrerelease)); } /// @@ -48,13 +49,14 @@ public bool IsSatisfied(Version version) /// /// The version to check. /// When true, be more forgiving of some invalid version specifications. + /// When true, allow prerelease versions to satisfy the range. /// true if the range is satisfied by the version. - public bool IsSatisfied(string versionString, bool loose = false) + public bool IsSatisfied(string versionString, bool loose = false, bool includePrerelease = false) { try { var version = new Version(versionString, loose); - return IsSatisfied(version); + return IsSatisfied(version, includePrerelease: includePrerelease); } catch (ArgumentException) { @@ -66,10 +68,11 @@ public bool IsSatisfied(string versionString, bool loose = false) /// Return the set of versions that satisfy this range. /// /// The versions to check. + /// When true, allow prerelease versions to satisfy the range. /// An IEnumerable of satisfying versions. - public IEnumerable Satisfying(IEnumerable versions) + public IEnumerable Satisfying(IEnumerable versions, bool includePrerelease = false) { - return versions.Where(IsSatisfied); + return versions.Where(v => IsSatisfied(v, includePrerelease: includePrerelease)); } /// @@ -78,20 +81,22 @@ public IEnumerable Satisfying(IEnumerable versions) /// /// The version strings to check. /// When true, be more forgiving of some invalid version specifications. + /// When true, allow prerelease versions to satisfy the range. /// An IEnumerable of satisfying version strings. - public IEnumerable Satisfying(IEnumerable versions, bool loose = false) + public IEnumerable Satisfying(IEnumerable versions, bool loose = false, bool includePrerelease = false) { - return versions.Where(v => IsSatisfied(v, loose)); + return versions.Where(v => IsSatisfied(v, loose, includePrerelease)); } /// /// Return the maximum version that satisfies this range. /// /// The versions to select from. + /// When true, allow prerelease versions to satisfy the range. /// The maximum satisfying version, or null if no versions satisfied this range. - public Version MaxSatisfying(IEnumerable versions) + public Version MaxSatisfying(IEnumerable versions, bool includePrerelease = false) { - return Satisfying(versions).Max(); + return Satisfying(versions, includePrerelease: includePrerelease).Max(); } /// @@ -99,11 +104,12 @@ public Version MaxSatisfying(IEnumerable versions) /// /// The version strings to select from. /// When true, be more forgiving of some invalid version specifications. + /// When true, allow prerelease versions to satisfy the range. /// The maximum satisfying version string, or null if no versions satisfied this range. - public string MaxSatisfying(IEnumerable versionStrings, bool loose = false) + public string MaxSatisfying(IEnumerable versionStrings, bool loose = false, bool includePrerelease = false) { var versions = ValidVersions(versionStrings, loose); - var maxVersion = MaxSatisfying(versions); + var maxVersion = MaxSatisfying(versions, includePrerelease: includePrerelease); return maxVersion == null ? null : maxVersion.ToString(); } @@ -179,11 +185,12 @@ public override int GetHashCode() /// The range specification. /// The version to check. /// When true, be more forgiving of some invalid version specifications. + /// When true, allow prerelease versions to satisfy the range. /// true if the range is satisfied by the version. - public static bool IsSatisfied(string rangeSpec, string versionString, bool loose = false) + public static bool IsSatisfied(string rangeSpec, string versionString, bool loose = false, bool includePrerelease = false) { var range = new Range(rangeSpec); - return range.IsSatisfied(versionString); + return range.IsSatisfied(versionString, loose: loose, includePrerelease: includePrerelease); } /// @@ -194,10 +201,10 @@ public static bool IsSatisfied(string rangeSpec, string versionString, bool loos /// The version strings to check. /// When true, be more forgiving of some invalid version specifications. /// An IEnumerable of satisfying version strings. - public static IEnumerable Satisfying(string rangeSpec, IEnumerable versions, bool loose = false) + public static IEnumerable Satisfying(string rangeSpec, IEnumerable versions, bool loose = false, bool includePrerelease = false) { var range = new Range(rangeSpec); - return range.Satisfying(versions); + return range.Satisfying(versions, loose: loose, includePrerelease: includePrerelease); } /// @@ -206,11 +213,12 @@ public static IEnumerable Satisfying(string rangeSpec, IEnumerableThe range specification. /// The version strings to select from. /// When true, be more forgiving of some invalid version specifications. + /// When true, allow prerelease versions to satisfy the range. /// The maximum satisfying version string, or null if no versions satisfied this range. - public static string MaxSatisfying(string rangeSpec, IEnumerable versionStrings, bool loose = false) + public static string MaxSatisfying(string rangeSpec, IEnumerable versionStrings, bool loose = false, bool includePrerelease = false) { var range = new Range(rangeSpec); - return range.MaxSatisfying(versionStrings); + return range.MaxSatisfying(versionStrings, includePrerelease: includePrerelease); } /// diff --git a/src/SemanticVersioning/Version.cs b/src/SemanticVersioning/Version.cs index afdc76f..807c1fa 100644 --- a/src/SemanticVersioning/Version.cs +++ b/src/SemanticVersioning/Version.cs @@ -42,6 +42,11 @@ public class Version : IComparable, IComparable, IEquatable /// public string Build { get { return _build; } } + /// + /// Whether this version is a pre-release + /// + public bool IsPreRelease { get { return !string.IsNullOrEmpty(_preRelease); } } + private static Regex strictRegex = new Regex(@"^ \s*v? ([0-9]|[1-9][0-9]+) # major version diff --git a/test/SemanticVersioning.Tests/AdvancedRanges.cs b/test/SemanticVersioning.Tests/AdvancedRanges.cs index e26a0f8..e07db19 100644 --- a/test/SemanticVersioning.Tests/AdvancedRanges.cs +++ b/test/SemanticVersioning.Tests/AdvancedRanges.cs @@ -7,17 +7,18 @@ namespace SemanticVersioning.Tests public class AdvancedRanges { [Theory] - [InlineData("~1.2.3", ">=1.2.3", "<1.3.0")] - [InlineData("~1.2", ">=1.2.0", "<1.3.0")] - [InlineData("~1", ">=1.0.0", "<2.0.0")] - [InlineData("~0.2.3", ">=0.2.3", "<0.3.0")] - [InlineData("~0.2", ">=0.2.0", "<0.3.0")] - [InlineData("~0", ">=0.0.0", "<1.0.0")] + [InlineData("~1.2.3", ">=1.2.3", "1.3.0")] + [InlineData("~1.2", ">=1.2.0", "1.3.0")] + [InlineData("~1", ">=1.0.0", "2.0.0")] + [InlineData("~0.2.3", ">=0.2.3", "0.3.0")] + [InlineData("~0.2", ">=0.2.0", "0.3.0")] + [InlineData("~0", ">=0.0.0", "1.0.0")] public void TestTildeRanges(string range, - string comparatorStringA, string comparatorStringB) + string comparatorStringA, string comparatorVersionB) { var comparatorA = new Comparator(comparatorStringA); - var comparatorB = new Comparator(comparatorStringB); + var comparatorB = new Comparator( + Comparator.Operator.LessThanExcludingPrereleases, Version.Parse(comparatorVersionB)); var comparators = Desugarer.TildeRange(range).Item2; Assert.Equal(comparators.Count(), 2); Assert.Contains(comparatorA, comparators); @@ -25,20 +26,21 @@ public void TestTildeRanges(string range, } [Theory] - [InlineData("^1.2.3", ">=1.2.3", "<2.0.0")] - [InlineData("^0.2.3", ">=0.2.3", "<0.3.0")] - [InlineData("^0.0.3", ">=0.0.3", "<0.0.4")] - [InlineData("^1.2.x", ">=1.2.0", "<2.0.0")] - [InlineData("^0.0.x", ">=0.0.0", "<0.1.0")] - [InlineData("^0.0", ">=0.0.0", "<0.1.0")] - [InlineData("^1.x", ">=1.0.0", "<2.0.0")] - [InlineData("^0.x", ">=0.0.0", "<1.0.0")] - [InlineData("^0.0.0", ">=0.0.0", "<0.0.1")] - public void TestCaretRanges(string range, - string comparatorStringA, string comparatorStringB) + [InlineData("^1.2.3", "1.2.3", "2.0.0")] + [InlineData("^0.2.3", "0.2.3", "0.3.0")] + [InlineData("^0.0.3", "0.0.3", "0.0.4")] + [InlineData("^1.2.x", "1.2.0", "2.0.0")] + [InlineData("^0.0.x", "0.0.0", "0.1.0")] + [InlineData("^0.0", "0.0.0", "0.1.0")] + [InlineData("^1.x", "1.0.0", "2.0.0")] + [InlineData("^0.x", "0.0.0", "1.0.0")] + [InlineData("^0.0.0", "0.0.0", "0.0.1")] + public void TestCaretRanges(string range, string comparatorVersionA, string comparatorVersionB) { - var comparatorA = new Comparator(comparatorStringA); - var comparatorB = new Comparator(comparatorStringB); + var comparatorA = new Comparator( + Comparator.Operator.GreaterThanOrEqualIncludingPrereleases, Version.Parse(comparatorVersionA)); + var comparatorB = new Comparator( + Comparator.Operator.LessThanExcludingPrereleases, Version.Parse(comparatorVersionB)); var comparators = Desugarer.CaretRange(range).Item2; Assert.Equal(comparators.Count(), 2); Assert.Contains(comparatorA, comparators); @@ -61,6 +63,10 @@ public void TestStarRanges(string range, string[] comparatorStrings) foreach (var comparatorString in comparatorStrings) { var comparator = new Comparator(comparatorString); + if (comparator.ComparatorType == Comparator.Operator.LessThan) + { + comparator = new Comparator(Comparator.Operator.LessThanExcludingPrereleases, comparator.Version); + } Assert.Contains(comparator, comparators); } } @@ -79,6 +85,14 @@ public void TestHyphenRanges(string range, string[] comparatorStrings) foreach (var comparatorString in comparatorStrings) { var comparator = new Comparator(comparatorString); + if (comparator.ComparatorType == Comparator.Operator.LessThan) + { + comparator = new Comparator(Comparator.Operator.LessThanExcludingPrereleases, comparator.Version); + } + else if (comparator.ComparatorType == Comparator.Operator.GreaterThanOrEqual) + { + comparator = new Comparator(Comparator.Operator.GreaterThanOrEqualIncludingPrereleases, comparator.Version); + } Assert.Contains(comparator, comparators); } } diff --git a/test/SemanticVersioning.Tests/PreReleaseRanges.cs b/test/SemanticVersioning.Tests/PreReleaseRanges.cs index cf29178..4db4391 100644 --- a/test/SemanticVersioning.Tests/PreReleaseRanges.cs +++ b/test/SemanticVersioning.Tests/PreReleaseRanges.cs @@ -30,6 +30,51 @@ public void ExcludedPreRelease(string rangeString, string versionString) Assert.False(range.IsSatisfied(version)); } + [Theory] + [InlineData(">1.2.3-alpha.3", "1.2.3")] + [InlineData(">1.2.3-alpha.3", "1.2.3-alpha.4")] + [InlineData(">1.2.3-alpha.3", "3.4.5-alpha.1")] + [InlineData("<1.3.0", "1.2.3-alpha.4")] + [InlineData("<1.3.0-alpha.1", "1.2.3-alpha.4")] + [InlineData("<1.3.0-alpha.1", "1.2.3")] + [InlineData("<1.3.0-alpha.3", "1.3.0-alpha.2")] + [InlineData("<=1.3.0-alpha.3", "1.3.0-alpha.3")] + [InlineData("<=1.3.0", "1.3.0-alpha.3")] + [InlineData(">=1.3.0", "1.3.1-alpha.1")] + [InlineData("<1.3.0", "1.3.0-alpha.1")] + [InlineData(">1.3", "1.4.0-alpha.1")] + [InlineData(">=1.3", "1.3.0-alpha.1")] + [InlineData("1.2 - 1.3", "1.2.0-alpha.1")] + [InlineData("1.2 - 1.3", "1.3.0-alpha.1")] + [InlineData("1.2.0 - 1.3.0", "1.2.0-alpha.1")] + [InlineData("1.2.0 - 1.3.0", "1.3.0-alpha.1")] + [InlineData("^0.2.3", "0.2.3-alpha")] + [InlineData("^0.2.3", "0.2.4-alpha")] + public void MatchingPreReleaseWithIncludePrereleases(string rangeString, string versionString) + { + var range = new Range(rangeString); + var version = new Version(versionString); + Assert.True(range.IsSatisfied(version, includePrerelease: true)); + } + + [Theory] + [InlineData("1.2.3", "1.2.3-alpha.3")] + [InlineData("1.2.3-alpha.3", "1.2.3-alpha.7")] + [InlineData("1.2.3-alpha.3", "1.2.3")] + [InlineData(">1.2.3-alpha.3", "1.2.3-alpha.2")] + [InlineData("<1.3.0-alpha.3", "1.3.0-alpha.4")] + [InlineData(">=1.3.0", "1.3.0-alpha.4")] + [InlineData("<1.3", "1.3.0-alpha.1")] + [InlineData("~1.2.3", "1.3.0-alpha.1")] + [InlineData("^0.2.3", "0.2.2-alpha")] + [InlineData("^0.2.3", "0.3.0-alpha")] + public void ExcludedPreReleaseWithIncludePrereleases(string rangeString, string versionString) + { + var range = new Range(rangeString); + var version = new Version(versionString); + Assert.False(range.IsSatisfied(version, includePrerelease: true)); + } + [Theory] [InlineData("~1.2.3-alpha.3", "1.2.3-alpha.7")] [InlineData("~1.2.3-alpha.3", "1.2.5")] diff --git a/test/SemanticVersioning.Tests/RangeEquals.cs b/test/SemanticVersioning.Tests/RangeEquals.cs index 6dbf59b..42a4ca9 100644 --- a/test/SemanticVersioning.Tests/RangeEquals.cs +++ b/test/SemanticVersioning.Tests/RangeEquals.cs @@ -7,8 +7,9 @@ namespace SemanticVersioning.Tests public class RangeEquals { [Theory] - [InlineData("~1.2.3", ">=1.2.3 <1.3.0")] - [InlineData("~1.2.3 || =1.3.2", "=1.3.2 || >=1.2.3 <1.3.0")] + [InlineData(">=1.2.3 <1.3.0", "<1.3.0 >=1.2.3")] + [InlineData("~1.2.3 || =1.3.2", "=1.3.2 || ~1.2.3")] + [InlineData("<=1.2", "<1.3.0")] public void EqualRanges(string a, string b) { var aRange = new Range(a); @@ -33,8 +34,9 @@ public void NotEqualRanges(string a, string b) } [Theory] - [InlineData("~1.2.3", ">=1.2.3 <1.3.0")] - [InlineData("~1.2.3 || =1.3.2", "=1.3.2 || >=1.2.3 <1.3.0")] + [InlineData(">=1.2.3 <1.3.0", "<1.3.0 >=1.2.3")] + [InlineData("~1.2.3 || =1.3.2", "=1.3.2 || ~1.2.3")] + [InlineData("<=1.2", "<1.3.0")] public void EqualHashes(string a, string b) { var aRange = new Range(a); diff --git a/test/SemanticVersioning.Tests/RangeOperations.cs b/test/SemanticVersioning.Tests/RangeOperations.cs index efc00e4..bb83688 100644 --- a/test/SemanticVersioning.Tests/RangeOperations.cs +++ b/test/SemanticVersioning.Tests/RangeOperations.cs @@ -11,7 +11,7 @@ public class RangeOperations [InlineData("~1.2.3", "=1.3.2", "<0.0.0")] [InlineData("=1.2.3", "=1.2.3", "=1.2.3")] [InlineData("=1.2.3", "=1.2.4", "<0.0.0")] - [InlineData("~1.2.3 || ~1.3.2", ">=1.2.9 < 1.3.8", ">=1.2.9 < 1.3.0 || >=1.3.2 < 1.3.8")] + [InlineData("~1.2.3 || ~1.3.2", ">=1.2.9 < 1.3.8", "~1.2.9 || >=1.3.2 < 1.3.8")] [InlineData("<3.0.0", ">=3.0.0", "<0.0.0")] [InlineData("^2", "^3", "<0.0.0")] public void Intersect(string a, string b, string intersect) diff --git a/test/SemanticVersioning.Tests/StaticRangeMethods.cs b/test/SemanticVersioning.Tests/StaticRangeMethods.cs index 8023e9e..0bc5a46 100644 --- a/test/SemanticVersioning.Tests/StaticRangeMethods.cs +++ b/test/SemanticVersioning.Tests/StaticRangeMethods.cs @@ -47,5 +47,52 @@ public void TestIsSatisfied(string range, string version, bool expectedSatisfied var satisfied = Range.IsSatisfied(range, version); Assert.Equal(expectedSatisfied, satisfied); } + + [Fact] + public void TestMaxSatisfyingWithIncludePreRelease() + { + var versions = new [] { + "1.2.7", + "v1.2.8", + "v1.2.98", + "v1.2.99-alpha.1", + "1.2.6", + "v1.3.0", + "v1.1.0", + }; + var max = Range.MaxSatisfying(">=1.2.7 <1.3.0", versions, includePrerelease: true); + Assert.Equal("v1.2.99-alpha.1", max); + } + + [Fact] + public void TestSatisfyingWithIncludePreRelease() + { + var versions = new [] { + "1.2.7", + "v1.2.8-beta.2", + "v1.2.98", + "v1.2.99-alpha.1", + "1.2.6", + "v1.3.0", + "v1.1.0", + }; + var satisfying = Range.Satisfying(">=1.2.7 <1.3.0", versions, includePrerelease: true).ToArray(); + Assert.Equal(4, satisfying.Count()); + Assert.Contains("1.2.7", satisfying); + Assert.Contains("v1.2.98", satisfying); + Assert.Contains("v1.2.8-beta.2", satisfying); + Assert.Contains("v1.2.99-alpha.1", satisfying); + } + + [Theory] + [InlineData("~1.2.3", "1.2.5-alpha", true)] + [InlineData("~1.2.3", "1.3.0-alpha", false)] + [InlineData("^0.2.3", "0.2.5-alpha", true)] + [InlineData("^0.2.3", "0.3.0-alpha", false)] + public void TestIsSatisfiedWithIncludePreRelease(string range, string version, bool expectedSatisfied) + { + var satisfied = Range.IsSatisfied(range, version, includePrerelease: true); + Assert.Equal(expectedSatisfied, satisfied); + } } }