From 4d8231a556154aa9bc761eb3f44e1990131789f8 Mon Sep 17 00:00:00 2001 From: Rafael Sliveira Cordeiro Date: Mon, 31 Jul 2023 09:53:34 -0700 Subject: [PATCH] Adds `NullOrOutOfRange` clauses, adding support for nullable classes/structs to `OutOfRange` (#143) --- .../GuardAgainstOutOfRangeExtensions.cs | 114 +++++++++++++++++- .../GuardAgainstNullOrInvalidInput.cs | 12 +- ...instNullOrOutOfRangeForClassIComparable.cs | 83 +++++++++++++ .../GuardAgainstNullOrOutOfRangeForInt.cs | 58 +++++++++ ...rdAgainstNullOrOutOfRangeForNullableInt.cs | 53 ++++++++ .../GuardAgainstNullOrOutOfSQLDateRange.cs | 104 ++++++++++++++++ .../GuardAgainstOutOfRangeForDateTime.cs | 14 ++- .../GuardAgainstOutOfRangeForDecimal.cs | 12 +- .../GuardAgainstOutOfRangeForDouble.cs | 13 +- .../GuardAgainstOutOfRangeForFloat.cs | 13 +- .../GuardAgainstOutOfRangeForInt.cs | 12 +- .../GuardAgainstOutOfRangeForShort.cs | 14 ++- ...dAgainstOutOfRangeForStructIComparable.cs} | 17 ++- .../GuardAgainstOutOfRangeForTimeSpan.cs | 34 +++++- .../GuardAgainstOutOfRangeForUint.cs | 13 +- .../GuardAgainstOutOfSQLDateRange.cs | 49 +++++--- 16 files changed, 558 insertions(+), 57 deletions(-) create mode 100644 test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForClassIComparable.cs create mode 100644 test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForInt.cs create mode 100644 test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForNullableInt.cs create mode 100644 test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfSQLDateRange.cs rename test/GuardClauses.UnitTests/{GuardAgainstOutOfRangeForIComparable.cs => GuardAgainstOutOfRangeForStructIComparable.cs} (88%) diff --git a/src/GuardClauses/GuardAgainstOutOfRangeExtensions.cs b/src/GuardClauses/GuardAgainstOutOfRangeExtensions.cs index 8dec680a..27bdc359 100644 --- a/src/GuardClauses/GuardAgainstOutOfRangeExtensions.cs +++ b/src/GuardClauses/GuardAgainstOutOfRangeExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace Ardalis.GuardClauses; @@ -88,7 +89,11 @@ public static T EnumOutOfRange(this IGuardClause guardClause, /// if any item is not out of range. /// /// - public static IEnumerable OutOfRange(this IGuardClause guardClause, IEnumerable input, string parameterName, T rangeFrom, T rangeTo, string? message = null) where T : IComparable, IComparable + public static IEnumerable OutOfRange(this IGuardClause guardClause, + IEnumerable input, + string parameterName, + T rangeFrom, T rangeTo, + string? message = null) where T : IComparable, IComparable { if (rangeFrom.CompareTo(rangeTo) > 0) { @@ -106,6 +111,34 @@ public static IEnumerable OutOfRange(this IGuardClause guardClause, IEnume return input; } + + /// + /// Throws an if is null. + /// Throws an if is not in the range of valid SqlDateTime values. + /// + /// + /// + /// + /// Optional. Custom error message + /// if the value is in the range of valid SqlDateTime values. + /// + /// +#if NETSTANDARD || NETFRAMEWORK + public static DateTime NullOrOutOfSQLDateRange(this IGuardClause guardClause, + [NotNull][ValidatedNotNull] DateTime? input, + string parameterName, + string? message = null) +#else + public static DateTime NullOrOutOfSQLDateRange(this IGuardClause guardClause, + [NotNull][ValidatedNotNull] DateTime? input, + [CallerArgumentExpression("input")] string parameterName = null, + string? message = null) +#endif + { + guardClause.Null(input, nameof(input)); + return OutOfSQLDateRange(guardClause, input.Value, parameterName, message); + } + /// /// Throws an if is not in the range of valid SqlDateTime values. /// @@ -131,7 +164,7 @@ public static DateTime OutOfSQLDateRange(this IGuardClause guardClause, const long sqlMinDateTicks = 552877920000000000; const long sqlMaxDateTicks = 3155378975999970000; - return OutOfRange(guardClause, input, parameterName!, new DateTime(sqlMinDateTicks), new DateTime(sqlMaxDateTicks), message); + return NullOrOutOfRangeInternal(guardClause, input, parameterName, new DateTime(sqlMinDateTicks), new DateTime(sqlMaxDateTicks), message); } /// @@ -145,12 +178,82 @@ public static DateTime OutOfSQLDateRange(this IGuardClause guardClause, /// Optional. Custom error message /// if the value is not out of range. /// - public static T OutOfRange(this IGuardClause guardClause, T input, + public static T OutOfRange(this IGuardClause guardClause, + T input, string parameterName, - T rangeFrom, - T rangeTo, + [NotNull][ValidatedNotNull] T rangeFrom, + [NotNull][ValidatedNotNull] T rangeTo, string? message = null) where T : IComparable, IComparable { + return NullOrOutOfRangeInternal(guardClause, input, parameterName, rangeFrom, rangeTo, message); + } + + + /// + /// Throws an if is null. + /// Throws an if is less than or greater than . + /// + /// + /// + /// + /// + /// + /// Optional. Custom error message + /// if the value is not not null or out of range. + /// + /// + /// + public static T NullOrOutOfRange(this IGuardClause guardClause, + [NotNull][ValidatedNotNull] T? input, + string parameterName, + [NotNull][ValidatedNotNull] T rangeFrom, + [NotNull][ValidatedNotNull] T rangeTo, + string? message = null) where T : IComparable + { + guardClause.Null(input, nameof(input)); + return NullOrOutOfRangeInternal(guardClause, input, parameterName, rangeFrom, rangeTo, message); + } + + /// + /// Throws an if is null. + /// Throws an if is less than or greater than . + /// + /// + /// + /// + /// + /// + /// Optional. Custom error message + /// if the value is not not null or out of range. + /// + /// + /// + public static T NullOrOutOfRange(this IGuardClause guardClause, + [NotNull][ValidatedNotNull] T? input, + string parameterName, + [NotNull][ValidatedNotNull] T rangeFrom, + [NotNull][ValidatedNotNull] T rangeTo, + string? message = null) where T : struct, IComparable + { + guardClause.Null(input, nameof(input)); + return NullOrOutOfRangeInternal(guardClause, input.Value, parameterName, rangeFrom, rangeTo, message); + } + + /// + /// + /// + private static T NullOrOutOfRangeInternal(this IGuardClause guardClause, + [NotNull][ValidatedNotNull] T? input, + string? parameterName, + [NotNull][ValidatedNotNull] T? rangeFrom, + [NotNull][ValidatedNotNull] T? rangeTo, + string? message = null) where T : IComparable? + { + Guard.Against.Null(input, nameof(input)); + Guard.Against.Null(parameterName, nameof(parameterName)); + Guard.Against.Null(rangeFrom, nameof(rangeFrom)); + Guard.Against.Null(rangeTo, nameof(rangeTo)); + if (rangeFrom.CompareTo(rangeTo) > 0) { throw new ArgumentException(message ?? $"{nameof(rangeFrom)} should be less or equal than {nameof(rangeTo)}", parameterName); @@ -167,5 +270,4 @@ public static T OutOfRange(this IGuardClause guardClause, T input, return input; } - } diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrInvalidInput.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrInvalidInput.cs index fe0b2457..bd209b8d 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstNullOrInvalidInput.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrInvalidInput.cs @@ -71,14 +71,14 @@ public IEnumerator GetEnumerator() IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } - public class ArgumentNullExceptionClassData : IEnumerable - { - public IEnumerator GetEnumerator() + public class ArgumentNullExceptionClassData : IEnumerable { - yield return new object[] { null!, (Func)(x => x.Length > 10) }; + public IEnumerator GetEnumerator() + { + yield return new object?[] { null, (Func)(x => x.Length > 10) }; + } + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } public class ArgumentExceptionClassData : IEnumerable { diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForClassIComparable.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForClassIComparable.cs new file mode 100644 index 00000000..855e97f2 --- /dev/null +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForClassIComparable.cs @@ -0,0 +1,83 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Ardalis.GuardClauses; +using Xunit; + +namespace GuardClauses.UnitTests +{ + /// + /// Every type that implements IComparable and IComparable can use OutOfRange. + /// Here for example tuples are used. + /// + public class GuardAgainstNullOrOutOfRangeForClassIComparable + { + private class TestObj : IComparable, IEquatable + { + private readonly int _internalValue; + + public TestObj(int internalValue) + { + _internalValue = internalValue; + } + + public int CompareTo([AllowNull] TestObj? other) => _internalValue.CompareTo(other?._internalValue); + + + public override bool Equals(object? obj) + { + if (obj is null) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != typeof(TestObj)) return false; + return Equals((TestObj)obj); + } + public bool Equals([AllowNull] TestObj? other) => ReferenceEquals(this, other) || _internalValue == other?._internalValue; + + public override int GetHashCode() => _internalValue.GetHashCode(); + } + + [Fact] + public void DoesNothingGivenInRangeValue() + { + Guard.Against.NullOrOutOfRange(new TestObj(1), "index", new TestObj(1), new TestObj(1)); + Guard.Against.NullOrOutOfRange(new TestObj(2), "index", new TestObj(1), new TestObj(3)); + Guard.Against.NullOrOutOfRange(new TestObj(3), "index", new TestObj(1), new TestObj(3)); + } + + [Fact] + public void ThrowsGivenOutOfRangeValue() + { + Assert.Throws(() => Guard.Against.NullOrOutOfRange(new TestObj(-1), "index", new TestObj(1), new TestObj(3))); + Assert.Throws(() => Guard.Against.NullOrOutOfRange(new TestObj(0), "index", new TestObj(1), new TestObj(3))); + Assert.Throws(() => Guard.Against.NullOrOutOfRange(new TestObj(4), "index", new TestObj(1), new TestObj(3))); + } + + [Fact] + public void ThrowsGivenInvalidArgumentValue() + { + Assert.Throws(() => Guard.Against.NullOrOutOfRange(new TestObj(-1), "index", new TestObj(3), new TestObj(1))); + Assert.Throws(() => Guard.Against.NullOrOutOfRange(new TestObj(0), "index", new TestObj(3), new TestObj(1))); + Assert.Throws(() => Guard.Against.NullOrOutOfRange(new TestObj(4), "index", new TestObj(3), new TestObj(1))); + } + + [Fact] + public void ThrowsGivenInvalidNullArgumentValue() + { +#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type. + + Assert.Throws(() => Guard.Against.NullOrOutOfRange(null, "index", new TestObj(3), new TestObj(1))); + Assert.Throws(() => Guard.Against.NullOrOutOfRange(new TestObj(0), "index", null, new TestObj(1))); + Assert.Throws(() => Guard.Against.NullOrOutOfRange(new TestObj(4), "index", new TestObj(3), null)); + +#pragma warning restore CS8631 + } + + [Fact] + public void ReturnsExpectedValueGivenInRangeValue() + { + Assert.Equal(new TestObj(1), Guard.Against.NullOrOutOfRange(new TestObj(1), "index", new TestObj(1), new TestObj(1))); + Assert.Equal(new TestObj(1), Guard.Against.NullOrOutOfRange(new TestObj(1), "index", new TestObj(1), new TestObj(3))); + Assert.Equal(new TestObj(2), Guard.Against.NullOrOutOfRange(new TestObj(2), "index", new TestObj(1), new TestObj(3))); + Assert.Equal(new TestObj(3), Guard.Against.NullOrOutOfRange(new TestObj(3), "index", new TestObj(1), new TestObj(3))); + } + } +} diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForInt.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForInt.cs new file mode 100644 index 00000000..9b8c9ff3 --- /dev/null +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForInt.cs @@ -0,0 +1,58 @@ +using Ardalis.GuardClauses; +using System; +using Xunit; + +namespace GuardClauses.UnitTests +{ + public class GuardAgainstNullOrOutOfRangeForInt + { + [Theory] + [InlineData(1, 1, 1)] + [InlineData(1, 1, 3)] + [InlineData(2, 1, 3)] + [InlineData(3, 1, 3)] + public void DoesNothingGivenInRangeValue(int input, int rangeFrom, int rangeTo) + { + Guard.Against.NullOrOutOfRange(input, "index", rangeFrom, rangeTo); + } + + [Theory] + [InlineData(-1, 1, 3)] + [InlineData(0, 1, 3)] + [InlineData(4, 1, 3)] + public void ThrowsGivenOutOfRangeValue(int input, int rangeFrom, int rangeTo) + { + Assert.Throws(() => Guard.Against.NullOrOutOfRange(input, "index", rangeFrom, rangeTo)); + } + + [Theory] + [InlineData(-1, 3, 1)] + [InlineData(0, 3, 1)] + [InlineData(4, 3, 1)] + public void ThrowsGivenInvalidArgumentValue(int input, int rangeFrom, int rangeTo) + { + Assert.Throws(() => Guard.Against.NullOrOutOfRange(input, "index", rangeFrom, rangeTo)); + } + + [Theory] + [InlineData(1, 1, 1, 1)] + [InlineData(1, 1, 3, 1)] + [InlineData(2, 1, 3, 2)] + [InlineData(3, 1, 3, 3)] + public void ReturnsExpectedValueGivenInRangeValue(int input, int rangeFrom, int rangeTo, int expected) + { + Assert.Equal(expected, Guard.Against.NullOrOutOfRange(input, "index", rangeFrom, rangeTo)); + } + + [Theory] + [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] + [InlineData("Int range", "Int range (Parameter 'parameterName')")] + public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) + { + var exception = Assert.Throws(() => Guard.Against.NullOrOutOfRange(3, "parameterName", 0, 1, customMessage)); + Assert.NotNull(exception); + Assert.NotNull(exception.Message); + Assert.Equal(expectedMessage, exception.Message); + } + } +} diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForNullableInt.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForNullableInt.cs new file mode 100644 index 00000000..d8ef2f2b --- /dev/null +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfRangeForNullableInt.cs @@ -0,0 +1,53 @@ +using Ardalis.GuardClauses; +using System; +using Xunit; + +namespace GuardClauses.UnitTests +{ + public class GuardAgainstNullOrOutOfRangeForNullableInt + { + [Theory] + [InlineData(1, 1, 1)] + [InlineData(1, 1, 3)] + [InlineData(2, 1, 3)] + [InlineData(3, 1, 3)] + public void DoesNothingGivenInRangeValue(int? input, int rangeFrom, int rangeTo) + { + Guard.Against.NullOrOutOfRange(input, "index", rangeFrom, rangeTo); + } + + [Theory] + [InlineData(-1, 1, 3)] + [InlineData(0, 1, 3)] + [InlineData(4, 1, 3)] + public void ThrowsGivenOutOfRangeValue(int? input, int rangeFrom, int rangeTo) + { + Assert.Throws(() => Guard.Against.NullOrOutOfRange(input, "index", rangeFrom, rangeTo)); + } + + [Theory] + [InlineData(-1, 3, 1)] + [InlineData(0, 3, 1)] + [InlineData(4, 3, 1)] + public void ThrowsGivenInvalidArgumentValue(int? input, int rangeFrom, int rangeTo) + { + Assert.Throws(() => Guard.Against.NullOrOutOfRange(input, "index", rangeFrom, rangeTo)); + } + + [Theory] + [InlineData(1, 1, 1, 1)] + [InlineData(1, 1, 3, 1)] + [InlineData(2, 1, 3, 2)] + [InlineData(3, 1, 3, 3)] + public void ReturnsExpectedValueGivenInRangeValue(int? input, int rangeFrom, int rangeTo, int expected) + { + Assert.Equal(expected, Guard.Against.NullOrOutOfRange(input, "index", rangeFrom, rangeTo)); + } + + [Fact] + public void ThrowsGivenInvalidNullArgumentValue() + { + Assert.Throws(() => Guard.Against.NullOrOutOfRange(null, "index", -10, 10)); + } + } +} diff --git a/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfSQLDateRange.cs b/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfSQLDateRange.cs new file mode 100644 index 00000000..47f131ba --- /dev/null +++ b/test/GuardClauses.UnitTests/GuardAgainstNullOrOutOfSQLDateRange.cs @@ -0,0 +1,104 @@ +using Ardalis.GuardClauses; +using System; +using System.Collections.Generic; +using System.Data.SqlTypes; +using Xunit; + +namespace GuardClauses.UnitTests +{ + public class GuardAgainstNullOrOutOfSQLDateRange + { + [Theory] + [InlineData(1)] + [InlineData(60)] + [InlineData(60 * 60)] + [InlineData(60 * 60 * 24)] + [InlineData(60 * 60 * 24 * 30)] + [InlineData(60 * 60 * 24 * 30 * 365)] + public void ThrowsGivenValueBelowMinDate(int offsetInSeconds) + { + DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-offsetInSeconds); + + Assert.Throws(() => Guard.Against.NullOrOutOfSQLDateRange(date, nameof(date))); + } + + [Fact] + public void DoNothingGivenCurrentDate() + { + Guard.Against.NullOrOutOfSQLDateRange(DateTime.Today, "Today"); + Guard.Against.NullOrOutOfSQLDateRange(DateTime.Now, "Now"); + Guard.Against.NullOrOutOfSQLDateRange(DateTime.UtcNow, "UTC Now"); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(60)] + [InlineData(60 * 60)] + [InlineData(60 * 60 * 24)] + [InlineData(60 * 60 * 24 * 30)] + [InlineData(60 * 60 * 24 * 30 * 365)] + public void DoNothingGivenSqlMinValue(int offsetInSeconds) + { + DateTime date = SqlDateTime.MinValue.Value.AddSeconds(offsetInSeconds); + + Guard.Against.NullOrOutOfSQLDateRange(date, nameof(date)); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(60)] + [InlineData(60 * 60)] + [InlineData(60 * 60 * 24)] + [InlineData(60 * 60 * 24 * 30)] + [InlineData(60 * 60 * 24 * 30 * 365)] + public void DoNothingGivenSqlMaxValue(int offsetInSeconds) + { + DateTime date = SqlDateTime.MaxValue.Value.AddSeconds(-offsetInSeconds); + + Guard.Against.NullOrOutOfSQLDateRange(date, nameof(date)); + } + + [Theory] + [MemberData(nameof(GetSqlDateTimeTestVectors))] + public void ReturnsExpectedValueWhenGivenValidSqlDateTime(DateTime input, string name, DateTime expected) + { + Assert.Equal(expected, Guard.Against.NullOrOutOfSQLDateRange(input, name)); + } + + [Theory] + [InlineData(null, "Input date was out of range (Parameter 'date')")] + [InlineData("SQLDate range", "SQLDate range (Parameter 'date')")] + public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) + { + DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-1); + var exception = Assert.Throws(() => Guard.Against.NullOrOutOfSQLDateRange(date, nameof(date), customMessage)); + + Assert.NotNull(exception); + Assert.NotNull(exception.Message); + Assert.Equal(expectedMessage, exception.Message); + } + + [Fact] + public void ThrowsGivenInvalidNullArgumentValue() + { + Assert.Throws(() => Guard.Against.NullOrOutOfSQLDateRange(null, "index")); + } + + public static IEnumerable GetSqlDateTimeTestVectors() + { + var now = DateTime.Now; + var utc = DateTime.UtcNow; + var yesterday = DateTime.Now.AddDays(-1); + var min = SqlDateTime.MinValue.Value; + var max = SqlDateTime.MaxValue.Value; + + yield return new object[] {now, "now", now}; + yield return new object[] {utc, "utc", utc}; + yield return new object[] {yesterday, "yesterday", yesterday}; + yield return new object[] {min, "min", min}; + yield return new object[] {max, "max", max}; + } + } +} diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDateTime.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDateTime.cs index fa512617..a0033430 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDateTime.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDateTime.cs @@ -68,8 +68,6 @@ public void ErrorMessageMatchesExpected(string customMessage, string expectedMes } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) @@ -79,4 +77,16 @@ public void ExceptionParamNameMatchesExpected(string expectedParamName, string c Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } + + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var exception = Assert.Throws(() => Guard.Against.OutOfRange(DateTime.Today.AddDays(-1), expectedParamName, + DateTime.Today, DateTime.Today.AddDays(1), customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } } diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDecimal.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDecimal.cs index 66a2a07e..da6a063c 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDecimal.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDecimal.cs @@ -56,8 +56,6 @@ public void ErrorMessageMatchesExpected(string customMessage, string expectedMes } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) @@ -66,4 +64,14 @@ public void ExceptionParamNameMatchesExpected(string expectedParamName, string c Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0, expectedParamName, 0.0, 1.0, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } } diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDouble.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDouble.cs index deaa0cab..3f19798f 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDouble.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDouble.cs @@ -56,8 +56,6 @@ public void ErrorMessageMatchesExpected(string customMessage, string expectedMes } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) @@ -66,4 +64,15 @@ public void ExceptionParamNameMatchesExpected(string expectedParamName, string c Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0d, expectedParamName, 0.0d, 1.0d, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } } + diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForFloat.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForFloat.cs index 438bd07d..1f13a0a1 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForFloat.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForFloat.cs @@ -56,8 +56,6 @@ public void ErrorMessageMatchesExpected(string customMessage, string expectedMes } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) @@ -66,4 +64,15 @@ public void ExceptionParamNameMatchesExpected(string expectedParamName, string c Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0f, expectedParamName, 0.0f, 1.0f, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } } + diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForInt.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForInt.cs index a482c914..401993bd 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForInt.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForInt.cs @@ -56,8 +56,6 @@ public void ErrorMessageMatchesExpected(string customMessage, string expectedMes } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) @@ -66,4 +64,14 @@ public void ExceptionParamNameMatchesExpected(string expectedParamName, string c Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var exception = Assert.Throws(() => Guard.Against.OutOfRange(3, expectedParamName, 0, 1, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } } diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForShort.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForShort.cs index 2e5720d3..e9e81fff 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForShort.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForShort.cs @@ -56,8 +56,6 @@ public void ErrorMessageMatchesExpected(string customMessage, string expectedMes } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) @@ -66,4 +64,14 @@ public void ExceptionParamNameMatchesExpected(string expectedParamName, string c Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } -} + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var exception = Assert.Throws(() => Guard.Against.OutOfRange((short)3, expectedParamName, (short)0, (short)1, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } +} \ No newline at end of file diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForIComparable.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForStructIComparable.cs similarity index 88% rename from test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForIComparable.cs rename to test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForStructIComparable.cs index 36fd0d29..e61ad225 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForIComparable.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForStructIComparable.cs @@ -3,12 +3,11 @@ using Xunit; namespace GuardClauses.UnitTests; - /// /// Every type that implements IComparable and IComparable can use OutOfRange. /// Here for example tuples are used. /// -public class GuardAgainstOutOfRangeForIComparable +public class GuardAgainstOutOfRangeForStructIComparable { [Theory] [InlineData(1, 1, 1, 1, 10, 10)] @@ -62,8 +61,6 @@ public void ErrorMessageMatchesExpected(string customMessage, string expectedMes } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) @@ -72,4 +69,14 @@ public void ExceptionParamNameMatchesExpected(string expectedParamName, string c Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } -} + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var exception = Assert.Throws(() => Guard.Against.OutOfRange((1, 2), expectedParamName, (3, 3), (9, 9), customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } +} \ No newline at end of file diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForTimeSpan.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForTimeSpan.cs index d5e92c8b..b5162ccc 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForTimeSpan.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForTimeSpan.cs @@ -77,8 +77,6 @@ public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) @@ -92,6 +90,20 @@ public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParam Assert.Equal(expectedParamName, exception.ParamName); } + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var inputTimeSpan = TimeSpan.FromSeconds(-1); + var rangeFromTimeSpan = TimeSpan.FromSeconds(3); + var rangeToTimeSpan = TimeSpan.FromSeconds(1); + + var exception = Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, expectedParamName, rangeFromTimeSpan, rangeToTimeSpan, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } + [Theory] [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] @@ -108,8 +120,6 @@ public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) @@ -122,4 +132,18 @@ public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParam Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } -} + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull2(string? expectedParamName, string? customMessage) + { + var inputTimeSpan = TimeSpan.FromSeconds(-1); + var rangeFromTimeSpan = TimeSpan.FromSeconds(0); + var rangeToTimeSpan = TimeSpan.FromSeconds(1); + + var exception = Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, expectedParamName, rangeFromTimeSpan, rangeToTimeSpan, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } +} \ No newline at end of file diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForUint.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForUint.cs index 589983f9..c63a29f6 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForUint.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForUint.cs @@ -55,8 +55,6 @@ public void ErrorMessageMatchesExpected(string customMessage, string expectedMes } [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] [InlineData("SomeParameter", null)] [InlineData("SomeOtherParameter", "Value must be correct")] public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) @@ -65,4 +63,15 @@ public void ExceptionParamNameMatchesExpected(string expectedParamName, string c Assert.NotNull(exception); Assert.Equal(expectedParamName, exception.ParamName); } + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + var exception = Assert.Throws(() => Guard.Against.OutOfRange((uint)3.0d, expectedParamName, (uint)0.0d, (uint)1.0d, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } } + diff --git a/test/GuardClauses.UnitTests/GuardAgainstOutOfSQLDateRange.cs b/test/GuardClauses.UnitTests/GuardAgainstOutOfSQLDateRange.cs index 73e683ae..a5e83084 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstOutOfSQLDateRange.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstOutOfSQLDateRange.cs @@ -93,26 +93,35 @@ public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvided(string cust Assert.Equal(expectedMessage, exception.Message); } - [Theory] - [InlineData(null, null)] - [InlineData(null, "Please provide correct value")] - [InlineData("SomeParameter", null)] - [InlineData("SomeOtherParameter", "Value must be correct")] - public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) - { - DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-1); - var exception = Assert.Throws(() => Guard.Against.OutOfSQLDateRange(date, expectedParamName, customMessage)); - Assert.NotNull(exception); - Assert.Equal(expectedParamName, exception.ParamName); - } - - public static IEnumerable GetSqlDateTimeTestVectors() - { - var now = DateTime.Now; - var utc = DateTime.UtcNow; - var yesterday = DateTime.Now.AddDays(-1); - var min = SqlDateTime.MinValue.Value; - var max = SqlDateTime.MaxValue.Value; + [Theory] + [InlineData("SomeParameter", null)] + [InlineData("SomeOtherParameter", "Value must be correct")] + public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) + { + DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-1); + var exception = Assert.Throws(() => Guard.Against.OutOfSQLDateRange(date, expectedParamName, customMessage)); + Assert.NotNull(exception); + Assert.Equal(expectedParamName, exception.ParamName); + } + + [Theory] + [InlineData(null, null)] + [InlineData(null, "Please provide correct value")] + public void ExceptionParamNameNull(string? expectedParamName, string? customMessage) + { + DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-1); + var exception = Assert.Throws(() => Guard.Against.OutOfSQLDateRange(date, expectedParamName, customMessage)); + Assert.NotNull(exception); + Assert.Equal("parameterName", exception.ParamName); + } + + public static IEnumerable GetSqlDateTimeTestVectors() + { + var now = DateTime.Now; + var utc = DateTime.UtcNow; + var yesterday = DateTime.Now.AddDays(-1); + var min = SqlDateTime.MinValue.Value; + var max = SqlDateTime.MaxValue.Value; yield return new object[] { now, "now", now }; yield return new object[] { utc, "utc", utc };