diff --git a/Code/Light.GuardClauses.AllProjects.sln.DotSettings b/Code/Light.GuardClauses.AllProjects.sln.DotSettings
index 5c674a6..2c4519b 100644
--- a/Code/Light.GuardClauses.AllProjects.sln.DotSettings
+++ b/Code/Light.GuardClauses.AllProjects.sln.DotSettings
@@ -249,6 +249,7 @@
True
True
True
+ True
True
True
True
diff --git a/Code/Light.GuardClauses.InternalRoslynAnalyzers.Tests/Light.GuardClauses.InternalRoslynAnalyzers.Tests.csproj b/Code/Light.GuardClauses.InternalRoslynAnalyzers.Tests/Light.GuardClauses.InternalRoslynAnalyzers.Tests.csproj
index 814ef38..c15326f 100644
--- a/Code/Light.GuardClauses.InternalRoslynAnalyzers.Tests/Light.GuardClauses.InternalRoslynAnalyzers.Tests.csproj
+++ b/Code/Light.GuardClauses.InternalRoslynAnalyzers.Tests/Light.GuardClauses.InternalRoslynAnalyzers.Tests.csproj
@@ -1,15 +1,15 @@
- net6.0
+ net8.0
-
-
-
-
+
+
+
+
diff --git a/Code/Light.GuardClauses.InternalRoslynAnalyzers/Light.GuardClauses.InternalRoslynAnalyzers.csproj b/Code/Light.GuardClauses.InternalRoslynAnalyzers/Light.GuardClauses.InternalRoslynAnalyzers.csproj
index 5ce7f44..1df3b66 100644
--- a/Code/Light.GuardClauses.InternalRoslynAnalyzers/Light.GuardClauses.InternalRoslynAnalyzers.csproj
+++ b/Code/Light.GuardClauses.InternalRoslynAnalyzers/Light.GuardClauses.InternalRoslynAnalyzers.csproj
@@ -2,10 +2,11 @@
netstandard2.0
+ true
-
+
\ No newline at end of file
diff --git a/Code/Light.GuardClauses.InternalRoslynAnalyzers/XmlCommentAnalyzer.cs b/Code/Light.GuardClauses.InternalRoslynAnalyzers/XmlCommentAnalyzer.cs
index c96ef39..ec3d601 100644
--- a/Code/Light.GuardClauses.InternalRoslynAnalyzers/XmlCommentAnalyzer.cs
+++ b/Code/Light.GuardClauses.InternalRoslynAnalyzers/XmlCommentAnalyzer.cs
@@ -37,7 +37,7 @@ private static void AnalyzeXmlCommentsForParameterNameAndMessage(SymbolAnalysisC
if (methodSymbol.DeclaringSyntaxReferences.Length != 1 ||
!(methodSymbol.DeclaringSyntaxReferences[0].GetSyntax() is MethodDeclarationSyntax methodDeclarationSyntax) ||
!(methodDeclarationSyntax.DescendantTrivia()
- .SingleOrDefault(trivia => trivia.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia)
+ .SingleOrDefault(trivia => trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia))
.GetStructure() is DocumentationCommentTriviaSyntax documentationSyntax))
return;
diff --git a/Code/Light.GuardClauses.Performance/StringAssertions/MustBeBenchmark.cs b/Code/Light.GuardClauses.Performance/StringAssertions/MustBeBenchmark.cs
index 62310d7..19f51c5 100644
--- a/Code/Light.GuardClauses.Performance/StringAssertions/MustBeBenchmark.cs
+++ b/Code/Light.GuardClauses.Performance/StringAssertions/MustBeBenchmark.cs
@@ -22,6 +22,6 @@ public string ImperativeVersion()
[Benchmark]
public string LightGuardClausesCustomException() =>
- X.MustBe(Y, StringComparisonType.OrdinalIgnoreWhiteSpace, (x, y) => new Exception("The strings are not equal."));
+ X.MustBe(Y, StringComparisonType.OrdinalIgnoreWhiteSpace, (_, _, _) => new Exception("The strings are not equal."));
}
}
\ No newline at end of file
diff --git a/Code/Light.GuardClauses.Performance/StringAssertions/MustNotBeBenchmark.cs b/Code/Light.GuardClauses.Performance/StringAssertions/MustNotBeBenchmark.cs
index 67f3c3c..3b5da46 100644
--- a/Code/Light.GuardClauses.Performance/StringAssertions/MustNotBeBenchmark.cs
+++ b/Code/Light.GuardClauses.Performance/StringAssertions/MustNotBeBenchmark.cs
@@ -25,6 +25,6 @@ public string ImperativeVersion()
[Benchmark]
public string LightGuardClausesCustomException() =>
- X.MustNotBe(Y, StringComparisonType.OrdinalIgnoreCaseIgnoreWhiteSpace, (x, y) => new Exception("The strings are equal."));
+ X.MustNotBe(Y, StringComparisonType.OrdinalIgnoreCaseIgnoreWhiteSpace, (_, _, _) => new Exception("The strings are equal."));
}
}
\ No newline at end of file
diff --git a/Code/Light.GuardClauses.Source/Light.GuardClauses.Source.csproj b/Code/Light.GuardClauses.Source/Light.GuardClauses.Source.csproj
index b30140e..229eeab 100644
--- a/Code/Light.GuardClauses.Source/Light.GuardClauses.Source.csproj
+++ b/Code/Light.GuardClauses.Source/Light.GuardClauses.Source.csproj
@@ -1,8 +1,8 @@
- netstandard2.0
- 10.0
+ netstandard2.0
+ 12.0
Kenny Pflug
Kenny Pflug
Copyright © Kenny Pflug 2016 - 2023
diff --git a/Code/Light.GuardClauses.SourceCodeTransformation.Tests/Light.GuardClauses.SourceCodeTransformation.Tests.csproj b/Code/Light.GuardClauses.SourceCodeTransformation.Tests/Light.GuardClauses.SourceCodeTransformation.Tests.csproj
index 9a4eeec..75dd49f 100644
--- a/Code/Light.GuardClauses.SourceCodeTransformation.Tests/Light.GuardClauses.SourceCodeTransformation.Tests.csproj
+++ b/Code/Light.GuardClauses.SourceCodeTransformation.Tests/Light.GuardClauses.SourceCodeTransformation.Tests.csproj
@@ -6,11 +6,11 @@
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/Code/Light.GuardClauses.SourceCodeTransformation/Light.GuardClauses.SourceCodeTransformation.csproj b/Code/Light.GuardClauses.SourceCodeTransformation/Light.GuardClauses.SourceCodeTransformation.csproj
index de93906..f9959ae 100644
--- a/Code/Light.GuardClauses.SourceCodeTransformation/Light.GuardClauses.SourceCodeTransformation.csproj
+++ b/Code/Light.GuardClauses.SourceCodeTransformation/Light.GuardClauses.SourceCodeTransformation.csproj
@@ -4,16 +4,16 @@
Exe
- net7.0
+ net8.0
enable
-
-
-
-
+
+
+
+
diff --git a/Code/Light.GuardClauses.SourceCodeTransformation/SourceFileMerger.cs b/Code/Light.GuardClauses.SourceCodeTransformation/SourceFileMerger.cs
index 78f6bba..6ceb25d 100644
--- a/Code/Light.GuardClauses.SourceCodeTransformation/SourceFileMerger.cs
+++ b/Code/Light.GuardClauses.SourceCodeTransformation/SourceFileMerger.cs
@@ -34,7 +34,7 @@ public static void CreateSingleSourceFile(SourceFileMergeOptions options)
.AppendLine($@"License information for Light.GuardClauses
The MIT License (MIT)
-Copyright (c) 2016, 2023 Kenny Pflug mailto:kenny.pflug@live.de
+Copyright (c) 2016, 2024 Kenny Pflug mailto:kenny.pflug@live.de
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the ""Software""), to deal
@@ -69,6 +69,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
using System.Text.RegularExpressions;
{(options.IncludeJetBrainsAnnotationsUsing ? "using JetBrains.Annotations;" + Environment.NewLine : string.Empty)}using {options.BaseNamespace}.Exceptions;
using {options.BaseNamespace}.FrameworkExtensions;
+{(options.IncludeJetBrainsAnnotationsUsing ? "using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute;" : "")}
#nullable enable annotations
diff --git a/Code/Light.GuardClauses.Tests/ComparableAssertions/RangeTests.cs b/Code/Light.GuardClauses.Tests/ComparableAssertions/RangeTests.cs
index 3b81b9f..e2a848b 100644
--- a/Code/Light.GuardClauses.Tests/ComparableAssertions/RangeTests.cs
+++ b/Code/Light.GuardClauses.Tests/ComparableAssertions/RangeTests.cs
@@ -55,6 +55,78 @@ public static void ConstructorException(int from, int to)
.Message.Should().Contain($"{nameof(to)} must not be less than {from}, but it actually is {to}.");
}
+ [Theory]
+ [InlineData(0, 10, 0)] // Lower boundary
+ [InlineData(0, 10, 5)] // Middle value
+ [InlineData(0, 10, 10)] // Upper boundary
+ public static void InclusiveBetween_ValuesInRange(int from, int to, int value)
+ {
+ var range = Range.InclusiveBetween(from, to);
+
+ var result = range.IsValueWithinRange(value);
+
+ result.Should().BeTrue();
+ }
+
+ [Theory]
+ [InlineData(0, 10, -1)] // Below range
+ [InlineData(0, 10, 11)] // Above range
+ public static void InclusiveBetween_ValuesOutOfRange(int from, int to, int value)
+ {
+ var range = Range.InclusiveBetween(from, to);
+
+ var result = range.IsValueWithinRange(value);
+
+ result.Should().BeFalse();
+ }
+
+ [Theory]
+ [InlineData(0, 10, 1)] // Just above lower boundary
+ [InlineData(0, 10, 5)] // Middle value
+ [InlineData(0, 10, 9)] // Just below upper boundary
+ public static void ExclusiveBetween_ValuesInRange(int from, int to, int value)
+ {
+ var range = Range.ExclusiveBetween(from, to);
+
+ var result = range.IsValueWithinRange(value);
+
+ result.Should().BeTrue();
+ }
+
+ [Theory]
+ [InlineData(0, 10, 0)] // Lower boundary
+ [InlineData(0, 10, 10)] // Upper boundary
+ [InlineData(0, 10, -1)] // Below range
+ [InlineData(0, 10, 11)] // Above range
+ public static void ExclusiveBetween_ValuesOutOfRange(int from, int to, int value)
+ {
+ var range = Range.ExclusiveBetween(from, to);
+
+ var result = range.IsValueWithinRange(value);
+
+ result.Should().BeFalse();
+ }
+
+ [Theory]
+ [InlineData(10, 5)] // To less than From
+ [InlineData(-5, -10)] // Negative To less than From
+ public static void InclusiveBetween_InvalidRange_ThrowsException(int from, int to)
+ {
+ Action inclusiveAct = () => Range.InclusiveBetween(from, to);
+ inclusiveAct.Should().Throw()
+ .And.Message.Should().Contain($"{nameof(to)} must not be less than {from}");
+ }
+
+ [Theory]
+ [InlineData(10, 5)] // To less than From
+ [InlineData(-5, -10)] // Negative To less than From
+ public static void ExclusiveBetween_InvalidRange_ThrowsException(int from, int to)
+ {
+ Action exclusiveAct = () => Range.ExclusiveBetween(from, to);
+ exclusiveAct.Should().Throw()
+ .And.Message.Should().Contain($"{nameof(to)} must not be less than {from}");
+ }
+
[Theory]
[MemberData(nameof(Collections))]
public static void RangeForCollections(IEnumerable enumerable)
@@ -164,4 +236,4 @@ public static void RangeForReadOnlySpan(Memory memory)
Enumerable.Range(1, 500).ToArray(),
Array.Empty()
};
-}
\ No newline at end of file
+}
diff --git a/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs
new file mode 100644
index 0000000..c6c0123
--- /dev/null
+++ b/Code/Light.GuardClauses.Tests/Issues/Issue72NotNullAttributeTests.cs
@@ -0,0 +1,1520 @@
+#nullable enable
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq.Expressions;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
+using FluentAssertions;
+using Light.GuardClauses.FrameworkExtensions;
+using Xunit;
+
+namespace Light.GuardClauses.Tests.Issues;
+
+// This occurs for delegates that create exceptions, and we just turn it off for these tests
+#pragma warning disable CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate type.
+
+public static class Issue72NotNullAttributeTests
+{
+ [Fact]
+ public static void CheckMustNotBeNull()
+ {
+ TestMustNotBeNull("foo").Should().Be(3);
+ _ = TestMustNotBeNullWithDelegate("foo").Should().Be(3);
+ return;
+
+ static int TestMustNotBeNull(string? input)
+ {
+ Check.MustNotBeNull(input);
+ return input.Length;
+ }
+
+ static int TestMustNotBeNullWithDelegate(string? input)
+ {
+ input.MustNotBeNull(() => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotBeDefault()
+ {
+ TestMustNotBeDefault("foo").Should().Be(3);
+ TestMustNotBeDefaultWithDelegate("foo").Should().Be(3);
+ return;
+
+ static int TestMustNotBeDefault(string? input)
+ {
+ input.MustNotBeDefault();
+ return input.Length;
+ }
+
+ static int TestMustNotBeDefaultWithDelegate(string? input)
+ {
+ input.MustNotBeDefault(() => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotBeNullReference()
+ {
+ TestMustNotBeNullReference("foo").Should().Be(3);
+ TestMustNotBeNullReferenceWithDelegate("foo").Should().Be(3);
+ return;
+
+ static int TestMustNotBeNullReference(string? input)
+ {
+ input.MustNotBeNullReference();
+ return input.Length;
+ }
+
+ static int TestMustNotBeNullReferenceWithDelegate(string? input)
+ {
+ input.MustNotBeNullReference(() => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeOfType()
+ {
+ TestMustBeOfType("foo").Should().Be(3);
+ TestMustBeOfTypeWithDelegate("foo").Should().Be(3);
+ return;
+
+ static int TestMustBeOfType(object? input)
+ {
+ input.MustBeOfType();
+ return ((string) input).Length;
+ }
+
+ static int TestMustBeOfTypeWithDelegate(object? input)
+ {
+ input.MustBeOfType(_ => new Exception());
+ return ((string) input).Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustHaveValue()
+ {
+ TestMustHaveValue(42).Should().Be(42);
+ TestMustHaveValueWithDelegate(42).Should().Be(42);
+ return;
+
+ static int TestMustHaveValue(int? input)
+ {
+ input.MustHaveValue();
+ return input.Value;
+ }
+
+ static int TestMustHaveValueWithDelegate(int? input)
+ {
+ input.MustHaveValue(() => new Exception());
+ return input.Value;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotBeLessThan()
+ {
+ TestMustNotBeLessThan("foo").Should().Be("foo");
+ TestMustNotBeLessThanWithDelegate("foo").Should().Be("foo");
+ return;
+
+ // I need to provoke a compiler warning
+#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.
+ static string TestMustNotBeLessThan(string? input)
+ {
+ input.MustNotBeLessThan("bar");
+ return input;
+ }
+
+ static string TestMustNotBeLessThanWithDelegate(string? input)
+ {
+ input.MustNotBeLessThan("bar", (_, _) => new Exception());
+ return input;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustBeGreaterThanOrEqualTo()
+ {
+ TestMustBeGreaterThanOrEqualTo("foo").Should().Be("foo");
+ TestMustBeGreaterThanOrEqualToWithDelegate("foo").Should().Be("foo");
+ return;
+
+#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.
+ static string TestMustBeGreaterThanOrEqualTo(string? input)
+ {
+ input.MustBeGreaterThanOrEqualTo("bar");
+ return input;
+ }
+
+ static string TestMustBeGreaterThanOrEqualToWithDelegate(string? input)
+ {
+ input.MustBeGreaterThanOrEqualTo("bar", (_, _) => new Exception());
+ return input;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustBeLessThan()
+ {
+ TestMustBeLessThan("bar").Should().Be("bar");
+ TestMustBeLessThanWithDelegate("bar").Should().Be("bar");
+ return;
+
+#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.
+ static string TestMustBeLessThan(string? input)
+ {
+ input.MustBeLessThan("foo");
+ return input;
+ }
+
+ static string TestMustBeLessThanWithDelegate(string? input)
+ {
+ input.MustBeLessThan("foo", (_, _) => new Exception());
+ return input;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustNotBeGreaterThanOrEqualTo()
+ {
+ TestMustNotBeGreaterThanOrEqualTo("bar").Should().Be("bar");
+ TestMustNotBeGreaterThanOrEqualToWithDelegate("bar").Should().Be("bar");
+ return;
+
+#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.
+ static string TestMustNotBeGreaterThanOrEqualTo(string? input)
+ {
+ input.MustNotBeGreaterThanOrEqualTo("foo");
+ return input;
+ }
+
+ static string TestMustNotBeGreaterThanOrEqualToWithDelegate(string? input)
+ {
+ input.MustNotBeGreaterThanOrEqualTo("foo", (_, _) => new Exception());
+ return input;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustBeGreaterThan()
+ {
+ TestMustBeGreaterThan("foo").Should().Be("foo");
+ TestMustBeGreaterThanWithDelegate("foo").Should().Be("foo");
+ return;
+
+#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.
+ static string TestMustBeGreaterThan(string? input)
+ {
+ input.MustBeGreaterThan("bar");
+ return input;
+ }
+
+ static string TestMustBeGreaterThanWithDelegate(string? input)
+ {
+ input.MustBeGreaterThan("bar", (_, _) => new Exception());
+ return input;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustNotBeLessThanOrEqualTo()
+ {
+ TestMustNotBeLessThanOrEqualTo("foo").Should().Be("foo");
+ TestMustNotBeLessThanOrEqualToWithDelegate("foo").Should().Be("foo");
+ return;
+
+#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.
+ static string TestMustNotBeLessThanOrEqualTo(string? input)
+ {
+ input.MustNotBeLessThanOrEqualTo("bar");
+ return input;
+ }
+
+ static string TestMustNotBeLessThanOrEqualToWithDelegate(string? input)
+ {
+ input.MustNotBeLessThanOrEqualTo("bar", (_, _) => new Exception());
+ return input;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustNotBeGreaterThan()
+ {
+ TestMustNotBeGreaterThan("bar").Should().Be("bar");
+ TestMustNotBeGreaterThanWithDelegate("bar").Should().Be("bar");
+ return;
+
+#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.
+ static string TestMustNotBeGreaterThan(string? input)
+ {
+ input.MustNotBeGreaterThan("foo");
+ return input;
+ }
+
+ static string TestMustNotBeGreaterThanWithDelegate(string? input)
+ {
+ input.MustNotBeGreaterThan("foo", (_, _) => new Exception());
+ return input;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustBeLessThanOrEqualTo()
+ {
+ TestMustBeLessThanOrEqualTo("bar").Should().Be("bar");
+ TestMustBeLessThanOrEqualToWithDelegate("bar").Should().Be("bar");
+ return;
+
+#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.
+ static string TestMustBeLessThanOrEqualTo(string? input)
+ {
+ input.MustBeLessThanOrEqualTo("foo");
+ return input;
+ }
+
+ static string TestMustBeLessThanOrEqualToWithDelegate(string? input)
+ {
+ input.MustBeLessThanOrEqualTo("foo", (_, _) => new Exception());
+ return input;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustBeIn()
+ {
+ TestMustBeIn("b").Should().Be(1);
+ TestMustBeInWithDelegate("b").Should().Be(1);
+
+#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.
+ static int TestMustBeIn(string? input)
+ {
+ input.MustBeIn(Range.FromInclusive("a").ToInclusive("c")!);
+ return input.Length;
+ }
+
+ static int TestMustBeInWithDelegate(string? input)
+ {
+ input.MustBeIn(Range.FromInclusive("a").ToInclusive("c")!, (_, _) => new Exception());
+ return input.Length;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustNotBeIn()
+ {
+ TestMustNotBeIn("d").Should().Be(1);
+ TestMustNotBeInWithDelegate("d").Should().Be(1);
+
+#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.
+ static int TestMustNotBeIn(string? input)
+ {
+ input.MustNotBeIn(Range.FromInclusive("a").ToInclusive("c")!);
+ return input.Length;
+ }
+
+ static int TestMustNotBeInWithDelegate(string? input)
+ {
+ input.MustNotBeIn(Range.FromInclusive("a").ToInclusive("c")!, (_, _) => new Exception());
+ return input.Length;
+ }
+#pragma warning restore CS8631
+ }
+
+ [Fact]
+ public static void CheckMustHaveCount()
+ {
+ TestMustHaveCount([]).Should().Be(0);
+ TestMustHaveCountWithDelegate([]).Should().Be(0);
+ return;
+
+ static int TestMustHaveCount(string[]? input)
+ {
+ input.MustHaveCount(0);
+ return input.Length;
+ }
+
+ static int TestMustHaveCountWithDelegate(string[]? input)
+ {
+ input.MustHaveCount(0, (_, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotBeNullOrEmpty()
+ {
+ TestMustNotBeNullOrEmpty([1, 2, 3]).Should().Be(3);
+ TestMustNotBeNullOrEmptyWithDelegate([1, 2, 3]).Should().Be(3);
+ return;
+
+ static int TestMustNotBeNullOrEmpty(int[]? input)
+ {
+ input.MustNotBeNullOrEmpty();
+ return input.Length;
+ }
+
+ static int TestMustNotBeNullOrEmptyWithDelegate(int[]? input)
+ {
+ input.MustNotBeNullOrEmpty(_ => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustContainForCollections()
+ {
+ TestMustContain([1, 2, 3]).Should().Be(3);
+ TestMustContainWithDelegate([1, 2, 3]).Should().Be(3);
+ return;
+
+ static int TestMustContain(int[]? input)
+ {
+ input.MustContain(2);
+ return input.Length;
+ }
+
+ static int TestMustContainWithDelegate(int[]? input)
+ {
+ input.MustContain(2, (_, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotContain()
+ {
+ TestMustNotContain([1, 2, 3]).Should().Be(3);
+ TestMustNotContainWithDelegate([1, 2, 3]).Should().Be(3);
+ return;
+
+ static int TestMustNotContain(int[]? input)
+ {
+ input.MustNotContain(4);
+ return input.Length;
+ }
+
+ static int TestMustNotContainWithDelegate(int[]? input)
+ {
+ input.MustNotContain(4, (_, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckIsOneOf()
+ {
+ TestIsOneOf("foo").Should().Be(3);
+ return;
+
+ static int TestIsOneOf(string? input)
+ {
+ 'o'.IsOneOf(input!);
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeOneOf()
+ {
+ TestMustBeOneOf("foo").Should().Be(3);
+ TestMustBeOneOfWithDelegate("foo").Should().Be(3);
+ return;
+
+ static int TestMustBeOneOf(string? input)
+ {
+ 'o'.MustBeOneOf(input!);
+ return input.Length;
+ }
+
+ static int TestMustBeOneOfWithDelegate(string? input)
+ {
+ 'o'.MustBeOneOf(input!, (_, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotBeOneOf()
+ {
+ TestMustNotBeOneOf("bar").Should().Be(3);
+ TestMustNotBeOneOfWithDelegate("bar").Should().Be(3);
+ return;
+
+ static int TestMustNotBeOneOf(string? input)
+ {
+ 'o'.MustNotBeOneOf(input!);
+ return input.Length;
+ }
+
+ static int TestMustNotBeOneOfWithDelegate(string? input)
+ {
+ 'o'.MustNotBeOneOf(input!, (_, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustHaveMinimumCount()
+ {
+ TestMustHaveMinimumCount([1, 2, 3]).Should().Be(3);
+ TestMustHaveMinimumCountWithDelegate([1, 2, 3]).Should().Be(3);
+ return;
+
+ static int TestMustHaveMinimumCount(int[]? input)
+ {
+ input.MustHaveMinimumCount(2);
+ return input.Length;
+ }
+
+ static int TestMustHaveMinimumCountWithDelegate(int[]? input)
+ {
+ input.MustHaveMinimumCount(2, (_, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustHaveMaximumCount()
+ {
+ TestMustHaveMaximumCount([1, 2, 3]).Should().Be(3);
+ TestMustHaveMaximumCountWithDelegate([1, 2, 3]).Should().Be(3);
+ return;
+
+ static int TestMustHaveMaximumCount(int[]? input)
+ {
+ input.MustHaveMaximumCount(3);
+ return input.Length;
+ }
+
+ static int TestMustHaveMaximumCountWithDelegate(int[]? input)
+ {
+ input.MustHaveMaximumCount(3, (_, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotBeNullOrEmptyString()
+ {
+ TestMustNotBeNullOrEmptyString("foo").Should().Be(3);
+ TestMustNotBeNullOrEmptyStringWithDelegate("foo").Should().Be(3);
+ return;
+
+ static int TestMustNotBeNullOrEmptyString(string? input)
+ {
+ input.MustNotBeNullOrEmpty();
+ return input.Length;
+ }
+
+ static int TestMustNotBeNullOrEmptyStringWithDelegate(string? input)
+ {
+ input.MustNotBeNullOrEmpty(_ => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotBeNullOrWhiteSpace()
+ {
+ TestMustNotBeNullOrWhiteSpace("foo").Should().Be(3);
+ TestMustNotBeNullOrWhiteSpaceWithDelegate("foo").Should().Be(3);
+ return;
+
+ static int TestMustNotBeNullOrWhiteSpace(string? input)
+ {
+ input.MustNotBeNullOrWhiteSpace();
+ return input.Length;
+ }
+
+ static int TestMustNotBeNullOrWhiteSpaceWithDelegate(string? input)
+ {
+ input.MustNotBeNullOrWhiteSpace(_ => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustMatch()
+ {
+ TestMustMatch("foo", "^f.*").Should().Be(3);
+ TestMustMatchWithDelegate("foo", "^f.*").Should().Be(3);
+ return;
+
+ static int TestMustMatch(string? input, string pattern)
+ {
+ input.MustMatch(new Regex(pattern));
+ return input.Length;
+ }
+
+ static int TestMustMatchWithDelegate(string? input, string pattern)
+ {
+ input.MustMatch(new Regex(pattern), (_, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustContainForStrings()
+ {
+ TestMustContain("foo").Should().Be(3);
+ TestMustContainWithDelegate("foo").Should().Be(3);
+ TestMustContainWithStringComparison("foo").Should().Be(3);
+ TestMustContainWithDelegateAndStringComparison("foo").Should().Be(3);
+ return;
+
+ static int TestMustContain(string? input)
+ {
+ input.MustContain("oo");
+ return input.Length;
+ }
+
+ static int TestMustContainWithDelegate(string? input)
+ {
+ input.MustContain("oo", (_, _) => new Exception());
+ return input.Length;
+ }
+
+ static int TestMustContainWithStringComparison(string? input)
+ {
+ input.MustContain("OO", StringComparison.OrdinalIgnoreCase);
+ return input.Length;
+ }
+
+ static int TestMustContainWithDelegateAndStringComparison(string? input)
+ {
+ input.MustContain("OO", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotContainForStrings()
+ {
+ TestMustNotContain("foo").Should().Be(3);
+ TestMustNotContainWithDelegate("foo").Should().Be(3);
+ TestMustNotContainWithStringComparison("foo").Should().Be(3);
+ TestMustNotContainWithDelegateAndStringComparison("foo").Should().Be(3);
+ return;
+
+ static int TestMustNotContain(string? input)
+ {
+ input.MustNotContain("bar");
+ return input.Length;
+ }
+
+ static int TestMustNotContainWithDelegate(string? input)
+ {
+ input.MustNotContain("bar", (_, _) => new Exception());
+ return input.Length;
+ }
+
+ static int TestMustNotContainWithStringComparison(string? input)
+ {
+ input.MustNotContain("BAR", StringComparison.OrdinalIgnoreCase);
+ return input.Length;
+ }
+
+ static int TestMustNotContainWithDelegateAndStringComparison(string? input)
+ {
+ input.MustNotContain("BAR", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeSubstringOf()
+ {
+ TestMustBeSubstringOf("foo", "foobar").Should().Be(3);
+ TestMustBeSubstringOfWithDelegate("foo", "foobar").Should().Be(3);
+ TestMustBeSubstringOfWithStringComparison("OO").Should().Be(2);
+ TestMustBeSubstringOfWithDelegateAndStringComparison("OO").Should().Be(2);
+ return;
+
+ static int TestMustBeSubstringOf(string? input, string target)
+ {
+ input.MustBeSubstringOf(target);
+ return input.Length;
+ }
+
+ static int TestMustBeSubstringOfWithDelegate(string? input, string target)
+ {
+ input.MustBeSubstringOf(target, (_, _) => new Exception());
+ return input.Length;
+ }
+
+ static int TestMustBeSubstringOfWithStringComparison(string? input)
+ {
+ input.MustBeSubstringOf("foo", StringComparison.OrdinalIgnoreCase);
+ return input.Length;
+ }
+
+ static int TestMustBeSubstringOfWithDelegateAndStringComparison(string? input)
+ {
+ input.MustBeSubstringOf("foo", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustNotBeSubstringOf()
+ {
+ TestMustNotBeSubstringOf("foo", "bar").Should().Be(3);
+ TestMustNotBeSubstringOfWithDelegate("foo", "bar").Should().Be(3);
+ TestMustNotBeSubstringOfWithStringComparison("FOO").Should().Be(3);
+ TestMustNotBeSubstringOfWithDelegateAndStringComparison("FOO").Should().Be(3);
+ return;
+
+ static int TestMustNotBeSubstringOf(string? input, string target)
+ {
+ input.MustNotBeSubstringOf(target);
+ return input.Length;
+ }
+
+ static int TestMustNotBeSubstringOfWithDelegate(string? input, string target)
+ {
+ input.MustNotBeSubstringOf(target, (_, _) => new Exception());
+ return input.Length;
+ }
+
+ static int TestMustNotBeSubstringOfWithStringComparison(string? input)
+ {
+ input.MustNotBeSubstringOf("bar", StringComparison.OrdinalIgnoreCase);
+ return input.Length;
+ }
+
+ static int TestMustNotBeSubstringOfWithDelegateAndStringComparison(string? input)
+ {
+ input.MustNotBeSubstringOf("bar", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception());
+ return input.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeEmailAddress()
+ {
+ TestMustBeEmailAddress("test@example.com").Should().Be("test@example.com");
+ TestMustBeEmailAddressWithDelegate("test@example.com").Should().Be("test@example.com");
+ TestMustBeEmailAddressWithRegex("test@example.com").Should().Be("test@example.com");
+ TestMustBeEmailAddressWithRegexAndDelegate("test@example.com").Should().Be("test@example.com");
+ return;
+
+ static string TestMustBeEmailAddress(string? input)
+ {
+ input.MustBeEmailAddress();
+ return input;
+ }
+
+ static string TestMustBeEmailAddressWithDelegate(string? input)
+ {
+ input.MustBeEmailAddress(_ => new Exception());
+ return input;
+ }
+
+ static string TestMustBeEmailAddressWithRegex(string? input)
+ {
+ input.MustBeEmailAddress(new Regex(@"^[^@\s]+@[^@\s]+\.[^@\s]+$"));
+ return input;
+ }
+
+ static string TestMustBeEmailAddressWithRegexAndDelegate(string? input)
+ {
+ input.MustBeEmailAddress(new Regex(@"^[^@\s]+@[^@\s]+\.[^@\s]+$"), (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeShorterThan()
+ {
+ TestMustBeShorterThan("foo").Should().Be("foo");
+ TestMustBeShorterThanWithDelegate("foo").Should().Be("foo");
+ return;
+
+ static string TestMustBeShorterThan(string? input)
+ {
+ input.MustBeShorterThan(5);
+ return input;
+ }
+
+ static string TestMustBeShorterThanWithDelegate(string? input)
+ {
+ input.MustBeShorterThan(5, (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeShorterThanOrEqualTo()
+ {
+ TestMustBeShorterThanOrEqualTo("foo").Should().Be("foo");
+ TestMustBeShorterThanOrEqualToWithDelegate("foo").Should().Be("foo");
+ return;
+
+ static string TestMustBeShorterThanOrEqualTo(string? input)
+ {
+ input.MustBeShorterThanOrEqualTo(3);
+ return input;
+ }
+
+ static string TestMustBeShorterThanOrEqualToWithDelegate(string? input)
+ {
+ input.MustBeShorterThanOrEqualTo(3, (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustHaveLength()
+ {
+ TestMustHaveLength("foo").Should().Be("foo");
+ TestMustHaveLengthWithDelegate("foo").Should().Be("foo");
+ return;
+
+ static string TestMustHaveLength(string? input)
+ {
+ input.MustHaveLength(3);
+ return input;
+ }
+
+ static string TestMustHaveLengthWithDelegate(string? input)
+ {
+ input.MustHaveLength(3, (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeLongerThan()
+ {
+ TestMustBeLongerThan("foobar").Should().Be("foobar");
+ TestMustBeLongerThanWithDelegate("foobar").Should().Be("foobar");
+ return;
+
+ static string TestMustBeLongerThan(string? input)
+ {
+ input.MustBeLongerThan(3);
+ return input;
+ }
+
+ static string TestMustBeLongerThanWithDelegate(string? input)
+ {
+ input.MustBeLongerThan(3, (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeLongerThanOrEqualTo()
+ {
+ TestMustBeLongerThanOrEqualTo("foobar").Should().Be("foobar");
+ TestMustBeLongerThanOrEqualToWithDelegate("foobar").Should().Be("foobar");
+ return;
+
+ static string TestMustBeLongerThanOrEqualTo(string? input)
+ {
+ input.MustBeLongerThanOrEqualTo(6);
+ return input;
+ }
+
+ static string TestMustBeLongerThanOrEqualToWithDelegate(string? input)
+ {
+ input.MustBeLongerThanOrEqualTo(6, (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustHaveLengthIn()
+ {
+ TestMustHaveLengthIn("foo").Should().Be("foo");
+ TestMustHaveLengthInWithDelegate("foo").Should().Be("foo");
+ return;
+
+ static string TestMustHaveLengthIn(string? input)
+ {
+ input.MustHaveLengthIn(Range.FromInclusive(2).ToInclusive(4));
+ return input;
+ }
+
+ static string TestMustHaveLengthInWithDelegate(string? input)
+ {
+ input.MustHaveLengthIn(Range.FromInclusive(2).ToInclusive(4), (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeNewLine()
+ {
+ TestMustBeNewLine("\n").Should().Be("\n");
+ TestMustBeNewLineWithDelegate("\n").Should().Be("\n");
+ return;
+
+ static string TestMustBeNewLine(string? input)
+ {
+ input.MustBeNewLine();
+ return input;
+ }
+
+ static string TestMustBeNewLineWithDelegate(string? input)
+ {
+ input.MustBeNewLine(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeTrimmed()
+ {
+ TestMustBeTrimmed("foo").Should().Be("foo");
+ TestMustBeTrimmedWithDelegate("foo").Should().Be("foo");
+ return;
+
+ static string TestMustBeTrimmed(string? input)
+ {
+ input.MustBeTrimmed();
+ return input;
+ }
+
+ static string TestMustBeTrimmedWithDelegate(string? input)
+ {
+ input.MustBeTrimmed(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeTrimmedAtStart()
+ {
+ TestMustBeTrimmedAtStart("foo").Should().Be("foo");
+ TestMustBeTrimmedAtStartWithDelegate("foo").Should().Be("foo");
+ return;
+
+ static string TestMustBeTrimmedAtStart(string? input)
+ {
+ input.MustBeTrimmedAtStart();
+ return input;
+ }
+
+ static string TestMustBeTrimmedAtStartWithDelegate(string? input)
+ {
+ input.MustBeTrimmedAtStart(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeTrimmedAtEnd()
+ {
+ TestMustBeTrimmedAtEnd("foo").Should().Be("foo");
+ TestMustBeTrimmedAtEndWithDelegate("foo").Should().Be("foo");
+ return;
+
+ static string TestMustBeTrimmedAtEnd(string? input)
+ {
+ input.MustBeTrimmedAtEnd();
+ return input;
+ }
+
+ static string TestMustBeTrimmedAtEndWithDelegate(string? input)
+ {
+ input.MustBeTrimmedAtEnd(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckImplements()
+ {
+ TestImplements(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable)));
+ TestImplementsWithComparer(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable), EqualityComparer.Default));
+ return;
+
+ static (Type Type, Type InterfaceType) TestImplements(Type? type, Type? interfaceType)
+ {
+ type!.Implements(interfaceType!);
+ return (type, interfaceType);
+ }
+
+ static (Type Type, Type InterfaceType, IEqualityComparer Comparer) TestImplementsWithComparer(Type? type, Type? interfaceType)
+ {
+ type!.Implements(interfaceType!, EqualityComparer.Default);
+ return (type, interfaceType, EqualityComparer.Default);
+ }
+ }
+
+ [Fact]
+ public static void CheckIsOrImplements()
+ {
+ TestIsOrImplements(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable)));
+ TestIsOrImplementsWithComparer(typeof(FileInfo), typeof(ISerializable)).Should().Be((typeof(FileInfo), typeof(ISerializable), EqualityComparer.Default));
+ return;
+
+ static (Type Type, Type InterfaceType) TestIsOrImplements(Type? type, Type? interfaceType)
+ {
+ type!.IsOrImplements(interfaceType!);
+ return (type, interfaceType);
+ }
+
+ static (Type Type, Type InterfaceType, IEqualityComparer Comparer) TestIsOrImplementsWithComparer(Type? type, Type? interfaceType)
+ {
+ type!.IsOrImplements(interfaceType!, EqualityComparer.Default);
+ return (type, interfaceType, EqualityComparer.Default);
+ }
+ }
+
+ [Fact]
+ public static void CheckDerivesFrom()
+ {
+ TestDerivesFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream)));
+ TestDerivesFromWithTypeComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream)));
+ return;
+
+ static (Type Type, Type BaseType) TestDerivesFrom(Type? type, Type? baseType)
+ {
+ type!.DerivesFrom(baseType!);
+ return (type, baseType);
+ }
+
+ static (Type Type, Type BaseType) TestDerivesFromWithTypeComparer(Type? type, Type? baseType)
+ {
+ type!.DerivesFrom(baseType!, EqualityComparer.Default);
+ return (type, baseType);
+ }
+ }
+
+ [Fact]
+ public static void CheckIsOrDerivesFrom()
+ {
+ TestIsOrDerivesFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream)));
+ TestIsOrDerivesFromWithComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream), EqualityComparer.Default));
+ return;
+
+ static (Type Type, Type BaseType) TestIsOrDerivesFrom(Type? type, Type? baseType)
+ {
+ type!.IsOrDerivesFrom(baseType!);
+ return (type, baseType);
+ }
+
+ static (Type Type, Type BaseType, IEqualityComparer Comparer) TestIsOrDerivesFromWithComparer(Type? type, Type? baseType)
+ {
+ type!.IsOrDerivesFrom(baseType!, EqualityComparer.Default);
+ return (type, baseType, EqualityComparer.Default);
+ }
+ }
+
+ [Fact]
+ public static void CheckInheritsFrom()
+ {
+ TestInheritsFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream)));
+ TestInheritsFromWithTypeComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream), EqualityComparer.Default));
+ return;
+
+ static (Type Type, Type BaseType) TestInheritsFrom(Type? type, Type? baseType)
+ {
+ type!.InheritsFrom(baseType!);
+ return (type, baseType);
+ }
+
+ static (Type Type, Type BaseType, IEqualityComparer Comparer) TestInheritsFromWithTypeComparer(Type? type, Type? baseType)
+ {
+ type!.InheritsFrom(baseType!, EqualityComparer.Default);
+ return (type, baseType, EqualityComparer.Default);
+ }
+ }
+
+
+ [Fact]
+ public static void CheckIsOrInheritsFrom()
+ {
+ TestIsOrInheritsFrom(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream)));
+ TestIsOrInheritsFromWithComparer(typeof(FileStream), typeof(Stream)).Should().Be((typeof(FileStream), typeof(Stream), EqualityComparer.Default));
+ return;
+
+ static (Type Type, Type BaseType) TestIsOrInheritsFrom(Type? type, Type? baseType)
+ {
+ type!.IsOrInheritsFrom(baseType!);
+ return (type, baseType);
+ }
+
+ static (Type Type, Type BaseType, IEqualityComparer Comparer) TestIsOrInheritsFromWithComparer(Type? type, Type? baseType)
+ {
+ type!.IsOrInheritsFrom(baseType!, EqualityComparer.Default);
+ return (type, baseType, EqualityComparer.Default);
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeAbsoluteUri()
+ {
+ TestMustBeAbsoluteUri(new Uri("https://example.com")).Should().Be(new Uri("https://example.com"));
+ TestMustBeAbsoluteUriWithDelegate(new Uri("https://example.com")).Should().Be(new Uri("https://example.com"));
+ return;
+
+ static Uri TestMustBeAbsoluteUri(Uri? input)
+ {
+ input.MustBeAbsoluteUri();
+ return input;
+ }
+
+ static Uri TestMustBeAbsoluteUriWithDelegate(Uri? input)
+ {
+ input.MustBeAbsoluteUri(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeRelativeUri()
+ {
+ TestMustBeRelativeUri(new Uri("/relative/path", UriKind.Relative)).Should().Be(new Uri("/relative/path", UriKind.Relative));
+ TestMustBeRelativeUriWithDelegate(new Uri("/relative/path", UriKind.Relative)).Should().Be(new Uri("/relative/path", UriKind.Relative));
+ return;
+
+ static Uri TestMustBeRelativeUri(Uri? input)
+ {
+ input.MustBeRelativeUri();
+ return input;
+ }
+
+ static Uri TestMustBeRelativeUriWithDelegate(Uri? input)
+ {
+ input.MustBeRelativeUri(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustHaveScheme()
+ {
+ TestMustHaveScheme(new Uri("https://example.com"), "https").Should().Be(new Uri("https://example.com"));
+ TestMustHaveSchemeWithDelegate(new Uri("https://example.com"), "https").Should().Be(new Uri("https://example.com"));
+ TestMustHaveSchemeWithSecondDelegate(new Uri("https://example.com"), "https").Should().Be(new Uri("https://example.com"));
+ return;
+
+ static Uri TestMustHaveScheme(Uri? input, string scheme)
+ {
+ input.MustHaveScheme(scheme);
+ return input;
+ }
+
+ static Uri TestMustHaveSchemeWithDelegate(Uri? input, string scheme)
+ {
+ input.MustHaveScheme(scheme, _ => new Exception());
+ return input;
+ }
+
+ static Uri TestMustHaveSchemeWithSecondDelegate(Uri? input, string scheme)
+ {
+ input.MustHaveScheme(scheme, (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeHttpsUrl()
+ {
+ TestMustBeHttpsUrl(new Uri("https://example.com")).Should().Be(new Uri("https://example.com"));
+ TestMustBeHttpsUrlWithDelegate(new Uri("https://example.com")).Should().Be(new Uri("https://example.com"));
+ return;
+
+ static Uri TestMustBeHttpsUrl(Uri? input)
+ {
+ input.MustBeHttpsUrl();
+ return input;
+ }
+
+ static Uri TestMustBeHttpsUrlWithDelegate(Uri? input)
+ {
+ input.MustBeHttpsUrl(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeHttpUrl()
+ {
+ TestMustBeHttpUrl(new Uri("http://example.com")).Should().Be(new Uri("http://example.com"));
+ TestMustBeHttpUrlWithDelegate(new Uri("http://example.com")).Should().Be(new Uri("http://example.com"));
+ return;
+
+ static Uri TestMustBeHttpUrl(Uri? input)
+ {
+ input.MustBeHttpUrl();
+ return input;
+ }
+
+ static Uri TestMustBeHttpUrlWithDelegate(Uri? input)
+ {
+ input.MustBeHttpUrl(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustBeHttpOrHttpsUrl()
+ {
+ TestMustBeHttpOrHttpsUrl(new Uri("https://example.com")).Should().Be(new Uri("https://example.com"));
+ TestMustBeHttpOrHttpsUrlWithDelegate(new Uri("https://example.com")).Should().Be(new Uri("https://example.com"));
+ return;
+
+ static Uri TestMustBeHttpOrHttpsUrl(Uri? input)
+ {
+ input.MustBeHttpOrHttpsUrl();
+ return input;
+ }
+
+ static Uri TestMustBeHttpOrHttpsUrlWithDelegate(Uri? input)
+ {
+ input.MustBeHttpOrHttpsUrl(_ => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckMustHaveOneSchemeOf()
+ {
+ TestMustHaveOneSchemeOf(new Uri("https://example.com")).Should().Be(new Uri("https://example.com"));
+ TestMustHaveOneSchemeOfWithDelegate(new Uri("https://example.com")).Should().Be(new Uri("https://example.com"));
+ return;
+
+ static Uri TestMustHaveOneSchemeOf(Uri? input)
+ {
+ input.MustHaveOneSchemeOf(["http", "https"]);
+ return input;
+ }
+
+ static Uri TestMustHaveOneSchemeOfWithDelegate(Uri? input)
+ {
+ input.MustHaveOneSchemeOf(new[] { "http", "https" }, (_, _) => new Exception());
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckIsIn()
+ {
+ TestIsIn("k").Should().Be("k");
+ return;
+
+ static string TestIsIn(string? input)
+ {
+ input!.IsIn(Range.FromInclusive("a").ToInclusive("z"));
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckIsNotIn()
+ {
+ TestIsNotIn("k").Should().Be("k");
+ return;
+
+ static string TestIsNotIn(string? input)
+ {
+ input!.IsNotIn(Range.FromInclusive("a").ToInclusive("h"));
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckIsSubstringOf()
+ {
+ TestIsSubstringOf("foo", "oo").Should().Be("foo");
+ TestIsSubstringOfWithComparison("foo", "oo").Should().Be("foo");
+ return;
+
+ static string TestIsSubstringOf(string? input, string? comparison)
+ {
+ comparison!.IsSubstringOf(input!);
+ return input;
+ }
+
+ static string TestIsSubstringOfWithComparison(string? input, string? comparison)
+ {
+ comparison!.IsSubstringOf(input!, StringComparison.OrdinalIgnoreCase);
+ return input;
+ }
+ }
+
+ [Fact]
+ public static void CheckIsOpenConstructedGenericType()
+ {
+ TestIsOpenConstructedGenericType(typeof(List<>)).Should().Be(typeof(List<>));
+ return;
+
+ static Type TestIsOpenConstructedGenericType(Type? type)
+ {
+ type!.IsOpenConstructedGenericType();
+ return type;
+ }
+ }
+
+ [Fact]
+ public static void CheckAsList()
+ {
+ TestAsList(new List()).Should().Be(0);
+ TestAsListWithDelegate(new List()).Should().Be(0);
+ return;
+
+ static int TestAsList(IList? list)
+ {
+ list!.AsList();
+ return list.Count;
+ }
+
+ static int TestAsListWithDelegate(IList? list)
+ {
+ list!.AsList(collection => new List(collection));
+ return list.Count;
+ }
+ }
+
+ [Fact]
+ public static void CheckAsArray()
+ {
+ TestAsArray([1, 2, 3]).Should().Be(3);
+ return;
+
+ static int TestAsArray(int[]? array)
+ {
+ array!.AsArray();
+ return array.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckForEach()
+ {
+ TestForEach(["foo", "bar"]).Should().Be(2);
+ return;
+
+ static int TestForEach(string[]? array)
+ {
+ array!.ForEach(_ => { });
+ return array.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckAsReadOnlyList()
+ {
+ TestAsReadOnlyList([1, 2, 3]).Should().Be(3);
+ TestAsReadOnlyListWithDelegate([1, 2, 3], collection => new List(collection)).Should().Be(3);
+ return;
+
+ static int TestAsReadOnlyList(int[]? array)
+ {
+ array!.AsReadOnlyList();
+ return array.Length;
+ }
+
+ static int TestAsReadOnlyListWithDelegate(int[]? array, Func, IReadOnlyList>? collectionFactory)
+ {
+ array!.AsReadOnlyList(collectionFactory!);
+ return array.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckCount()
+ {
+ TestCount(new ArrayList(new[] { 1, 2, 3 })).Should().Be(3);
+ TestCountWithParameterNameAndMessage(new ArrayList(new[] { 1, 2, 3 })).Should().Be(3);
+ return;
+
+ static int TestCount(ICollection? collection)
+ {
+ collection!.Count();
+ return collection.Count;
+ }
+
+ static int TestCountWithParameterNameAndMessage(ICollection? collection)
+ {
+ collection!.Count(nameof(collection), "The collection must not be null");
+ return collection.Count;
+ }
+ }
+
+ [Fact]
+ public static void CheckGetCount()
+ {
+ TestGetCount([1, 2, 3]).Should().Be(3);
+ TestGetCountWithParameterNameAndMessage([1, 2, 3]).Should().Be(3);
+ return;
+
+ static int TestGetCount(ICollection? collection)
+ {
+ collection!.GetCount();
+ return collection.Count;
+ }
+
+ static int TestGetCountWithParameterNameAndMessage(ICollection? collection)
+ {
+ collection!.GetCount(nameof(collection), "The collection must not be null");
+ return collection.Count;
+ }
+ }
+
+ [Fact]
+ public static void CheckExtractProperty()
+ {
+ TestExtractProperty((string a) => a.Length).Should().NotBeNull();
+ return;
+
+ static Type TestExtractProperty(Expression>? expression)
+ {
+ expression!.ExtractProperty();
+ return expression.Type;
+ }
+ }
+
+ [Fact]
+ public static void CheckExtractField()
+ {
+ TestExtractField((TestClassWithPublicField x) => x.PublicField).Should().NotBeNull();
+ return;
+
+ static Type TestExtractField(Expression>? expression)
+ {
+ expression!.ExtractField();
+ return expression.Type;
+ }
+ }
+
+ private sealed class TestClassWithPublicField
+ {
+#pragma warning disable CS0414 // Field is assigned but its value is never used
+ // ReSharper disable once ConvertToConstant.Local
+ public readonly int PublicField = 42;
+#pragma warning restore CS0414
+ }
+
+ [Fact]
+ public static void CheckAppendCollectionContent()
+ {
+ var stringBuilder = new StringBuilder();
+ TestAppendCollectionContent(stringBuilder, [1, 2, 3]).Should().Be((stringBuilder, 3));
+ return;
+
+ static (StringBuilder, int) TestAppendCollectionContent(StringBuilder? stringBuilder, ICollection? items)
+ {
+ stringBuilder!.AppendCollectionContent(items!);
+ return (stringBuilder, items.Count);
+ }
+ }
+
+ [Fact]
+ public static void CheckToStringRepresentation()
+ {
+ TestToStringRepresentation("foo").Should().Be(3);
+ return;
+
+ static int TestToStringRepresentation(string? value)
+ {
+ value.ToStringRepresentation();
+ return value.Length;
+ }
+ }
+
+ [Fact]
+ public static void CheckAppendItemsWithNewLine()
+ {
+ var stringBuilder = new StringBuilder();
+ TestAppendItemsWithNewLine(stringBuilder, [1, 2, 3]).Should().Be((stringBuilder, 3));
+ return;
+
+ static (StringBuilder, int) TestAppendItemsWithNewLine(StringBuilder? stringBuilder, ICollection? items)
+ {
+ stringBuilder!.AppendItemsWithNewLine(items!);
+ return (stringBuilder, items.Count);
+ }
+ }
+
+ [Fact]
+ public static void CheckAppendIf()
+ {
+ var stringBuilder = new StringBuilder();
+ TestAppendIf(stringBuilder, true, "foo").Should().Be((stringBuilder, 3));
+ return;
+
+ static (StringBuilder, int) TestAppendIf(StringBuilder? stringBuilder, bool condition, string value)
+ {
+ stringBuilder!.AppendIf(condition, value);
+ return (stringBuilder, value.Length);
+ }
+ }
+
+ [Fact]
+ public static void CheckAppendLineIf()
+ {
+ var stringBuilder = new StringBuilder();
+ TestAppendLineIf(stringBuilder, true, "foo").Should().Be((stringBuilder, 3));
+ return;
+
+ static (StringBuilder, int) TestAppendLineIf(StringBuilder? stringBuilder, bool condition, string value)
+ {
+ stringBuilder!.AppendLineIf(condition, value);
+ return (stringBuilder, value.Length);
+ }
+ }
+
+ [Fact]
+ public static void CheckAppendItems()
+ {
+ var stringBuilder = new StringBuilder();
+ TestAppendItems(stringBuilder, [1, 2, 3]).Should().Be((stringBuilder, 3));
+ return;
+
+ static (StringBuilder, int) TestAppendItems(StringBuilder? stringBuilder, ICollection? items)
+ {
+ stringBuilder!.AppendItems(items!);
+ return (stringBuilder, items.Count);
+ }
+ }
+
+ [Fact]
+ public static void CheckAppendExceptionMessages()
+ {
+ var stringBuilder = new StringBuilder();
+ TestAppendExceptionMessages(stringBuilder, new Exception("foo")).Should().Be((stringBuilder, 3));
+ return;
+
+ static (StringBuilder, int) TestAppendExceptionMessages(StringBuilder? stringBuilder, Exception exception)
+ {
+ stringBuilder!.AppendExceptionMessages(exception);
+ return (stringBuilder, exception.Message.Length);
+ }
+ }
+
+ [Fact]
+ public static void CheckGetAllExceptionMessages()
+ {
+ TestGetAllExceptionMessages(new Exception("foo")).Should().Be(3);
+ return;
+
+ static int TestGetAllExceptionMessages(Exception? exception)
+ {
+ exception!.GetAllExceptionMessages();
+ return exception.Message.Length;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj b/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj
index 2633bd0..34f0e4e 100644
--- a/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj
+++ b/Code/Light.GuardClauses.Tests/Light.GuardClauses.Tests.csproj
@@ -1,19 +1,23 @@
-
-
-
-
-
- net8.0
- false
- 12
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ net8.0
+ false
+ 12
+ true
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
\ No newline at end of file
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustBeSubstringOfTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustBeSubstringOfTests.cs
index 3408d69..d6079be 100644
--- a/Code/Light.GuardClauses.Tests/StringAssertions/MustBeSubstringOfTests.cs
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustBeSubstringOfTests.cs
@@ -94,7 +94,6 @@ public static void CustomException(string first, string second) =>
[InlineData("Foo", "FOO", StringComparison.Ordinal)]
[InlineData("Bar", null, StringComparison.OrdinalIgnoreCase)]
[InlineData(null, "Baz", StringComparison.CurrentCulture)]
- [InlineData("Qux", "Quux", (StringComparison) 509)]
public static void CustomExceptionCustomComparisonType(string first, string second, StringComparison comparisonType) =>
Test.CustomException(first,
second,
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustBeTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustBeTests.cs
index 81b2285..6466858 100644
--- a/Code/Light.GuardClauses.Tests/StringAssertions/MustBeTests.cs
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustBeTests.cs
@@ -50,7 +50,8 @@ public static void StringsNotEqualIgnoreWhiteSpace(string first, string second,
public static void CustomException() =>
Test.CustomException("Foo",
"Bar",
- (x, y, exceptionFactory) => x.MustBe(y, StringComparison.Ordinal, exceptionFactory));
+ StringComparison.Ordinal,
+ (x, y, ct, exceptionFactory) => x.MustBe(y, ct, exceptionFactory));
[Fact]
public static void CustomMessage() =>
@@ -60,7 +61,8 @@ public static void CustomMessage() =>
public static void CustomExceptionIgnoreWhiteSpace() =>
Test.CustomException("Foo",
" foo",
- (x, y, exceptionFactory) => x.MustBe(y, StringComparisonType.OrdinalIgnoreWhiteSpace, exceptionFactory));
+ StringComparisonType.OrdinalIgnoreWhiteSpace,
+ (x, y, ct, exceptionFactory) => x.MustBe(y, ct, exceptionFactory));
[Fact]
public static void CustomMessageIgnoreWhiteSpace() =>
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustContainTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustContainTests.cs
index 70a594d..3912163 100644
--- a/Code/Light.GuardClauses.Tests/StringAssertions/MustContainTests.cs
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustContainTests.cs
@@ -79,7 +79,6 @@ public static void CustomException(string first, string second) =>
[InlineData("Foo", "foo", StringComparison.Ordinal)]
[InlineData(null, "Bar", StringComparison.OrdinalIgnoreCase)]
[InlineData("Baz", null, StringComparison.CurrentCulture)]
- [InlineData("Qux", "Qux", (StringComparison) 42)]
public static void CustomExceptionCustomSearch(string x, string y, StringComparison comparison) =>
Test.CustomException(x,
y,
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustEndWithTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustEndWithTests.cs
new file mode 100644
index 0000000..776665d
--- /dev/null
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustEndWithTests.cs
@@ -0,0 +1,73 @@
+using System;
+using FluentAssertions;
+using Light.GuardClauses.Exceptions;
+using Xunit;
+
+namespace Light.GuardClauses.Tests.StringAssertions;
+
+public static class MustEndWithTests
+{
+ [Theory]
+ [InlineData("Foo", "Bar")]
+ [InlineData("When you play the game of thrones you win, or you die.", "you live")]
+ public static void DoesNotEndWith(string x, string y)
+ {
+ var act = () => x.MustEndWith(y);
+
+ var exception = act.Should().Throw().Which;
+ exception.Message.Should().StartWith($"{nameof(x)} must end with \"{y}\" (CurrentCulture), but it actually is \"{x}\".");
+ exception.ParamName.Should().BeSameAs(nameof(x));
+ }
+
+ [Theory]
+ [InlineData("FooBar", "Bar", StringComparison.Ordinal)]
+ [InlineData("12345678", "5678", StringComparison.InvariantCultureIgnoreCase)]
+ public static void EndsWith(string x, string y, StringComparison comparisonType) =>
+ x.MustEndWith(y, comparisonType).Should().BeSameAs(x);
+
+ [Fact]
+ public static void ParameterNull()
+ {
+ var act = () => ((string) null).MustEndWith("Foo");
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public static void ValueNull()
+ {
+ var act = () => "Foo".MustEndWith(null!);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public static void CustomMessage() =>
+ Test.CustomMessage(message => "Foo".MustEndWith("Bar", message: message));
+
+ [Fact]
+ public static void CustomMessageParameterNull() =>
+ Test.CustomMessage(message => ((string) null).MustEndWith("Bar", message: message));
+
+ [Fact]
+ public static void EndsWithCustomException() =>
+ "Foo".MustEndWith("o", (_, _) => new Exception()).Should().Be("Foo");
+
+ [Fact]
+ public static void EndsWithCustomExceptionAndComparisonType() =>
+ "Foo".MustEndWith("O", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()).Should().Be("Foo");
+
+ [Theory]
+ [InlineData("Foo", "Bar")]
+ [InlineData("Foo", null)]
+ [InlineData(null, "Baz")]
+ public static void CustomException(string first, string second) =>
+ Test.CustomException(first, second, (s1, s2, exceptionFactory) => s1.MustEndWith(s2, exceptionFactory));
+
+ [Theory]
+ [InlineData("Foo", "Bar", StringComparison.Ordinal)]
+ [InlineData(null, "Bar", StringComparison.Ordinal)]
+ [InlineData("Baz", null, StringComparison.Ordinal)]
+ public static void CustomExceptionWithComparisonType(string a, string b, StringComparison comparisonType) =>
+ Test.CustomException(a, b, comparisonType, (s1, s2, ct, exceptionFactory) => s1.MustEndWith(s2, ct, exceptionFactory));
+}
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeSubstringOfTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeSubstringOfTests.cs
index 8c49034..aac5a97 100644
--- a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeSubstringOfTests.cs
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeSubstringOfTests.cs
@@ -93,7 +93,6 @@ public static void CustomException(string first, string second) =>
[InlineData("Full of Possibilities", "Death is so terribly final, while life is full of possibilities", StringComparison.OrdinalIgnoreCase)]
[InlineData(null, "Foo", StringComparison.Ordinal)]
[InlineData("Bar", null, StringComparison.CurrentCulture)]
- [InlineData("Baz", "Qux", (StringComparison) (-14))]
public static void CustomExceptionCustomComparison(string a, string b, StringComparison comparisonType) =>
Test.CustomException(a,
b,
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeTests.cs
index 6d6f28a..b412c7c 100644
--- a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeTests.cs
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotBeTests.cs
@@ -56,7 +56,8 @@ public static void CustomException() =>
public static void CustomExceptionIgnoreWhiteSpace() =>
Test.CustomException("Foo",
" Foo",
- (x, y, exceptionFactory) => x.MustNotBe(y, StringComparisonType.OrdinalIgnoreWhiteSpace, exceptionFactory));
+ StringComparisonType.OrdinalIgnoreWhiteSpace,
+ (x, y, ct, exceptionFactory) => x.MustNotBe(y, ct, exceptionFactory));
[Fact]
public static void CustomMessage() =>
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotContainTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotContainTests.cs
index e7511fc..923cc49 100644
--- a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotContainTests.cs
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotContainTests.cs
@@ -64,7 +64,6 @@ public static void CustomException(string first, string second) =>
[InlineData("Foo", "O", StringComparison.OrdinalIgnoreCase)]
[InlineData("Bar", null, StringComparison.CurrentCulture)]
[InlineData(null, "Baz", StringComparison.CurrentCultureIgnoreCase)]
- [InlineData("Qux", "Quux", (StringComparison) 504)]
public static void CustomExceptionCustomSearch(string first, string second, StringComparison comparisonType) =>
Test.CustomException(first,
second,
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotEndWithTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotEndWithTests.cs
new file mode 100644
index 0000000..d950826
--- /dev/null
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotEndWithTests.cs
@@ -0,0 +1,73 @@
+using System;
+using FluentAssertions;
+using Light.GuardClauses.Exceptions;
+using Xunit;
+
+namespace Light.GuardClauses.Tests.StringAssertions;
+
+public static class MustNotEndWithTests
+{
+ [Theory]
+ [InlineData("FooBar", "Bar")]
+ [InlineData("When you play the game of thrones you win, or you die.", "die.")]
+ public static void DoesEndWith(string x, string y)
+ {
+ var act = () => x.MustNotEndWith(y);
+
+ var exception = act.Should().Throw().Which;
+ exception.Message.Should().StartWith($"{nameof(x)} must not end with \"{y}\" (CurrentCulture), but it actually is \"{x}\".");
+ exception.ParamName.Should().BeSameAs(nameof(x));
+ }
+
+ [Theory]
+ [InlineData("Foo", "Bar", StringComparison.Ordinal)]
+ [InlineData("12345", "1234", StringComparison.InvariantCultureIgnoreCase)]
+ public static void DoesNotEndWith(string x, string y, StringComparison comparisonType) =>
+ x.MustNotEndWith(y, comparisonType).Should().BeSameAs(x);
+
+ [Fact]
+ public static void ParameterNull()
+ {
+ var act = () => ((string) null).MustNotEndWith("Foo");
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public static void ValueNull()
+ {
+ var act = () => "Foo".MustNotEndWith(null!);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public static void CustomMessage() =>
+ Test.CustomMessage(message => "FooBar".MustNotEndWith("Bar", message: message));
+
+ [Fact]
+ public static void CustomMessageParameterNull() =>
+ Test.CustomMessage(message => ((string) null).MustNotEndWith("Bar", message: message));
+
+ [Fact]
+ public static void DoesNotEndWithCustomException() =>
+ "Foo".MustNotEndWith("r", (_, _) => new Exception()).Should().Be("Foo");
+
+ [Fact]
+ public static void DoesNotEndWithCustomExceptionAndComparisonType() =>
+ "Foo".MustNotEndWith("R", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()).Should().Be("Foo");
+
+ [Theory]
+ [InlineData("FooBar", "Bar")]
+ [InlineData("Foo", null)]
+ [InlineData(null, "Baz")]
+ public static void CustomException(string first, string second) =>
+ Test.CustomException(first, second, (s1, s2, exceptionFactory) => s1.MustNotEndWith(s2, exceptionFactory));
+
+ [Theory]
+ [InlineData("FooBar", "Bar", StringComparison.Ordinal)]
+ [InlineData(null, "Bar", StringComparison.Ordinal)]
+ [InlineData("Baz", null, StringComparison.Ordinal)]
+ public static void CustomExceptionWithComparisonType(string a, string b, StringComparison comparisonType) =>
+ Test.CustomException(a, b, comparisonType, (s1, s2, ct, exceptionFactory) => s1.MustNotEndWith(s2, ct, exceptionFactory));
+}
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustNotStartWithTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotStartWithTests.cs
new file mode 100644
index 0000000..5ad5160
--- /dev/null
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustNotStartWithTests.cs
@@ -0,0 +1,85 @@
+using System;
+using FluentAssertions;
+using Light.GuardClauses.Exceptions;
+using Xunit;
+
+namespace Light.GuardClauses.Tests.StringAssertions;
+
+public static class MustNotStartWithTests
+{
+ [Theory]
+ [InlineData("Bar", "Foo")]
+ [InlineData("When you play the game of thrones you win, or you die.", "Love and peace")]
+ public static void DoesNotStartWith(string x, string y) =>
+ x.MustNotStartWith(y).Should().BeSameAs(x);
+
+ [Theory]
+ [InlineData("FooBar", "Foo")]
+ [InlineData("12345678", "1234")]
+ public static void StartsWith(string x, string y)
+ {
+ var act = () => x.MustNotStartWith(y);
+
+ var exception = act.Should().Throw().Which;
+ exception.Message.Should().StartWith($"{nameof(x)} must not start with \"{y}\" (CurrentCulture), but it actually is \"{x}\"");
+ exception.ParamName.Should().BeSameAs(nameof(x));
+ }
+
+ [Theory]
+ [InlineData("FooBar", "Foo", StringComparison.Ordinal)]
+ [InlineData("12345678", "1234", StringComparison.InvariantCultureIgnoreCase)]
+ public static void StartsWithComparisonType(string x, string y, StringComparison comparisonType)
+ {
+ var act = () => x.MustNotStartWith(y, comparisonType);
+
+ var exception = act.Should().Throw().Which;
+ exception.Message.Should().StartWith($"{nameof(x)} must not start with \"{y}\" ({comparisonType}), but it actually is \"{x}\"");
+ exception.ParamName.Should().BeSameAs(nameof(x));
+ }
+
+ [Fact]
+ public static void ParameterNull()
+ {
+ var act = () => ((string)null).MustNotStartWith("Foo");
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public static void ValueNull()
+ {
+ var act = () => "Foo".MustNotStartWith(null!);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public static void CustomMessage() =>
+ Test.CustomMessage(message => "FooBar".MustNotStartWith("Foo", message: message));
+
+ [Fact]
+ public static void CustomMessageParameterNull() =>
+ Test.CustomMessage(message => ((string)null).MustNotStartWith("Bar", message: message));
+
+ [Fact]
+ public static void NotStartsWithCustomException() =>
+ "Bar".MustNotStartWith("Foo", (_, _) => new Exception()).Should().Be("Bar");
+
+ [Fact]
+ public static void NotStartsWithCustomExceptionAndComparisonType() =>
+ "Bar".MustNotStartWith("foo", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()).Should().Be("Bar");
+
+ [Theory]
+ [InlineData("Foo", "Foo")]
+ [InlineData("Foo", null)]
+ [InlineData(null, "Baz")]
+ public static void CustomException(string first, string second) =>
+ Test.CustomException(first, second, (s1, s2, exceptionFactory) => s1.MustNotStartWith(s2, exceptionFactory));
+
+ [Theory]
+ [InlineData("Foo", "foo", StringComparison.OrdinalIgnoreCase)]
+ [InlineData(null, "Bar", StringComparison.Ordinal)]
+ [InlineData("Baz", null, StringComparison.Ordinal)]
+ public static void CustomExceptionWithComparisonType(string a, string b, StringComparison comparisonType) =>
+ Test.CustomException(a, b, comparisonType, (s1, s2, ct, exceptionFactory) => s1.MustNotStartWith(s2, ct, exceptionFactory));
+}
diff --git a/Code/Light.GuardClauses.Tests/StringAssertions/MustStartWithTests.cs b/Code/Light.GuardClauses.Tests/StringAssertions/MustStartWithTests.cs
new file mode 100644
index 0000000..34d1237
--- /dev/null
+++ b/Code/Light.GuardClauses.Tests/StringAssertions/MustStartWithTests.cs
@@ -0,0 +1,73 @@
+using System;
+using FluentAssertions;
+using Light.GuardClauses.Exceptions;
+using Xunit;
+
+namespace Light.GuardClauses.Tests.StringAssertions;
+
+public static class MustStartWithTests
+{
+ [Theory]
+ [InlineData("Foo", "Bar")]
+ [InlineData("When you play the game of thrones you win, or you die. There is no middle ground.", "Love and peace")]
+ public static void DoesNotStartWith(string x, string y)
+ {
+ var act = () => x.MustStartWith(y);
+
+ var exception = act.Should().Throw().Which;
+ exception.Message.Should().StartWith($"{nameof(x)} must start with \"{y}\" (CurrentCulture), but it actually is \"{x}\".");
+ exception.ParamName.Should().BeSameAs(nameof(x));
+ }
+
+ [Theory]
+ [InlineData("FooBar", "Foo", StringComparison.Ordinal)]
+ [InlineData("12345678", "1234", StringComparison.InvariantCultureIgnoreCase)]
+ public static void StartsWith(string x, string y, StringComparison comparisonType) =>
+ x.MustStartWith(y, comparisonType).Should().BeSameAs(x);
+
+ [Fact]
+ public static void ParameterNull()
+ {
+ var act = () => ((string) null).MustStartWith("Foo");
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public static void ValueNull()
+ {
+ var act = () => "Foo".MustStartWith(null!);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public static void CustomMessage() =>
+ Test.CustomMessage(message => "Foo".MustStartWith("Bar", message: message));
+
+ [Fact]
+ public static void CustomMessageParameterNull() =>
+ Test.CustomMessage(message => ((string) null).MustStartWith("Bar", message: message));
+
+ [Fact]
+ public static void StartsWithCustomException() =>
+ "Foo".MustStartWith("F", (_, _) => new Exception()).Should().Be("Foo");
+
+ [Fact]
+ public static void StartsWithCustomExceptionAndComparisonType() =>
+ "Foo".MustStartWith("f", StringComparison.OrdinalIgnoreCase, (_, _, _) => new Exception()).Should().Be("Foo");
+
+ [Theory]
+ [InlineData("Foo", "Bar")]
+ [InlineData("Foo", null)]
+ [InlineData(null, "Baz")]
+ public static void CustomException(string first, string second) =>
+ Test.CustomException(first, second, (s1, s2, exceptionFactory) => s1.MustStartWith(s2, exceptionFactory));
+
+ [Theory]
+ [InlineData("Foo", "Bar", StringComparison.Ordinal)]
+ [InlineData(null, "Bar", StringComparison.Ordinal)]
+ [InlineData("Baz", null, StringComparison.Ordinal)]
+ public static void CustomExceptionWithComparisonType(string a, string b, StringComparison comparisonType) =>
+ Test.CustomException(a, b, comparisonType, (s1, s2, ct, exceptionFactory) => s1.MustStartWith(s2, ct, exceptionFactory));
+}
\ No newline at end of file
diff --git a/Code/Light.GuardClauses.sln.DotSettings b/Code/Light.GuardClauses.sln.DotSettings
index 14c11e8..47d8c24 100644
--- a/Code/Light.GuardClauses.sln.DotSettings
+++ b/Code/Light.GuardClauses.sln.DotSettings
@@ -249,6 +249,7 @@
True
True
True
+ True
True
True
True
diff --git a/Code/Light.GuardClauses/Check.CommonAssertions.cs b/Code/Light.GuardClauses/Check.CommonAssertions.cs
index 73a6379..0104f58 100644
--- a/Code/Light.GuardClauses/Check.CommonAssertions.cs
+++ b/Code/Light.GuardClauses/Check.CommonAssertions.cs
@@ -3,6 +3,7 @@
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
using Light.GuardClauses.Exceptions;
+using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute;
namespace Light.GuardClauses;
@@ -20,7 +21,7 @@ public static partial class Check
/// Thrown when is null.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")]
- public static T MustNotBeNull([ValidatedNotNull, NoEnumeration] this T? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : class
+ public static T MustNotBeNull([NotNull, ValidatedNotNull, NoEnumeration] this T? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : class
{
if (parameter is null)
Throw.ArgumentNull(parameterName, message);
@@ -35,7 +36,7 @@ public static T MustNotBeNull([ValidatedNotNull, NoEnumeration] this T? param
/// Your custom exception thrown when is null.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")]
- public static T MustNotBeNull([ValidatedNotNull, NoEnumeration] this T? parameter, Func exceptionFactory) where T : class
+ public static T MustNotBeNull([NotNull, ValidatedNotNull, NoEnumeration] this T? parameter, Func exceptionFactory) where T : class
{
if (parameter is null)
Throw.CustomException(exceptionFactory);
@@ -53,7 +54,7 @@ public static T MustNotBeNull([ValidatedNotNull, NoEnumeration] this T? param
/// Thrown when is a value type and the default value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")]
- public static T MustNotBeDefault([ValidatedNotNull] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ public static T MustNotBeDefault([NotNull, ValidatedNotNull] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
{
if (default(T) is null)
{
@@ -64,7 +65,11 @@ public static T MustNotBeDefault([ValidatedNotNull] this T parameter, [Caller
if (EqualityComparer.Default.Equals(parameter, default!))
Throw.ArgumentDefault(parameterName, message);
+
+ // If we end up here, we have a value type which cannot be null
+#pragma warning disable CS8777 // Parameter must have a non-null value when exiting.
return parameter;
+#pragma warning restore CS8777
}
///
@@ -75,7 +80,7 @@ public static T MustNotBeDefault([ValidatedNotNull] this T parameter, [Caller
/// Your custom exception thrown when is the default value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")]
- public static T MustNotBeDefault([ValidatedNotNull] this T parameter, Func exceptionFactory)
+ public static T MustNotBeDefault([NotNull, ValidatedNotNull] this T parameter, Func exceptionFactory)
{
if (default(T) is null)
{
@@ -86,7 +91,11 @@ public static T MustNotBeDefault([ValidatedNotNull] this T parameter, Func.Default.Equals(parameter, default!))
Throw.CustomException(exceptionFactory);
+
+ // If we end up here, we have a value type which cannot be null
+#pragma warning disable CS8777 // Parameter must have a non-null value when exiting.
return parameter;
+#pragma warning restore CS8777
}
@@ -101,10 +110,15 @@ public static T MustNotBeDefault([ValidatedNotNull] this T parameter, FuncThrown when is a reference type and is null.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")]
- public static T MustNotBeNullReference([ValidatedNotNull, NoEnumeration] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ public static T MustNotBeNullReference([NotNull, ValidatedNotNull, NoEnumeration] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
{
if (default(T) != null)
+ {
+ // If we end up here, parameter cannot be null
+#pragma warning disable CS8777 // Parameter must have a non-null value when exiting.
return parameter;
+#pragma warning restore CS8777 // Parameter must have a non-null value when exiting.
+ }
if (parameter is null)
Throw.ArgumentNull(parameterName, message);
@@ -121,10 +135,15 @@ public static T MustNotBeNullReference([ValidatedNotNull, NoEnumeration] this
/// Your custom exception thrown when is a reference type and is null.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")]
- public static T MustNotBeNullReference([ValidatedNotNull, NoEnumeration] this T parameter, Func exceptionFactory)
+ public static T MustNotBeNullReference([NotNull, ValidatedNotNull, NoEnumeration] this T parameter, Func exceptionFactory)
{
if (default(T) != null)
+ {
+ // If we end up here, parameter cannot be null
+#pragma warning disable CS8777 // Parameter must have a non-null value when exiting.
return parameter;
+#pragma warning restore CS8777 // Parameter must have a non-null value when exiting.
+ }
if (parameter is null)
Throw.CustomException(exceptionFactory);
@@ -141,7 +160,7 @@ public static T MustNotBeNullReference([ValidatedNotNull, NoEnumeration] this
/// Thrown when is null.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")]
- public static T MustBeOfType([ValidatedNotNull, NoEnumeration] this object? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ public static T MustBeOfType([NotNull, ValidatedNotNull, NoEnumeration] this object? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
{
if (parameter.MustNotBeNull(parameterName, message) is T castValue)
return castValue;
@@ -158,7 +177,7 @@ public static T MustBeOfType([ValidatedNotNull, NoEnumeration] this object? p
/// Your custom exception thrown when cannot be cast to .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")]
- public static T MustBeOfType([ValidatedNotNull, NoEnumeration] this object? parameter, Func