├── icon_1280.png ├── media ├── 144.png ├── 256.png ├── 512.png ├── 72.png ├── 96.png ├── fav16.ico ├── favicon.ico ├── logotype 1024.eps ├── logotype 1024.pdf ├── logotype 1024.png ├── 48.svg ├── 72.svg ├── 96.svg ├── 144.svg ├── 256.svg ├── 512.svg └── logotype 1024.svg ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── stale.yaml └── workflows │ ├── codeql-analysis.yml │ ├── publish.yml │ └── build.yml ├── src └── GuardClauses │ ├── icon.png │ ├── ValidatedNotNullAttribute.cs │ ├── Guard.cs │ ├── GuardAgainstExpressionExtensions.cs │ ├── Exceptions │ └── NotFoundException.cs │ ├── GuardClauses.csproj │ ├── GuardAgainstInvalidFormatExtensions.cs │ ├── GuardAgainstNotFoundExtensions.cs │ ├── GuardAgainstZeroExtensions.cs │ └── GuardAgainstOutOfRangeExtensions.cs ├── test └── GuardClauses.UnitTests │ ├── GlobalUsings.cs │ ├── NamespaceSeparate │ └── ExtendingGuard.cs │ ├── GuardAgainstFooExtension.cs │ ├── GuardClauses.UnitTests.csproj │ ├── GuardAgainstNotFound.cs │ ├── GuardAgainstInvalidFormatTests.cs │ ├── GuardAgainstOutOfRangeForInt.cs │ ├── GuardAgainstOutOfRangeForUint.cs │ ├── GuardAgainstOutOfRangeForShort.cs │ ├── GuardAgainstExpression.cs │ ├── GuardAgainstOutOfRangeForFloat.cs │ ├── GuardAgainstOutOfRangeForDouble.cs │ ├── GuardAgainstOutOfRangeForDecimal.cs │ ├── GuardAgainstNull.cs │ ├── GuardAgainstOutOfRangeForIComparable.cs │ ├── GuardAgainstOutOfRangeForDateTime.cs │ ├── GuardAgainstDefault.cs │ ├── GuardAgainstNullOrInvalidInput.cs │ ├── GuardAgainstOutOfRangeForInvalidInput.cs │ ├── GuardAgainstOutOfSQLDateRange.cs │ ├── GuardAgainstNullOrWhiteSpace.cs │ ├── GuardAgainstOutOfRangeForTimeSpan.cs │ ├── GuardAgainstOutOfRangeForEnumerableInt.cs │ ├── GuardAgainstOutOfRangeForEnumerableShort.cs │ ├── GuardAgainstOutOfRangeForEnumerableLong.cs │ ├── GuardAgainstOutOfRangeForEnum.cs │ ├── GuardAgainstOutOfRangeForEnumerableFloat.cs │ ├── GuardAgainstOutOfRangeForEnumerableDecimal.cs │ ├── GuardAgainstOutOfRangeForEnumerableDouble.cs │ ├── GuardAgainstOutOfRangeForEnumerableTimeSpan.cs │ └── GuardAgainstNullOrEmpty.cs ├── Directory.Build.props ├── nuget.txt ├── LICENSE ├── GuardClauses.sln ├── CONTRIBUTING.md ├── azure-pipelines.yml.bak ├── README.md ├── .gitignore └── .editorconfig /icon_1280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/icon_1280.png -------------------------------------------------------------------------------- /media/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/144.png -------------------------------------------------------------------------------- /media/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/256.png -------------------------------------------------------------------------------- /media/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/512.png -------------------------------------------------------------------------------- /media/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/72.png -------------------------------------------------------------------------------- /media/96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/96.png -------------------------------------------------------------------------------- /media/fav16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/fav16.ico -------------------------------------------------------------------------------- /media/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/favicon.ico -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ardalis 4 | -------------------------------------------------------------------------------- /media/logotype 1024.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/logotype 1024.eps -------------------------------------------------------------------------------- /media/logotype 1024.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/logotype 1024.pdf -------------------------------------------------------------------------------- /media/logotype 1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/media/logotype 1024.png -------------------------------------------------------------------------------- /src/GuardClauses/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/GuardClauses/HEAD/src/GuardClauses/icon.png -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | 2 | blank_issues_enabled: false 3 | contact_links: 4 | - name: Question 5 | url: https://github.com/ardalis/GuardClauses/discussions/categories/q-a 6 | about: Please ask and answer questions in the Discussions Q&A tab. 7 | 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | --- 5 | 6 | 7 | 8 | - .NET SDK Version: 9 | 10 | Steps to Reproduce: 11 | 12 | 1. 13 | 2. 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/GuardClauses/ValidatedNotNullAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Ardalis.GuardClauses 4 | { 5 | /// 6 | /// Add to methods that check input for null and throw if the input is null. 7 | /// 8 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] 9 | public sealed class ValidatedNotNullAttribute : Attribute { } 10 | } 11 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using System; 2 | global using System.Collections; 3 | global using System.Collections.Generic; 4 | global using System.ComponentModel; 5 | global using System.Data.SqlTypes; 6 | global using System.Linq; 7 | global using System.Runtime.CompilerServices; 8 | global using Ardalis.GuardClauses; 9 | global using Microsoft.VisualBasic; 10 | global using Xunit; 11 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | # default location of `.github/workflows` 5 | directory: "/" 6 | open-pull-requests-limit: 10 7 | schedule: 8 | interval: "weekly" 9 | 10 | - package-ecosystem: nuget 11 | directory: "/" 12 | schedule: 13 | interval: daily 14 | open-pull-requests-limit: 10 15 | ignore: 16 | - dependency-name: altcover 17 | versions: 18 | - 8.1.819 -------------------------------------------------------------------------------- /nuget.txt: -------------------------------------------------------------------------------- 1 | Checklist: 2 | https://ardalis.com/nuget-publication-checklist 3 | 4 | -- Don't forget to update the .csproj file with version and release notes! 5 | 6 | dotnet pack -c release /p:Version=1.0.0 7 | 8 | -- from /bin/release folder 9 | dotnet nuget push -s https://www.nuget.org/api/v2/package -k Ardalis.GuardClauses.1.0.1.nupkg 10 | 11 | -- can also just add a release in github.com UI 12 | git tag -a v1.2.4 -m "Published 1.2.4 to nuget.org" 13 | 14 | git push --follow-tags 15 | -------------------------------------------------------------------------------- /.github/stale.yaml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/NamespaceSeparate/ExtendingGuard.cs: -------------------------------------------------------------------------------- 1 | // By using the same namespace, the required using for Ardalis.GuardClauses will include custom guards regardless of location. 2 | namespace Ardalis.GuardClauses; 3 | 4 | /// 5 | /// An example Guard extension method. Throws if input is "foo". 6 | /// 7 | public static class FooGuard 8 | { 9 | #if NETSTANDARD || NETFRAMEWORK 10 | public static void Foo(this IGuardClause guardClause, string input, string parameterName) 11 | #else 12 | public static void Foo(this IGuardClause guardClause, string input, [CallerArgumentExpression("input")] string? parameterName = null) 13 | #endif 14 | { 15 | if (input?.ToLower() == "foo") 16 | throw new ArgumentException("Should not have been foo!", parameterName); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: CodeQL Analysis 2 | 3 | on: 4 | # push: 5 | # pull_request: 6 | # 1st of the month only 7 | schedule: 8 | - cron: '0 8 1 * *' 9 | 10 | jobs: 11 | analyze: 12 | name: CodeQL Analysis 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | id: checkout_repo 17 | uses: actions/checkout@v2 18 | 19 | - name: Initialize CodeQL 20 | id: init_codeql 21 | uses: github/codeql-action/init@v2 22 | with: 23 | queries: security-and-quality 24 | 25 | - name: Autobuild 26 | uses: github/codeql-action/autobuild@v2 27 | 28 | - name: Perform CodeQL Analysis 29 | id: analyze_codeql 30 | uses: github/codeql-action/analyze@v2 31 | 32 | # Built with ❤ by [Pipeline Foundation](https://pipeline.foundation) 33 | -------------------------------------------------------------------------------- /src/GuardClauses/Guard.cs: -------------------------------------------------------------------------------- 1 | using JetBrainsNotNullAttribute = JetBrains.Annotations.NotNullAttribute; 2 | 3 | namespace Ardalis.GuardClauses 4 | { 5 | /// 6 | /// Simple interface to provide a generic mechanism to build guard clause extension methods from. 7 | /// 8 | public interface IGuardClause 9 | { 10 | } 11 | 12 | /// 13 | /// An entry point to a set of Guard Clauses defined as extension methods on IGuardClause. 14 | /// 15 | /// See http://www.weeklydevtips.com/004 on Guard Clauses 16 | public class Guard : IGuardClause 17 | { 18 | /// 19 | /// An entry point to a set of Guard Clauses. 20 | /// 21 | [JetBrainsNotNull] public static IGuardClause Against { get; } = new Guard(); 22 | 23 | private Guard() { } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstFooExtension.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstFooExtension 4 | { 5 | [Fact] 6 | public void ThrowsGivenFoo() 7 | { 8 | Assert.Throws(() => Guard.Against.Foo("foo", "aParameterName")); 9 | } 10 | 11 | [Fact] 12 | public void DoesNothingGivenAnythingElse() 13 | { 14 | Guard.Against.Foo("anythingElse", "aParameterName"); 15 | //Guard.Against.Foo(null, "aParameterName"); 16 | } 17 | 18 | [Fact] 19 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvided() 20 | { 21 | string? xyz = "foo"; 22 | 23 | var exception = Assert.Throws(() => Guard.Against.Foo(xyz)); 24 | 25 | Assert.NotNull(exception); 26 | Assert.NotNull(exception.Message); 27 | Assert.Contains($"Should not have been foo! (Parameter '{nameof(xyz)}')", exception.Message); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Steve Smith 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/GuardClauses/GuardAgainstExpressionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JetBrainsNotNullAttribute = JetBrains.Annotations.NotNullAttribute; 3 | 4 | namespace Ardalis.GuardClauses 5 | { 6 | public static partial class GuardClauseExtensions 7 | { 8 | /// 9 | /// Throws an if evaluates to false for given 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// if the evaluates to true 17 | /// 18 | public static T AgainstExpression([JetBrainsNotNull] this IGuardClause guardClause, [JetBrainsNotNull] Func func, T input, string message) where T : struct 19 | { 20 | if (!func(input)) 21 | { 22 | throw new ArgumentException(message); 23 | } 24 | 25 | return input; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardClauses.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | false 6 | 10 7 | 8 | 9 | 10 | 11 | 12 | runtime; build; native; contentfiles; analyzers 13 | all 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish Ardalis.GuardClauses to nuget 2 | on: 3 | push: 4 | branches: 5 | - main # Your default release branch 6 | paths: 7 | - 'src/GuardClauses/**' 8 | jobs: 9 | publish: 10 | name: list Ardalis.GuardClauses on nuget.org 11 | runs-on: windows-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | # Required for a specific dotnet version that doesn't come with ubuntu-latest / windows-latest 16 | # Visit bit.ly/2synnZl to see the list of SDKs that are pre-installed with ubuntu-latest / windows-latest 17 | - name: Setup dotnet 18 | uses: actions/setup-dotnet@v1 19 | with: 20 | dotnet-version: 6.0.x 21 | 22 | # Publish 23 | - name: publish on version change 24 | uses: rohith/publish-nuget@v2 25 | with: 26 | PROJECT_FILE_PATH: src/GuardClauses/GuardClauses.csproj # Relative to repository root 27 | # VERSION_FILE_PATH: Directory.Build.props # Filepath with version info, relative to repository root. Defaults to project file 28 | VERSION_REGEX: (.*)<\/Version> # Regex pattern to extract version info in a capturing group 29 | TAG_COMMIT: true # Flag to enable / disable git tagging 30 | TAG_FORMAT: GuardClauses-v* # Format of the git tag, [*] gets replaced with version 31 | NUGET_KEY: ${{secrets.NUGET_API_KEY}} # nuget.org API key 32 | -------------------------------------------------------------------------------- /src/GuardClauses/Exceptions/NotFoundException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Ardalis.GuardClauses 4 | { 5 | /// 6 | /// Represents error that occurs if a queried object by a particular key is null (not found). 7 | /// 8 | public class NotFoundException : Exception 9 | { 10 | /// 11 | /// Initializes a new instance of the NotFoundException class with a specified name of the queried object and its key. 12 | /// 13 | /// Name of the queried object. 14 | /// The value by which the object is queried. 15 | public NotFoundException(string key, string objectName) 16 | : base($"Queried object {objectName} was not found, Key: {key}") 17 | { 18 | } 19 | 20 | /// 21 | /// Initializes a new instance of the NotFoundException class with a specified name of the queried object, its key, 22 | /// and the exception that is the cause of this exception. 23 | /// 24 | /// Name of the queried object. 25 | /// The value by which the object is queried. 26 | /// The exception that is the cause of the current exception. 27 | public NotFoundException(string key, string objectName, Exception innerException) 28 | : base($"Queried object {objectName} was not found, Key: {key}", innerException) 29 | { 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: .NET Core 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ main ] 7 | pull_request: 8 | branches: [ main ] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Setup .NET Core 18 | uses: actions/setup-dotnet@v1 19 | with: 20 | dotnet-version: '6.0.x' 21 | - name: Install dependencies 22 | run: dotnet restore 23 | - name: Build 24 | run: dotnet build --configuration Release --no-restore 25 | 26 | # See https://josh-ops.com/posts/github-code-coverage/ 27 | # Add coverlet.collector nuget package to test project - 'dotnet add package coverlet 28 | - name: Test 29 | run: dotnet test --no-restore --verbosity normal --collect:"XPlat Code Coverage" --logger trx --results-directory coverage 30 | 31 | - name: Copy Coverage To Predictable Location 32 | run: cp coverage/*/coverage.cobertura.xml coverage/coverage.cobertura.xml 33 | 34 | - name: Code Coverage Summary Report 35 | uses: irongut/CodeCoverageSummary@v1.2.0 36 | # uses: joshjohanning/CodeCoverageSummary@v1.0.2 37 | with: 38 | filename: coverage/coverage.cobertura.xml 39 | badge: true 40 | format: 'markdown' 41 | output: 'both' 42 | 43 | - name: Add Coverage PR Comment 44 | uses: marocchino/sticky-pull-request-comment@v2 45 | if: github.event_name == 'pull_request' 46 | with: 47 | recreate: true 48 | path: code-coverage-results.md 49 | -------------------------------------------------------------------------------- /GuardClauses.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.32112.339 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GuardClauses", "src\GuardClauses\GuardClauses.csproj", "{2A1AA760-8929-433C-BC27-5513F0289842}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D0831547-3E6D-4E0E-8CB0-F7DA27F4E8EA}" 9 | ProjectSection(SolutionItems) = preProject 10 | .editorconfig = .editorconfig 11 | Directory.Build.props = Directory.Build.props 12 | README.md = README.md 13 | EndProjectSection 14 | EndProject 15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GuardClauses.UnitTests", "test\GuardClauses.UnitTests\GuardClauses.UnitTests.csproj", "{B84F450E-7778-48C8-A9DB-CCD5EE80E92E}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {2A1AA760-8929-433C-BC27-5513F0289842}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {2A1AA760-8929-433C-BC27-5513F0289842}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {2A1AA760-8929-433C-BC27-5513F0289842}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {2A1AA760-8929-433C-BC27-5513F0289842}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {B84F450E-7778-48C8-A9DB-CCD5EE80E92E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {B84F450E-7778-48C8-A9DB-CCD5EE80E92E}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {B84F450E-7778-48C8-A9DB-CCD5EE80E92E}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {B84F450E-7778-48C8-A9DB-CCD5EE80E92E}.Release|Any CPU.Build.0 = Release|Any CPU 31 | EndGlobalSection 32 | GlobalSection(SolutionProperties) = preSolution 33 | HideSolutionNode = FALSE 34 | EndGlobalSection 35 | GlobalSection(ExtensibilityGlobals) = postSolution 36 | SolutionGuid = {46896DE3-41B8-442F-A6FB-6AC9F11CCBCE} 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Ardalis.GuardClauses 2 | 3 | We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: 4 | 5 | - Reporting a bug 6 | - Discussing the current state of the code 7 | - Submitting a fix 8 | - Proposing new features 9 | 10 | ## We Develop with GitHub 11 | 12 | Obviously... 13 | 14 | ## We Use Pull Requests 15 | 16 | Mostly. But pretty much exclusively for non-maintainers. You'll need to fork the repo in order to submit a pull request. Here are the basic steps: 17 | 18 | 1. Fork the repo and create your branch from `main`. 19 | 2. If you've added code that should be tested, add tests. 20 | 3. If you've changed APIs, update the documentation. 21 | 4. Ensure the test suite passes. 22 | 5. Make sure your code lints. 23 | 6. Issue that pull request! 24 | 25 | - [Pull Request Check List](https://ardalis.com/github-pull-request-checklist/) 26 | - [Resync your fork with this upstream repo](https://ardalis.com/syncing-a-fork-of-a-github-repository-with-upstream/) 27 | 28 | ## Ask before adding a pull request 29 | 30 | You can just add a pull request out of the blue if you want, but it's much better etitquette (and more likely to be accepted) if you open a new issue or comment in an existing issue stating you'd like to make a pull request. 31 | 32 | ## Getting Started 33 | 34 | Look for [issues marked with 'help wanted'](https://github.com/ardalis/guardclauses/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) to find good places to start contributing. 35 | 36 | ## Any contributions you make will be under the MIT Software License 37 | 38 | In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers this project. 39 | 40 | ## Report bugs using Github's [issues](https://github.com/ardalis/guardclauses/issues) 41 | 42 | We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/ardalis/GuardClauses/issues/new/choose); it's that easy! 43 | 44 | ## Sponsor us 45 | 46 | If you don't have the time or expertise to contribute code, you can still support us by [sponsoring](https://github.com/sponsors/ardalis). 47 | -------------------------------------------------------------------------------- /src/GuardClauses/GuardClauses.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | LICENSE 4 | 5 | 6 | 7 | 8 | 9 | netstandard2.0;net451;net60 10 | Ardalis.GuardClauses 11 | Ardalis.GuardClauses 12 | true 13 | Steve Smith (@ardalis) 14 | Ardalis.com 15 | https://github.com/ardalis/guardclauses 16 | A simple package by @ardalis and @nimblepros with guard clause helper methods. See docs for how to extend using your own extension methods defined in your project. 17 | A simple package with guard clause helper methods. See docs for how to extend using your own extension methods. 18 | https://github.com/ardalis/guardclauses 19 | guard clause clauses assert assertion 20 | 21 | Add more support for CallerArgumentExpression. 22 | 23 | 4.0.1 24 | Ardalis.GuardClauses 25 | icon.png 26 | true 27 | true 28 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 29 | 30 | 31 | bin\$(Configuration)\Ardalis.GuardClauses.xml 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /media/48.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /media/72.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /media/96.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /media/144.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /media/256.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstNotFound.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstNotFound 4 | { 5 | [Fact] 6 | public void DoesNothingGivenNonNullValue() 7 | { 8 | Guard.Against.NotFound("mykey", "", "string"); 9 | Guard.Against.NotFound(1, 1, "int"); 10 | Guard.Against.NotFound(1, Guid.Empty, "guid"); 11 | Guard.Against.NotFound(Guid.Empty, DateTime.Now, "datetime"); 12 | Guard.Against.NotFound(1, new Object(), "object"); 13 | } 14 | 15 | [Fact] 16 | public void ThrowsGivenNullValue() 17 | { 18 | object obj = null!; 19 | Assert.Throws(() => Guard.Against.NotFound(1, obj, "null")); 20 | } 21 | 22 | [Fact] 23 | public void ReturnsExpectedValueWhenGivenNonNullValue() 24 | { 25 | Assert.Equal("", Guard.Against.NotFound("mykey", "", "string")); 26 | Assert.Equal(1, Guard.Against.NotFound(1, 1, "int")); 27 | 28 | var guid = Guid.Empty; 29 | Assert.Equal(guid, Guard.Against.NotFound(1, guid, "guid")); 30 | 31 | var now = DateTime.Now; 32 | Assert.Equal(now, Guard.Against.NotFound(1, now, "datetime")); 33 | 34 | var obj = new Object(); 35 | Assert.Equal(obj, Guard.Against.NotFound(1, obj, "object")); 36 | } 37 | 38 | [Fact] 39 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvidedGivenStringValue() 40 | { 41 | string? xyz = null; 42 | var key = "mykey"; 43 | 44 | var exception = Assert.Throws(() => Guard.Against.NotFound(key, xyz)); 45 | 46 | Assert.NotNull(exception); 47 | Assert.NotNull(exception.Message); 48 | Assert.Contains($"Queried object {nameof(xyz)} was not found, Key: {key}", exception.Message); 49 | 50 | //Assert.Equal("", Guard.Against.NotFound("mykey", "", "string")); 51 | //Assert.Equal(1, Guard.Against.NotFound(1, 1, "int")); 52 | 53 | //var guid = Guid.Empty; 54 | //Assert.Equal(guid, Guard.Against.NotFound(1, guid, "guid")); 55 | 56 | //var now = DateTime.Now; 57 | //Assert.Equal(now, Guard.Against.NotFound(1, now, "datetime")); 58 | 59 | //var obj = new Object(); 60 | //Assert.Equal(obj, Guard.Against.NotFound(1, obj, "object")); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstInvalidFormatTests.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstInvalidFormatTests 4 | { 5 | [Theory] 6 | [InlineData("12345",@"\d{1,6}")] 7 | [InlineData("50FA", @"[0-9a-fA-F]{1,6}")] 8 | [InlineData("abfACD", @"[a-fA-F]{1,8}")] 9 | [InlineData("DHSTRY",@"[A-Z]+")] 10 | [InlineData("3498792", @"\d+")] 11 | public void ReturnsExpectedValueGivenCorrectFormat(string input,string regexPattern) 12 | { 13 | var result = Guard.Against.InvalidFormat(input, nameof(input), regexPattern); 14 | Assert.Equal(input, result); 15 | } 16 | 17 | [Theory] 18 | [InlineData("aaa", @"\d{1,6}")] 19 | [InlineData("50XA", @"[0-9a-fA-F]{1,6}")] 20 | [InlineData("2GudhUtG", @"[a-fA-F]+")] 21 | [InlineData("sDHSTRY", @"[A-Z]+")] 22 | [InlineData("3F498792", @"\d+")] 23 | [InlineData("", @"\d+")] 24 | public void ThrowsGivenGivenIncorrectFormat(string input, string regexPattern) 25 | { 26 | Assert.Throws(() => Guard.Against.InvalidFormat(input, nameof(input), regexPattern)); 27 | } 28 | 29 | [Theory] 30 | [InlineData(null, "Input parameterName was not in required format (Parameter 'parameterName')")] 31 | [InlineData("Please provide value in a correct format", "Please provide value in a correct format (Parameter 'parameterName')")] 32 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 33 | { 34 | var exception = Assert.Throws(() => Guard.Against.InvalidFormat("aaa", "parameterName", "^b", customMessage)); 35 | Assert.NotNull(exception); 36 | Assert.NotNull(exception.Message); 37 | Assert.Equal(expectedMessage, exception.Message); 38 | } 39 | 40 | [Theory] 41 | [InlineData(null, null)] 42 | [InlineData(null, "Please provide correct value")] 43 | [InlineData("SomeParameter", null)] 44 | [InlineData("SomeOtherParameter", "Value must be correct")] 45 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 46 | { 47 | var exception = Assert.Throws(() => Guard.Against.InvalidFormat("aaa", expectedParamName, "^b", customMessage)); 48 | Assert.NotNull(exception); 49 | Assert.Equal(expectedParamName, exception.ParamName); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /media/512.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /azure-pipelines.yml.bak: -------------------------------------------------------------------------------- 1 | trigger: 2 | branches: 3 | include: 4 | - master 5 | - refs/tags/* 6 | pr: 7 | - master 8 | 9 | pool: 10 | vmImage: 'windows-2019' 11 | 12 | variables: 13 | buildConfiguration: 'Release' 14 | buildPlatform: 'Any CPU' 15 | solution: '**/*.sln' 16 | 17 | steps: 18 | 19 | # Prepare 20 | - task: DotNetCoreCLI@2 21 | displayName: 'dotnet info' 22 | inputs: 23 | command: custom 24 | custom: '--info' 25 | 26 | - task: DotNetCoreCLI@2 27 | displayName: 'dotnet version' 28 | inputs: 29 | command: custom 30 | custom: '--version' 31 | 32 | - task: NuGetToolInstaller@0 33 | displayName: 'Use NuGet 4.9.3' 34 | inputs: 35 | versionSpec: 4.9.3 36 | 37 | - task: NuGetCommand@2 38 | inputs: 39 | restoreSolution: '$(solution)' 40 | 41 | # Build 42 | - task: VSBuild@1 43 | inputs: 44 | solution: '$(solution)' 45 | platform: '$(buildPlatform)' 46 | configuration: '$(buildConfiguration)' 47 | arguments: '--output $(Build.ArtifactStagingDirectory)' 48 | 49 | # Run tests and create coverage report 50 | - task: DotNetCoreCLI@2 51 | displayName: Test 52 | inputs: 53 | command: test 54 | # projects: '$(Parameters.TestProjects)' 55 | projects: '**/*[Tt]ests/*.csproj' 56 | arguments: '--configuration $(BuildConfiguration) --no-build /p:AltCover=true /p:AltCoverForce=true /p:AltCoverCallContext=[Fact] /p:AltCoverXmlReport=..\target\reports\coverage\coverage.opencover.xml --collect "Code Coverage"' 57 | 58 | - task: Palmmedia.reportgenerator.reportgenerator-build-release-task.reportgenerator@4 59 | displayName: ReportGenerator 60 | inputs: 61 | reports: 'src\target\reports\coverage\coverage.opencover.xml' 62 | targetdir: 'src\target\reports\coverage' 63 | reporttypes: 'HtmlInline_AzurePipelines;Cobertura;Badges' 64 | assemblyfilters: '-xunit*' 65 | 66 | - task: PublishCodeCoverageResults@1 67 | displayName: 'Publish code coverage results' 68 | inputs: 69 | codeCoverageTool: Cobertura 70 | summaryFileLocation: '$(build.sourcesdirectory)\src\target\reports\coverage\Cobertura.xml' 71 | reportDirectory: '$(build.sourcesdirectory)\src\target\reports\coverage' 72 | 73 | - task: CopyFiles@2 74 | displayName: 'Copy *.nupkg Files' 75 | inputs: 76 | SourceFolder: '$(Build.SourcesDirectory)' 77 | Contents: '**\*.nupkg' 78 | TargetFolder: '$(Build.ArtifactStagingDirectory)\Package' 79 | flattenFolders: true 80 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 81 | 82 | # Publish 83 | - task: PublishBuildArtifacts@1 84 | displayName: 'Publish Artifact' 85 | inputs: 86 | PathtoPublish: '$(Build.ArtifactStagingDirectory)\Package' 87 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 88 | 89 | -------------------------------------------------------------------------------- /src/GuardClauses/GuardAgainstInvalidFormatExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using JetBrainsInvokerParameterNameAttribute = JetBrains.Annotations.InvokerParameterNameAttribute; 4 | using JetBrainsNotNullAttribute = JetBrains.Annotations.NotNullAttribute; 5 | using JetBrainsRegexPattern = JetBrains.Annotations.RegexPatternAttribute; 6 | 7 | namespace Ardalis.GuardClauses 8 | { 9 | public static partial class GuardClauseExtensions 10 | { 11 | /// 12 | /// Throws an if doesn't match the . 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// Optional. Custom error message 19 | /// 20 | /// 21 | public static string InvalidFormat([JetBrainsNotNull] this IGuardClause guardClause, 22 | [JetBrainsNotNull] string input, 23 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 24 | [JetBrainsNotNull][JetBrainsRegexPattern] string regexPattern, 25 | string? message = null) 26 | { 27 | var m = Regex.Match(input, regexPattern); 28 | if (!m.Success || input != m.Value) 29 | { 30 | throw new ArgumentException(message ?? $"Input {parameterName} was not in required format", parameterName); 31 | } 32 | 33 | return input; 34 | } 35 | 36 | /// 37 | /// Throws an if doesn't satisfy the function. 38 | /// 39 | /// 40 | /// 41 | /// 42 | /// 43 | /// Optional. Custom error message 44 | /// 45 | /// 46 | /// 47 | public static T InvalidInput([JetBrainsNotNull] this IGuardClause guardClause, [JetBrainsNotNull] T input, [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, Func predicate, string? message = null) 48 | { 49 | if (!predicate(input)) 50 | { 51 | throw new ArgumentException(message ?? $"Input {parameterName} did not satisfy the options", parameterName); 52 | } 53 | 54 | return input; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForInt.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForInt 4 | { 5 | [Theory] 6 | [InlineData(1, 1, 1)] 7 | [InlineData(1, 1, 3)] 8 | [InlineData(2, 1, 3)] 9 | [InlineData(3, 1, 3)] 10 | public void DoesNothingGivenInRangeValue(int input, int rangeFrom, int rangeTo) 11 | { 12 | Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo); 13 | } 14 | 15 | [Theory] 16 | [InlineData(-1, 1, 3)] 17 | [InlineData(0, 1, 3)] 18 | [InlineData(4, 1, 3)] 19 | public void ThrowsGivenOutOfRangeValue(int input, int rangeFrom, int rangeTo) 20 | { 21 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 22 | } 23 | 24 | [Theory] 25 | [InlineData(-1, 3, 1)] 26 | [InlineData(0, 3, 1)] 27 | [InlineData(4, 3, 1)] 28 | public void ThrowsGivenInvalidArgumentValue(int input, int rangeFrom, int rangeTo) 29 | { 30 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 31 | } 32 | 33 | [Theory] 34 | [InlineData(1, 1, 1, 1)] 35 | [InlineData(1, 1, 3, 1)] 36 | [InlineData(2, 1, 3, 2)] 37 | [InlineData(3, 1, 3, 3)] 38 | public void ReturnsExpectedValueGivenInRangeValue(int input, int rangeFrom, int rangeTo, int expected) 39 | { 40 | Assert.Equal(expected, Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 41 | } 42 | 43 | [Theory] 44 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 45 | [InlineData("Int range", "Int range (Parameter 'parameterName')")] 46 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 47 | { 48 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(3, "parameterName", 0, 1, customMessage)); 49 | Assert.NotNull(exception); 50 | Assert.NotNull(exception.Message); 51 | Assert.Equal(expectedMessage, exception.Message); 52 | } 53 | 54 | [Theory] 55 | [InlineData(null, null)] 56 | [InlineData(null, "Please provide correct value")] 57 | [InlineData("SomeParameter", null)] 58 | [InlineData("SomeOtherParameter", "Value must be correct")] 59 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 60 | { 61 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(3, expectedParamName, 0, 1, customMessage)); 62 | Assert.NotNull(exception); 63 | Assert.Equal(expectedParamName, exception.ParamName); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForUint.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForUint 4 | { 5 | [Theory] 6 | [InlineData(1, 1, 1)] 7 | [InlineData(1, 1, 3)] 8 | [InlineData(2, 1, 3)] 9 | [InlineData(3, 1, 3)] 10 | public void DoesNothingGivenInRangeValue(uint input, uint rangeFrom, uint rangeTo) 11 | { 12 | Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo); 13 | } 14 | 15 | [Theory] 16 | [InlineData(0, 1, 3)] 17 | [InlineData(4, 1, 3)] 18 | public void ThrowsGivenOutOfRangeValue(uint input, uint rangeFrom, uint rangeTo) 19 | { 20 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 21 | } 22 | 23 | [Theory] 24 | [InlineData(0, 3, 1)] 25 | [InlineData(1, 3, 1)] 26 | [InlineData(4, 3, 1)] 27 | public void ThrowsGivenInvalidArgumentValue(uint input, uint rangeFrom, uint rangeTo) 28 | { 29 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 30 | } 31 | 32 | [Theory] 33 | [InlineData(1, 1, 1, 1)] 34 | [InlineData(1, 1, 3, 1)] 35 | [InlineData(2, 1, 3, 2)] 36 | [InlineData(3, 1, 3, 3)] 37 | public void ReturnsExpectedValueGivenInRangeValue(uint input, uint rangeFrom, uint rangeTo, uint expected) 38 | { 39 | Assert.Equal(expected, Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 40 | } 41 | 42 | [Theory] 43 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 44 | [InlineData("Uint range", "Uint range (Parameter 'parameterName')")] 45 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 46 | { 47 | var exception = Assert.Throws(() => Guard.Against.OutOfRange((uint)3.0d, "parameterName", (uint)0.0d, (uint)1.0d, customMessage)); 48 | Assert.NotNull(exception); 49 | Assert.NotNull(exception.Message); 50 | Assert.Equal(expectedMessage, exception.Message); 51 | } 52 | 53 | [Theory] 54 | [InlineData(null, null)] 55 | [InlineData(null, "Please provide correct value")] 56 | [InlineData("SomeParameter", null)] 57 | [InlineData("SomeOtherParameter", "Value must be correct")] 58 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 59 | { 60 | var exception = Assert.Throws(() => Guard.Against.OutOfRange((uint)3.0d, expectedParamName, (uint)0.0d, (uint)1.0d, customMessage)); 61 | Assert.NotNull(exception); 62 | Assert.Equal(expectedParamName, exception.ParamName); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForShort.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForShort 4 | { 5 | [Theory] 6 | [InlineData(1, 1, 1)] 7 | [InlineData(1, 1, 3)] 8 | [InlineData(2, 1, 3)] 9 | [InlineData(3, 1, 3)] 10 | public void DoesNothingGivenInRangeValue(short input, short rangeFrom, short rangeTo) 11 | { 12 | Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo); 13 | } 14 | 15 | [Theory] 16 | [InlineData(-1, 1, 3)] 17 | [InlineData(0, 1, 3)] 18 | [InlineData(4, 1, 3)] 19 | public void ThrowsGivenOutOfRangeValue(short input, short rangeFrom, short rangeTo) 20 | { 21 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 22 | } 23 | 24 | [Theory] 25 | [InlineData(-1, 3, 1)] 26 | [InlineData(0, 3, 1)] 27 | [InlineData(4, 3, 1)] 28 | public void ThrowsGivenInvalidArgumentValue(short input, short rangeFrom, short rangeTo) 29 | { 30 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 31 | } 32 | 33 | [Theory] 34 | [InlineData(1, 1, 1, 1)] 35 | [InlineData(1, 1, 3, 1)] 36 | [InlineData(2, 1, 3, 2)] 37 | [InlineData(3, 1, 3, 3)] 38 | public void ReturnsExpectedValueGivenInRangeValue(short input, short rangeFrom, short rangeTo, short expected) 39 | { 40 | Assert.Equal(expected, Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 41 | } 42 | 43 | [Theory] 44 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 45 | [InlineData("Short range", "Short range (Parameter 'parameterName')")] 46 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 47 | { 48 | var exception = Assert.Throws(() => Guard.Against.OutOfRange((short) 3, "parameterName", (short) 0, (short) 1, customMessage)); 49 | Assert.NotNull(exception); 50 | Assert.NotNull(exception.Message); 51 | Assert.Equal(expectedMessage, exception.Message); 52 | } 53 | 54 | [Theory] 55 | [InlineData(null, null)] 56 | [InlineData(null, "Please provide correct value")] 57 | [InlineData("SomeParameter", null)] 58 | [InlineData("SomeOtherParameter", "Value must be correct")] 59 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 60 | { 61 | var exception = Assert.Throws(() => Guard.Against.OutOfRange((short)3, expectedParamName, (short)0, (short)1, customMessage)); 62 | Assert.NotNull(exception); 63 | Assert.Equal(expectedParamName, exception.ParamName); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstExpression.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstExpression 4 | { 5 | public struct CustomStruct 6 | { 7 | public string FieldName { get; set; } 8 | } 9 | 10 | private static IEnumerable GetCustomStruct() 11 | { 12 | yield return new object[] { 13 | new CustomStruct 14 | { 15 | FieldName = "FieldValue" 16 | } 17 | }; 18 | } 19 | 20 | [Theory] 21 | [InlineData(10)] 22 | public void GivenIntegerWhenTheExpressionEvaluatesToTrueDoesNothing(int test) 23 | { 24 | Guard.Against.AgainstExpression((x) => x == 10, test, "Value is not equal to 10"); 25 | } 26 | 27 | [Theory] 28 | [InlineData(10)] 29 | public void GivenIntegerWhenTheExpressionEvaluatesToFalseThrowsException(int test) 30 | { 31 | Assert.Throws(() => Guard.Against.AgainstExpression((x) => x == 5, test, "Value is not equal to 10")); 32 | } 33 | 34 | [Theory] 35 | [InlineData(1.1)] 36 | public void GivenDoubleWhenTheExpressionEvaluatesToTrueDoesNothing(double test) 37 | { 38 | Guard.Against.AgainstExpression((x) => x == 1.1, test, "Value is not equal to 1.1"); 39 | } 40 | 41 | [Theory] 42 | [InlineData(1.1)] 43 | public void GivenDoubleWhenTheExpressionEvaluatesToFalseThrowsException(int test) 44 | { 45 | Assert.Throws(() => Guard.Against.AgainstExpression((x) => x == 5.0, test, "Value is not equal to 1.1")); 46 | } 47 | 48 | [Theory] 49 | [MemberData(nameof(GetCustomStruct))] 50 | public void GivenCustomStructWhenTheExpressionEvaluatesToTrueDoesNothing(CustomStruct test) 51 | { 52 | Guard.Against.AgainstExpression((x) => x.FieldName == "FieldValue", test, "FieldValue is not matching"); 53 | } 54 | 55 | [Theory] 56 | [MemberData(nameof(GetCustomStruct))] 57 | public void GivenCustomStructWhenTheExpressionEvaluatesToFalseThrowsException(CustomStruct test) 58 | { 59 | Assert.Throws(() => Guard.Against.AgainstExpression((x) => x.FieldName == "FailThis", test, "FieldValue is not matching")); 60 | } 61 | 62 | [Theory] 63 | [InlineData(null, "Value does not fall within the expected range.")] 64 | [InlineData("Please provide correct value", "Please provide correct value")] 65 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 66 | { 67 | var exception = Assert.Throws(() => Guard.Against.AgainstExpression(x => x == 1, 2, customMessage)); 68 | Assert.NotNull(exception); 69 | Assert.NotNull(exception.Message); 70 | Assert.Equal(expectedMessage, exception.Message); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForFloat.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForFloat 4 | { 5 | [Theory] 6 | [InlineData(1.0, 1.0, 1.0)] 7 | [InlineData(1.0, 1.0, 3.0)] 8 | [InlineData(2.0, 1.0, 3.0)] 9 | [InlineData(3.0, 1.0, 3.0)] 10 | public void DoesNothingGivenInRangeValue(float input, float rangeFrom, float rangeTo) 11 | { 12 | Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo); 13 | } 14 | 15 | [Theory] 16 | [InlineData(-1.0, 1.0, 3.0)] 17 | [InlineData(0.0, 1.0, 3.0)] 18 | [InlineData(4.0, 1.0, 3.0)] 19 | public void ThrowsGivenOutOfRangeValue(float input, float rangeFrom, float rangeTo) 20 | { 21 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 22 | } 23 | 24 | [Theory] 25 | [InlineData(-1.0, 3.0, 1.0)] 26 | [InlineData(0.0, 3.0, 1.0)] 27 | [InlineData(4.0, 3.0, 1.0)] 28 | public void ThrowsGivenInvalidArgumentValue(float input, float rangeFrom, float rangeTo) 29 | { 30 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 31 | } 32 | 33 | [Theory] 34 | [InlineData(1.0, 1.0, 1.0, 1.0)] 35 | [InlineData(1.0, 1.0, 3.0, 1.0)] 36 | [InlineData(2.0, 1.0, 3.0, 2.0)] 37 | [InlineData(3.0, 1.0, 3.0, 3.0)] 38 | public void ReturnsExpectedValueGivenInRangeValue(float input, float rangeFrom, float rangeTo, float expected) 39 | { 40 | Assert.Equal(expected, Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 41 | } 42 | 43 | [Theory] 44 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 45 | [InlineData("Float range", "Float range (Parameter 'parameterName')")] 46 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 47 | { 48 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0f, "parameterName", 0.0f, 1.0f, customMessage)); 49 | Assert.NotNull(exception); 50 | Assert.NotNull(exception.Message); 51 | Assert.Equal(expectedMessage, exception.Message); 52 | } 53 | 54 | [Theory] 55 | [InlineData(null, null)] 56 | [InlineData(null, "Please provide correct value")] 57 | [InlineData("SomeParameter", null)] 58 | [InlineData("SomeOtherParameter", "Value must be correct")] 59 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 60 | { 61 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0f, expectedParamName, 0.0f, 1.0f, customMessage)); 62 | Assert.NotNull(exception); 63 | Assert.Equal(expectedParamName, exception.ParamName); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDouble.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForDouble 4 | { 5 | [Theory] 6 | [InlineData(1.0, 1.0, 1.0)] 7 | [InlineData(1.0, 1.0, 3.0)] 8 | [InlineData(2.0, 1.0, 3.0)] 9 | [InlineData(3.0, 1.0, 3.0)] 10 | public void DoesNothingGivenInRangeValue(double input, double rangeFrom, double rangeTo) 11 | { 12 | Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo); 13 | } 14 | 15 | [Theory] 16 | [InlineData(-1.0, 1.0, 3.0)] 17 | [InlineData(0.0, 1.0, 3.0)] 18 | [InlineData(4.0, 1.0, 3.0)] 19 | public void ThrowsGivenOutOfRangeValue(double input, double rangeFrom, double rangeTo) 20 | { 21 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 22 | } 23 | 24 | [Theory] 25 | [InlineData(-1.0, 3.0, 1.0)] 26 | [InlineData(0.0, 3.0, 1.0)] 27 | [InlineData(4.0, 3.0, 1.0)] 28 | public void ThrowsGivenInvalidArgumentValue(double input, double rangeFrom, double rangeTo) 29 | { 30 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 31 | } 32 | 33 | [Theory] 34 | [InlineData(1.0, 0.0, 1.0, 1.0)] 35 | [InlineData(1.0, 0.0, 3.0, 1.0)] 36 | [InlineData(2.0, 1.0, 3.0, 2.0)] 37 | [InlineData(3.0, 3.0, 3.0, 3.0)] 38 | public void ReturnsExpectedValueGivenInRangeValue(double input, double rangeFrom, double rangeTo, double expected) 39 | { 40 | Assert.Equal(expected, Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 41 | } 42 | 43 | [Theory] 44 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 45 | [InlineData("Double range", "Double range (Parameter 'parameterName')")] 46 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 47 | { 48 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0d, "parameterName", 0.0d, 1.0d, customMessage)); 49 | Assert.NotNull(exception); 50 | Assert.NotNull(exception.Message); 51 | Assert.Equal(expectedMessage, exception.Message); 52 | } 53 | 54 | [Theory] 55 | [InlineData(null, null)] 56 | [InlineData(null, "Please provide correct value")] 57 | [InlineData("SomeParameter", null)] 58 | [InlineData("SomeOtherParameter", "Value must be correct")] 59 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 60 | { 61 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0d, expectedParamName, 0.0d, 1.0d, customMessage)); 62 | Assert.NotNull(exception); 63 | Assert.Equal(expectedParamName, exception.ParamName); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDecimal.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForDecimal 4 | { 5 | [Theory] 6 | [InlineData(1.0, 1.0, 1.0)] 7 | [InlineData(1.0, 1.0, 3.0)] 8 | [InlineData(2.0, 1.0, 3.0)] 9 | [InlineData(3.0, 1.0, 3.0)] 10 | public void DoesNothingGivenInRangeValue(decimal input, decimal rangeFrom, decimal rangeTo) 11 | { 12 | Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo); 13 | } 14 | 15 | [Theory] 16 | [InlineData(-1.0, 1.0, 3.0)] 17 | [InlineData(0.0, 1.0, 3.0)] 18 | [InlineData(4.0, 1.0, 3.0)] 19 | public void ThrowsGivenOutOfRangeValue(decimal input, decimal rangeFrom, decimal rangeTo) 20 | { 21 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 22 | } 23 | 24 | [Theory] 25 | [InlineData(-1.0, 3.0, 1.0)] 26 | [InlineData(0.0, 3.0, 1.0)] 27 | [InlineData(4.0, 3.0, 1.0)] 28 | public void ThrowsGivenInvalidArgumentValue(decimal input, decimal rangeFrom, decimal rangeTo) 29 | { 30 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 31 | } 32 | 33 | [Theory] 34 | [InlineData(1.0, 0.0, 1.0, 1.0)] 35 | [InlineData(1.0, 0.0, 3.0, 1.0)] 36 | [InlineData(2.0, 1.0, 3.0, 2.0)] 37 | [InlineData(3.0, 3.0, 3.0, 3.0)] 38 | public void ReturnsExpectedValueGivenInRangeValue(decimal input, decimal rangeFrom, decimal rangeTo, decimal expected) 39 | { 40 | Assert.Equal(expected, Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 41 | } 42 | 43 | [Theory] 44 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 45 | [InlineData("Decimal range", "Decimal range (Parameter 'parameterName')")] 46 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 47 | { 48 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0, "parameterName", 0.0, 1.0, customMessage)); 49 | Assert.NotNull(exception); 50 | Assert.NotNull(exception.Message); 51 | Assert.Equal(expectedMessage, exception.Message); 52 | } 53 | 54 | [Theory] 55 | [InlineData(null, null)] 56 | [InlineData(null, "Please provide correct value")] 57 | [InlineData("SomeParameter", null)] 58 | [InlineData("SomeOtherParameter", "Value must be correct")] 59 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 60 | { 61 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(3.0, expectedParamName, 0.0, 1.0, customMessage)); 62 | Assert.NotNull(exception); 63 | Assert.Equal(expectedParamName, exception.ParamName); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstNull.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstNull 4 | { 5 | [Fact] 6 | public void DoesNothingGivenNonNullValue() 7 | { 8 | Guard.Against.Null("", "string"); 9 | Guard.Against.Null(1, "int"); 10 | Guard.Against.Null(Guid.Empty, "guid"); 11 | Guard.Against.Null(DateTime.Now, "datetime"); 12 | Guard.Against.Null(new Object(), "object"); 13 | } 14 | 15 | [Fact] 16 | public void ThrowsGivenNullValue() 17 | { 18 | object obj = null!; 19 | Assert.Throws(() => Guard.Against.Null(obj, "null")); 20 | } 21 | 22 | [Fact] 23 | public void ReturnsExpectedValueWhenGivenNonNullValue() 24 | { 25 | Assert.Equal("", Guard.Against.Null("", "string")); 26 | Assert.Equal(1, Guard.Against.Null(1, "int")); 27 | 28 | var guid = Guid.Empty; 29 | Assert.Equal(guid, Guard.Against.Null(guid, "guid")); 30 | 31 | var now = DateTime.Now; 32 | Assert.Equal(now, Guard.Against.Null(now, "datetime")); 33 | 34 | var obj = new Object(); 35 | Assert.Equal(obj, Guard.Against.Null(obj, "object")); 36 | } 37 | 38 | [Theory] 39 | [InlineData(null, "Value cannot be null. (Parameter 'parameterName')")] 40 | [InlineData("Please provide correct value", "Please provide correct value (Parameter 'parameterName')")] 41 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 42 | { 43 | string? nullString = null; 44 | var exception = Assert.Throws(() => Guard.Against.Null(nullString, "parameterName", customMessage)); 45 | Assert.NotNull(exception); 46 | Assert.NotNull(exception.Message); 47 | Assert.Equal(expectedMessage, exception.Message); 48 | } 49 | 50 | [Fact] 51 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvided() 52 | { 53 | string? xyz = null; 54 | 55 | var exception = Assert.Throws(() => Guard.Against.Null(xyz)); 56 | 57 | Assert.NotNull(exception); 58 | Assert.NotNull(exception.Message); 59 | Assert.Contains($"Value cannot be null. (Parameter '{nameof(xyz)}')", exception.Message); 60 | } 61 | 62 | [Theory] 63 | [InlineData(null, null)] 64 | [InlineData(null, "Please provide correct value")] 65 | [InlineData("SomeParameter", null)] 66 | [InlineData("SomeOtherParameter", "Value must be correct")] 67 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 68 | { 69 | string? nullString = null; 70 | var exception = Assert.Throws(() => Guard.Against.Null(nullString, expectedParamName, customMessage)); 71 | Assert.NotNull(exception); 72 | Assert.Equal(expectedParamName, exception.ParamName); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForIComparable.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | /// 4 | /// Every type that implements IComparable and IComparable can use OutOfRange. 5 | /// Here for example tuples are used. 6 | /// 7 | public class GuardAgainstOutOfRangeForIComparable 8 | { 9 | [Theory] 10 | [InlineData(1, 1, 1, 1, 10, 10)] 11 | [InlineData(5, 5, 1, 1, 10, 10)] 12 | [InlineData(10, 10, 1, 1, 10, 10)] 13 | public void DoesNothingGivenInRangeValue(int input1, int input2, int rangeFrom1, int rangeFrom2, int rangeTo1, int rangeTo2) 14 | { 15 | Guard.Against.OutOfRange((input1, input2), "tuple", (rangeFrom1, rangeFrom2), (rangeTo1, rangeTo2)); 16 | } 17 | 18 | [Theory] 19 | [InlineData(0, 1, 1, 1, 10, 10)] 20 | [InlineData(1, 0, 1, 1, 10, 10)] 21 | [InlineData(10, 11, 1, 1, 10, 10)] 22 | [InlineData(11, 10, 1, 1, 10, 10)] 23 | public void ThrowsGivenOutOfRangeValue(int input1, int input2, int rangeFrom1, int rangeFrom2, int rangeTo1, int rangeTo2) 24 | { 25 | Assert.Throws(() => Guard.Against.OutOfRange((input1, input2), "tuple", (rangeFrom1, rangeFrom2), (rangeTo1, rangeTo2))); 26 | } 27 | 28 | [Theory] 29 | [InlineData(0, 1, 10, 10, 1, 1)] 30 | [InlineData(1, 0, 10, 10, 1, 1)] 31 | [InlineData(10, 11, 10, 10, 1, 1)] 32 | [InlineData(11, 10, 10, 10, 1, 1)] 33 | public void ThrowsGivenInvalidArgumentValue(int input1, int input2, int rangeFrom1, int rangeFrom2, int rangeTo1, int rangeTo2) 34 | { 35 | Assert.Throws(() => Guard.Against.OutOfRange((input1, input2), "tuple", (rangeFrom1, rangeFrom2), (rangeTo1, rangeTo2))); 36 | } 37 | 38 | [Theory] 39 | [InlineData(1, 1, 1, 1, 10, 10)] 40 | [InlineData(5, 5, 1, 1, 10, 10)] 41 | [InlineData(10, 10, 1, 1, 10, 10)] 42 | public void ReturnsExpectedValueGivenInRangeValue(int input1, int input2, int rangeFrom1, int rangeFrom2, int rangeTo1, int rangeTo2) 43 | { 44 | var input = (input1, input2); 45 | var actual = Guard.Against.OutOfRange(input, "tuple", (rangeFrom1, rangeFrom2), (rangeTo1, rangeTo2)); 46 | Assert.Equal(input, actual); 47 | } 48 | 49 | [Theory] 50 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 51 | [InlineData("Tuple range", "Tuple range (Parameter 'parameterName')")] 52 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 53 | { 54 | var exception = Assert.Throws(() => Guard.Against.OutOfRange((1,2), "parameterName", (3,3), (9,9), customMessage)); 55 | Assert.NotNull(exception); 56 | Assert.NotNull(exception.Message); 57 | Assert.Equal(expectedMessage, exception.Message); 58 | } 59 | 60 | [Theory] 61 | [InlineData(null, null)] 62 | [InlineData(null, "Please provide correct value")] 63 | [InlineData("SomeParameter", null)] 64 | [InlineData("SomeOtherParameter", "Value must be correct")] 65 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 66 | { 67 | var exception = Assert.Throws(() => Guard.Against.OutOfRange((1, 2), expectedParamName, (3, 3), (9, 9), customMessage)); 68 | Assert.NotNull(exception); 69 | Assert.Equal(expectedParamName, exception.ParamName); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForDateTime.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForDateTime 4 | { 5 | [Theory] 6 | [InlineData(0, 0)] 7 | [InlineData(0, 3)] 8 | [InlineData(-1, 1)] 9 | [InlineData(-1, 0)] 10 | public void DoesNothingGivenInRangeValue(int rangeFromOffset, int rangeToOffset) 11 | { 12 | DateTime input = DateTime.Now; 13 | DateTime rangeFrom = input.AddSeconds(rangeFromOffset); 14 | DateTime rangeTo = input.AddSeconds(rangeToOffset); 15 | Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo); 16 | } 17 | 18 | [Theory] 19 | [InlineData(1, 3)] 20 | [InlineData(-4, -3)] 21 | public void ThrowsGivenOutOfRangeValue(int rangeFromOffset, int rangeToOffset) 22 | { 23 | DateTime input = DateTime.Now; 24 | DateTime rangeFrom = input.AddSeconds(rangeFromOffset); 25 | DateTime rangeTo = input.AddSeconds(rangeToOffset); 26 | Assert.Throws(() => Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 27 | } 28 | 29 | [Theory] 30 | [InlineData(3, 1)] 31 | [InlineData(3, -1)] 32 | public void ThrowsGivenInvalidArgumentValue(int rangeFromOffset, int rangeToOffset) 33 | { 34 | DateTime input = DateTime.Now; 35 | DateTime rangeFrom = input.AddSeconds(rangeFromOffset); 36 | DateTime rangeTo = input.AddSeconds(rangeToOffset); 37 | Assert.Throws(() => Guard.Against.OutOfRange(DateTime.Now, "index", rangeFrom, rangeTo)); 38 | } 39 | 40 | [Theory] 41 | [InlineData(0, 0)] 42 | [InlineData(0, 3)] 43 | [InlineData(-1, 1)] 44 | [InlineData(-1, 0)] 45 | public void ReturnsExpectedValueGivenInRangeValue(int rangeFromOffset, int rangeToOffset) 46 | { 47 | DateTime input = DateTime.Now; 48 | DateTime expected = input; 49 | DateTime rangeFrom = input.AddSeconds(rangeFromOffset); 50 | DateTime rangeTo = input.AddSeconds(rangeToOffset); 51 | Assert.Equal(expected, Guard.Against.OutOfRange(input, "index", rangeFrom, rangeTo)); 52 | } 53 | 54 | [Theory] 55 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 56 | [InlineData("DateTime range", "DateTime range (Parameter 'parameterName')")] 57 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 58 | { 59 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(DateTime.Today.AddDays(-1), "parameterName", 60 | DateTime.Today, DateTime.Today.AddDays(1), customMessage)); 61 | Assert.NotNull(exception); 62 | Assert.NotNull(exception.Message); 63 | Assert.Equal(expectedMessage, exception.Message); 64 | } 65 | 66 | [Theory] 67 | [InlineData(null, null)] 68 | [InlineData(null, "Please provide correct value")] 69 | [InlineData("SomeParameter", null)] 70 | [InlineData("SomeOtherParameter", "Value must be correct")] 71 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 72 | { 73 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(DateTime.Today.AddDays(-1), expectedParamName, 74 | DateTime.Today, DateTime.Today.AddDays(1), customMessage)); 75 | Assert.NotNull(exception); 76 | Assert.Equal(expectedParamName, exception.ParamName); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/GuardClauses/GuardAgainstNotFoundExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Runtime.CompilerServices; 3 | using JetBrainsInvokerParameterNameAttribute = JetBrains.Annotations.InvokerParameterNameAttribute; 4 | using JetBrainsNoEnumerationAttribute = JetBrains.Annotations.NoEnumerationAttribute; 5 | using JetBrainsNotNullAttribute = JetBrains.Annotations.NotNullAttribute; 6 | 7 | namespace Ardalis.GuardClauses 8 | { 9 | public static partial class GuardClauseExtensions 10 | { 11 | /// 12 | /// Throws an if with is not found. 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// if the value is not null. 20 | /// 21 | #if NETSTANDARD || NETFRAMEWORK 22 | public static T NotFound([JetBrainsNotNull] this IGuardClause guardClause, 23 | [NotNull, JetBrainsNotNull][ValidatedNotNull] string key, 24 | [NotNull, JetBrainsNotNull][ValidatedNotNull][JetBrainsNoEnumeration] T input, 25 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName) 26 | #else 27 | public static T NotFound([JetBrainsNotNull] this IGuardClause guardClause, 28 | [NotNull, JetBrainsNotNull][ValidatedNotNull] string key, 29 | [NotNull, JetBrainsNotNull][ValidatedNotNull][JetBrainsNoEnumeration] T input, 30 | [JetBrainsNotNull][CallerArgumentExpression("input")] string? parameterName = null) 31 | #endif 32 | { 33 | guardClause.NullOrEmpty(key, nameof(key)); 34 | 35 | if (input is null) 36 | { 37 | throw new NotFoundException(key, parameterName!); 38 | } 39 | 40 | return input; 41 | } 42 | 43 | /// 44 | /// Throws an if with is not found. 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// if the value is not null. 53 | /// 54 | #if NETSTANDARD || NETFRAMEWORK 55 | public static T NotFound([JetBrainsNotNull] this IGuardClause guardClause, 56 | [NotNull, JetBrainsNotNull][ValidatedNotNull] TKey key, 57 | [NotNull, JetBrainsNotNull][ValidatedNotNull][JetBrainsNoEnumeration] T input, 58 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName) where TKey : struct 59 | #else 60 | public static T NotFound([JetBrainsNotNull] this IGuardClause guardClause, 61 | [NotNull, JetBrainsNotNull][ValidatedNotNull] TKey key, 62 | [NotNull, JetBrainsNotNull][ValidatedNotNull][JetBrainsNoEnumeration] T input, 63 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null) where TKey : struct 64 | #endif 65 | { 66 | guardClause.Null(key, nameof(key)); 67 | 68 | if (input is null) 69 | { 70 | // TODO: Can we safely consider that ToString() won't return null for struct? 71 | throw new NotFoundException(key.ToString()!, parameterName!); 72 | } 73 | 74 | return input; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstDefault.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstDefault 4 | { 5 | [Fact] 6 | public void DoesNothingGivenNonDefaultValue() 7 | { 8 | Guard.Against.Default("", "string"); 9 | Guard.Against.Default(1, "int"); 10 | Guard.Against.Default(Guid.NewGuid(), "guid"); 11 | Guard.Against.Default(DateTime.Now, "datetime"); 12 | Guard.Against.Default(new Object(), "object"); 13 | } 14 | 15 | [Fact] 16 | public void ThrowsGivenDefaultValue() 17 | { 18 | Assert.Throws("string", () => Guard.Against.Default(default(string), "string")); 19 | Assert.Throws("int", () => Guard.Against.Default(default(int), "int")); 20 | Assert.Throws("guid", () => Guard.Against.Default(default(Guid), "guid")); 21 | Assert.Throws("datetime", () => Guard.Against.Default(default(DateTime), "datetime")); 22 | Assert.Throws("object", () => Guard.Against.Default(default(object), "object")); 23 | } 24 | 25 | [Theory] 26 | [MemberData(nameof(GetNonDefaultTestVectors))] 27 | public void ReturnsExpectedValueWhenGivenNonDefaultValue(object input, string name, object expected) 28 | { 29 | var actual = Guard.Against.Default(input, name); 30 | Assert.Equal(expected, actual); 31 | } 32 | 33 | [Theory] 34 | [InlineData(null, "Parameter [parameterName] is default value for type String (Parameter 'parameterName')")] 35 | [InlineData("Please provide correct value", "Please provide correct value (Parameter 'parameterName')")] 36 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 37 | { 38 | var exception = Assert.Throws(() => Guard.Against.Default(default(string), "parameterName", customMessage)); 39 | Assert.NotNull(exception); 40 | Assert.NotNull(exception.Message); 41 | Assert.Equal(expectedMessage, exception.Message); 42 | } 43 | 44 | [Theory] 45 | [InlineData(null, "Parameter [xyz] is default value for type String (Parameter 'xyz')")] 46 | [InlineData("Please provide correct value", "Please provide correct value (Parameter 'xyz')")] 47 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvided(string customMessage, string expectedMessage) 48 | { 49 | var xyz = default(string); 50 | var exception = Assert.Throws(() => Guard.Against.Default(xyz, message: customMessage)); 51 | Assert.NotNull(exception); 52 | Assert.NotNull(exception.Message); 53 | Assert.Equal(expectedMessage, exception.Message); 54 | } 55 | 56 | [Theory] 57 | [InlineData(null, null)] 58 | [InlineData(null, "Please provide correct value")] 59 | [InlineData("SomeParameter", null)] 60 | [InlineData("SomeOtherParameter", "Value must be correct")] 61 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 62 | { 63 | var exception = Assert.Throws(() => Guard.Against.Default(default(string), expectedParamName, customMessage)); 64 | Assert.NotNull(exception); 65 | Assert.Equal(expectedParamName, exception.ParamName); 66 | } 67 | 68 | public static IEnumerable GetNonDefaultTestVectors() 69 | { 70 | yield return new object[] { "", "string", "" }; 71 | yield return new object[] { 1, "int", 1 }; 72 | 73 | var guid = Guid.NewGuid(); 74 | yield return new object[] { guid, "guid", guid }; 75 | 76 | var now = DateTime.Now; 77 | yield return new object[] { now, "now", now }; 78 | 79 | var obj = new Object(); 80 | yield return new object[] { obj, "obj", obj }; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstNullOrInvalidInput.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstNullOrInvalidInput 4 | { 5 | [Theory] 6 | [ClassData(typeof(ArgumentNullExceptionClassData))] 7 | public void ThrowsArgumentNullExceptionWhenInputIsNull(string input, Func func) 8 | { 9 | Assert.Throws("string", 10 | () => Guard.Against.NullOrInvalidInput(input, "string", func)); 11 | } 12 | 13 | [Theory] 14 | [ClassData(typeof(ArgumentExceptionClassData))] 15 | public void ThrowsArgumentExceptionWhenInputIsInvalid(string input, Func func) 16 | { 17 | Assert.Throws("string", 18 | () => Guard.Against.NullOrInvalidInput(input, "string", func)); 19 | } 20 | 21 | [Theory] 22 | [ClassData(typeof(ValidClassData))] 23 | public void ReturnsExceptedValueWhenGivenValidInput(int input, Func func) 24 | { 25 | var result = Guard.Against.NullOrInvalidInput(input, nameof(input), func); 26 | Assert.Equal(input, result); 27 | } 28 | 29 | [Theory] 30 | [InlineData(null, "Input parameterName did not satisfy the options (Parameter 'parameterName')", typeof(ArgumentException), 10)] 31 | [InlineData("Evaluation failed", "Evaluation failed (Parameter 'parameterName')", typeof(ArgumentException), 10)] 32 | [InlineData(null, "Value cannot be null. (Parameter 'parameterName')", typeof(ArgumentNullException))] 33 | [InlineData("Please provide correct value", "Please provide correct value (Parameter 'parameterName')", typeof(ArgumentNullException))] 34 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage, Type exceptionType, int? input = null) 35 | { 36 | var exception = Assert.Throws(exceptionType, 37 | () => Guard.Against.NullOrInvalidInput(input, "parameterName", x => x > 20, customMessage)); 38 | 39 | Assert.NotNull(exception); 40 | Assert.NotNull(exception.Message); 41 | Assert.Equal(expectedMessage, exception.Message); 42 | } 43 | 44 | [Theory] 45 | [InlineData(null, null, typeof(ArgumentException), 10)] 46 | [InlineData(null, "Please provide correct value", typeof(ArgumentException), 10)] 47 | [InlineData("SomeParameter", null, typeof(ArgumentNullException))] 48 | [InlineData("SomeOtherParameter", "Value must be correct", typeof(ArgumentNullException))] 49 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage, Type exceptionType, int? input = null) 50 | { 51 | var exception = Assert.Throws(exceptionType, 52 | () => Guard.Against.NullOrInvalidInput(input, expectedParamName, x => x > 20, customMessage)); 53 | 54 | Assert.IsAssignableFrom(exception); 55 | Assert.NotNull(exception); 56 | Assert.Equal(expectedParamName, (exception as ArgumentException)!.ParamName); 57 | } 58 | 59 | public class ValidClassData : IEnumerable 60 | { 61 | public IEnumerator GetEnumerator() 62 | { 63 | yield return new object[] { 20, (Func)(x => x > 10) }; 64 | } 65 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 66 | } 67 | 68 | public class ArgumentNullExceptionClassData : IEnumerable 69 | { 70 | public IEnumerator GetEnumerator() 71 | { 72 | yield return new object[] { null, (Func)(x => x.Length > 10) }; 73 | } 74 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 75 | } 76 | 77 | public class ArgumentExceptionClassData : IEnumerable 78 | { 79 | public IEnumerator GetEnumerator() 80 | { 81 | yield return new object[] { "TestData", (Func)(x => x.Length > 10) }; 82 | } 83 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForInvalidInput.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForInvalidInput 4 | { 5 | [Theory] 6 | [ClassData(typeof(CorrectClassData))] 7 | public void DoesNothingGivenInRangeValue(T input, Func func) 8 | { 9 | Guard.Against.InvalidInput(input, nameof(input), func); 10 | } 11 | 12 | [Theory] 13 | [ClassData(typeof(IncorrectClassData))] 14 | public void ThrowsGivenOutOfRangeValue(T input, Func func) 15 | { 16 | Assert.Throws(() => Guard.Against.InvalidInput(input, nameof(input), func)); 17 | } 18 | 19 | [Theory] 20 | [ClassData(typeof(CorrectClassData))] 21 | public void ReturnsExpectedValueGivenInRangeValue(T input, Func func) 22 | { 23 | var result = Guard.Against.InvalidInput(input, nameof(input), func); 24 | Assert.Equal(input, result); 25 | } 26 | 27 | [Theory] 28 | [InlineData(null, "Input parameterName did not satisfy the options (Parameter 'parameterName')")] 29 | [InlineData("Evaluation failed", "Evaluation failed (Parameter 'parameterName')")] 30 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 31 | { 32 | var exception = Assert.Throws(() => Guard.Against.InvalidInput(10, "parameterName", x => x > 20, customMessage)); 33 | Assert.NotNull(exception); 34 | Assert.NotNull(exception.Message); 35 | Assert.Equal(expectedMessage, exception.Message); 36 | } 37 | 38 | [Theory] 39 | [InlineData(null, null)] 40 | [InlineData(null, "Please provide correct value")] 41 | [InlineData("SomeParameter", null)] 42 | [InlineData("SomeOtherParameter", "Value must be correct")] 43 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 44 | { 45 | var exception = Assert.Throws(() => Guard.Against.InvalidInput(10, expectedParamName, x => x > 20, customMessage)); 46 | Assert.NotNull(exception); 47 | Assert.Equal(expectedParamName, exception.ParamName); 48 | } 49 | 50 | // TODO: Test decimal types outside of ClassData 51 | // See: https://github.com/xunit/xunit/issues/2298 52 | public class CorrectClassData : IEnumerable 53 | { 54 | public IEnumerator GetEnumerator() 55 | { 56 | yield return new object[] { 20, (Func)((x) => x > 10) }; 57 | yield return new object[] { DateAndTime.Now, (Func)((x) => x > DateTime.MinValue) }; 58 | yield return new object[] { 20.0f, (Func)((x) => x > 10.0f) }; 59 | //yield return new object[] { 20.0m, (Func)((x) => x > 10.0m) }; 60 | yield return new object[] { 20.0, (Func)((x) => x > 10.0) }; 61 | yield return new object[] { long.MaxValue, (Func)((x) => x > 1) }; 62 | yield return new object[] { short.MaxValue, (Func)((x) => x > 1) }; 63 | yield return new object[] { "abcd", (Func)((x) => x == x.ToLower()) }; 64 | } 65 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 66 | } 67 | 68 | public class IncorrectClassData : IEnumerable 69 | { 70 | public IEnumerator GetEnumerator() 71 | { 72 | yield return new object[] { 20, (Func)((x) => x < 10) }; 73 | yield return new object[] { DateAndTime.Now, (Func)((x) => x > DateTime.MaxValue) }; 74 | yield return new object[] { 20.0f, (Func)((x) => x > 30.0f) }; 75 | //yield return new object[] { 20.0m, (Func)((x) => x > 30.0m) }; 76 | yield return new object[] { 20.0, (Func)((x) => x > 30.0) }; 77 | yield return new object[] { long.MaxValue, (Func)((x) => x < 1) }; 78 | yield return new object[] { short.MaxValue, (Func)((x) => x < 1) }; 79 | yield return new object[] { "abcd", (Func)((x) => x == x.ToUpper()) }; 80 | } 81 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | [![NuGet](https://img.shields.io/nuget/v/Ardalis.GuardClauses.svg)](https://www.nuget.org/packages/Ardalis.GuardClauses)[![NuGet](https://img.shields.io/nuget/dt/Ardalis.GuardClauses.svg)](https://www.nuget.org/packages/Ardalis.GuardClauses) 6 | ![publish Ardalis.GuardClauses to nuget](https://github.com/ardalis/GuardClauses/workflows/publish%20Ardalis.GuardClauses%20to%20nuget/badge.svg) 7 | 8 | 9 | Follow @ardalis 10 |   11 | Follow @nimblepros 12 | 13 | 14 | # Guard Clauses 15 | 16 | A simple extensible package with guard clause extensions. 17 | 18 | A [guard clause](https://deviq.com/design-patterns/guard-clause) is a software pattern that simplifies complex functions by "failing fast", checking for invalid inputs up front and immediately failing if any are found. 19 | 20 | ## Give a Star! :star: 21 | 22 | If you like or are using this project please give it a star. Thanks! 23 | 24 | ## Usage 25 | 26 | ```c# 27 | public void ProcessOrder(Order order) 28 | { 29 | Guard.Against.Null(order, nameof(order)); 30 | 31 | // process order here 32 | } 33 | 34 | // OR 35 | 36 | public class Order 37 | { 38 | private string _name; 39 | private int _quantity; 40 | private long _max; 41 | private decimal _unitPrice; 42 | private DateTime _dateCreated; 43 | 44 | public Order(string name, int quantity, long max, decimal unitPrice, DateTime dateCreated) 45 | { 46 | _name = Guard.Against.NullOrWhiteSpace(name, nameof(name)); 47 | _quantity = Guard.Against.NegativeOrZero(quantity, nameof(quantity)); 48 | _max = Guard.Against.Zero(max, nameof(max)); 49 | _unitPrice = Guard.Against.Negative(unitPrice, nameof(unitPrice)); 50 | _dateCreated = Guard.Against.OutOfSQLDateRange(dateCreated, nameof(dateCreated)); 51 | } 52 | } 53 | ``` 54 | 55 | ## Supported Guard Clauses 56 | 57 | - **Guard.Against.Null** (throws if input is null) 58 | - **Guard.Against.NullOrEmpty** (throws if string, guid or array input is null or empty) 59 | - **Guard.Against.NullOrWhiteSpace** (throws if string input is null, empty or whitespace) 60 | - **Guard.Against.OutOfRange** (throws if integer/DateTime/enum input is outside a provided range) 61 | - **Guard.Against.EnumOutOfRange** (throws if a enum value is outside a provided Enum range) 62 | - **Guard.Against.OutOfSQLDateRange** (throws if DateTime input is outside the valid range of SQL Server DateTime values) 63 | - **Guard.Against.Zero** (throws if number input is zero) 64 | 65 | ## Extending with your own Guard Clauses 66 | 67 | To extend your own guards, you can do the following: 68 | 69 | ```c# 70 | // Using the same namespace will make sure your code picks up your 71 | // extensions no matter where they are in your codebase. 72 | namespace Ardalis.GuardClauses 73 | { 74 | public static class FooGuard 75 | { 76 | public static void Foo(this IGuardClause guardClause, string input, string parameterName) 77 | { 78 | if (input?.ToLower() == "foo") 79 | throw new ArgumentException("Should not have been foo!", parameterName); 80 | } 81 | } 82 | } 83 | 84 | // Usage 85 | public void SomeMethod(string something) 86 | { 87 | Guard.Against.Foo(something, nameof(something)); 88 | } 89 | ``` 90 | 91 | ## Breaking Changes in v4 92 | 93 | - OutOfRange for Enums now uses `EnumOutOfRange` 94 | - Custom error messages now work more consistently, which may break some unit tests 95 | 96 | ## References 97 | 98 | - [Getting Started with Guard Clauses](https://blog.nimblepros.com/blogs/getting-started-with-guard-clauses/) 99 | - [How to write clean validation clauses in .NET](https://www.youtube.com/watch?v=Tvx6DNarqDM) (Nick Chapsas, YouTube, 9 minutes) 100 | - [Guard Clauses (podcast: 7 minutes)](http://www.weeklydevtips.com/004) 101 | - [Guard Clause](http://deviq.com/guard-clause/) 102 | 103 | ## Build Notes (for maintainers) 104 | 105 | - Remember to update the PackageVersion in the csproj file and then a build on master should automatically publish the new package to nuget.org. 106 | - Add a release with form `1.3.2` to GitHub Releases in order for the package to actually be published to Nuget. Otherwise it will claim to have been successful but is lying to you. 107 | 108 | 109 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfSQLDateRange.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfSQLDateRange 4 | { 5 | [Theory] 6 | [InlineData(1)] 7 | [InlineData(60)] 8 | [InlineData(60 * 60)] 9 | [InlineData(60 * 60 * 24)] 10 | [InlineData(60 * 60 * 24 * 30)] 11 | [InlineData(60 * 60 * 24 * 30 * 365)] 12 | public void ThrowsGivenValueBelowMinDate(int offsetInSeconds) 13 | { 14 | DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-offsetInSeconds); 15 | 16 | Assert.Throws(() => Guard.Against.OutOfSQLDateRange(date, nameof(date))); 17 | } 18 | 19 | [Fact] 20 | public void DoNothingGivenCurrentDate() 21 | { 22 | Guard.Against.OutOfSQLDateRange(DateTime.Today, "Today"); 23 | Guard.Against.OutOfSQLDateRange(DateTime.Now, "Now"); 24 | Guard.Against.OutOfSQLDateRange(DateTime.UtcNow, "UTC Now"); 25 | } 26 | 27 | [Theory] 28 | [InlineData(0)] 29 | [InlineData(1)] 30 | [InlineData(60)] 31 | [InlineData(60 * 60)] 32 | [InlineData(60 * 60 * 24)] 33 | [InlineData(60 * 60 * 24 * 30)] 34 | [InlineData(60 * 60 * 24 * 30 * 365)] 35 | public void DoNothingGivenSqlMinValue(int offsetInSeconds) 36 | { 37 | DateTime date = SqlDateTime.MinValue.Value.AddSeconds(offsetInSeconds); 38 | 39 | Guard.Against.OutOfSQLDateRange(date, nameof(date)); 40 | } 41 | 42 | [Theory] 43 | [InlineData(0)] 44 | [InlineData(1)] 45 | [InlineData(60)] 46 | [InlineData(60 * 60)] 47 | [InlineData(60 * 60 * 24)] 48 | [InlineData(60 * 60 * 24 * 30)] 49 | [InlineData(60 * 60 * 24 * 30 * 365)] 50 | public void DoNothingGivenSqlMaxValue(int offsetInSeconds) 51 | { 52 | DateTime date = SqlDateTime.MaxValue.Value.AddSeconds(-offsetInSeconds); 53 | 54 | Guard.Against.OutOfSQLDateRange(date, nameof(date)); 55 | } 56 | 57 | [Theory] 58 | [MemberData(nameof(GetSqlDateTimeTestVectors))] 59 | public void ReturnsExpectedValueWhenGivenValidSqlDateTime(DateTime input, string name, DateTime expected) 60 | { 61 | Assert.Equal(expected, Guard.Against.OutOfSQLDateRange(input, name)); 62 | } 63 | 64 | [Theory] 65 | [InlineData(null, "Input date was out of range (Parameter 'date')")] 66 | [InlineData("SQLDate range", "SQLDate range (Parameter 'date')")] 67 | public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage) 68 | { 69 | DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-1); 70 | var exception = Assert.Throws(() => Guard.Against.OutOfSQLDateRange(date, nameof(date), customMessage)); 71 | 72 | Assert.NotNull(exception); 73 | Assert.NotNull(exception.Message); 74 | Assert.Equal(expectedMessage, exception.Message); 75 | } 76 | 77 | [Theory] 78 | [InlineData(null, "Input date was out of range (Parameter 'date')")] 79 | [InlineData("SQLDate range", "SQLDate range (Parameter 'date')")] 80 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvided(string customMessage, string expectedMessage) 81 | { 82 | DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-1); 83 | var exception = Assert.Throws(() => Guard.Against.OutOfSQLDateRange(date, message: customMessage)); 84 | 85 | Assert.NotNull(exception); 86 | Assert.NotNull(exception.Message); 87 | Assert.Equal(expectedMessage, exception.Message); 88 | } 89 | 90 | [Theory] 91 | [InlineData(null, null)] 92 | [InlineData(null, "Please provide correct value")] 93 | [InlineData("SomeParameter", null)] 94 | [InlineData("SomeOtherParameter", "Value must be correct")] 95 | public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage) 96 | { 97 | DateTime date = SqlDateTime.MinValue.Value.AddSeconds(-1); 98 | var exception = Assert.Throws(() => Guard.Against.OutOfSQLDateRange(date, expectedParamName, customMessage)); 99 | Assert.NotNull(exception); 100 | Assert.Equal(expectedParamName, exception.ParamName); 101 | } 102 | 103 | public static IEnumerable GetSqlDateTimeTestVectors() 104 | { 105 | var now = DateTime.Now; 106 | var utc = DateTime.UtcNow; 107 | var yesterday = DateTime.Now.AddDays(-1); 108 | var min = SqlDateTime.MinValue.Value; 109 | var max = SqlDateTime.MaxValue.Value; 110 | 111 | yield return new object[] { now, "now", now }; 112 | yield return new object[] { utc, "utc", utc }; 113 | yield return new object[] { yesterday, "yesterday", yesterday }; 114 | yield return new object[] { min, "min", min }; 115 | yield return new object[] { max, "max", max }; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstNullOrWhiteSpace.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstNullOrWhiteSpace 4 | { 5 | [Theory] 6 | [InlineData("a")] 7 | [InlineData("1")] 8 | [InlineData("some text")] 9 | [InlineData(" leading whitespace")] 10 | [InlineData("trailing whitespace ")] 11 | public void DoesNothingGivenNonEmptyStringValue(string nonEmptyString) 12 | { 13 | Guard.Against.NullOrWhiteSpace(nonEmptyString, "string"); 14 | Guard.Against.NullOrWhiteSpace(nonEmptyString, "aNumericString"); 15 | } 16 | 17 | [Fact] 18 | public void ThrowsGivenNullValue() 19 | { 20 | Assert.Throws(() => Guard.Against.NullOrWhiteSpace(null, "null")); 21 | } 22 | 23 | [Fact] 24 | public void ThrowsGivenEmptyString() 25 | { 26 | Assert.Throws(() => Guard.Against.NullOrWhiteSpace("", "emptystring")); 27 | } 28 | 29 | [Theory] 30 | [InlineData(" ")] 31 | [InlineData(" ")] 32 | public void ThrowsGivenWhiteSpaceString(string whiteSpaceString) 33 | { 34 | Assert.Throws(() => Guard.Against.NullOrWhiteSpace(whiteSpaceString, "whitespacestring")); 35 | } 36 | 37 | [Theory] 38 | [InlineData("a", "a")] 39 | [InlineData("1", "1")] 40 | [InlineData("some text", "some text")] 41 | [InlineData(" leading whitespace", " leading whitespace")] 42 | [InlineData("trailing whitespace ", "trailing whitespace ")] 43 | public void ReturnsExpectedValueGivenNonEmptyStringValue(string nonEmptyString, string expected) 44 | { 45 | Assert.Equal(expected, Guard.Against.NullOrWhiteSpace(nonEmptyString, "string")); 46 | Assert.Equal(expected, Guard.Against.NullOrWhiteSpace(nonEmptyString, "aNumericString")); 47 | } 48 | 49 | [Theory] 50 | [InlineData(null, "Required input parameterName was empty. (Parameter 'parameterName')")] 51 | [InlineData("Value is empty", "Value is empty (Parameter 'parameterName')")] 52 | public void ErrorMessageMatchesExpectedWhenInputIsWhiteSpace(string customMessage, string expectedMessage) 53 | { 54 | var exception = Assert.Throws(() => Guard.Against.NullOrWhiteSpace(" ", "parameterName", customMessage)); 55 | Assert.NotNull(exception); 56 | Assert.NotNull(exception.Message); 57 | Assert.Equal(expectedMessage, exception.Message); 58 | } 59 | 60 | [Theory] 61 | [InlineData(null, "Value cannot be null. (Parameter 'parameterName')")] 62 | [InlineData("Value is null", "Value is null (Parameter 'parameterName')")] 63 | public void ErrorMessageMatchesExpectedWhenInputIsNull(string customMessage, string expectedMessage) 64 | { 65 | string? nullString = null; 66 | var exception = Assert.Throws(() => Guard.Against.NullOrWhiteSpace(nullString, "parameterName", customMessage)); 67 | Assert.NotNull(exception); 68 | Assert.NotNull(exception.Message); 69 | Assert.Equal(expectedMessage, exception.Message); 70 | } 71 | 72 | [Theory] 73 | [InlineData(null, "Value cannot be null. (Parameter 'xyz')")] 74 | [InlineData("Value is null", "Value is null (Parameter 'xyz')")] 75 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvided(string customMessage, string expectedMessage) 76 | { 77 | string? xyz = null; 78 | var exception = Assert.Throws(() => Guard.Against.NullOrWhiteSpace(xyz, message: customMessage)); 79 | Assert.NotNull(exception); 80 | Assert.NotNull(exception.Message); 81 | Assert.Equal(expectedMessage, exception.Message); 82 | } 83 | 84 | [Theory] 85 | [InlineData(null, null)] 86 | [InlineData(null, "Please provide correct value")] 87 | [InlineData("SomeParameter", null)] 88 | [InlineData("SomeOtherParameter", "Value must be correct")] 89 | public void ExceptionParamNameMatchesExpectedWhenInputIsWhiteSpace(string expectedParamName, string customMessage) 90 | { 91 | var exception = Assert.Throws(() => Guard.Against.NullOrWhiteSpace(" ", expectedParamName, customMessage)); 92 | Assert.NotNull(exception); 93 | Assert.Equal(expectedParamName, exception.ParamName); 94 | } 95 | 96 | [Theory] 97 | [InlineData(null, null)] 98 | [InlineData(null, "Please provide correct value")] 99 | [InlineData("SomeParameter", null)] 100 | [InlineData("SomeOtherParameter", "Value must be correct")] 101 | public void ExceptionParamNameMatchesExpectedWhenInputIsNull(string expectedParamName, string customMessage) 102 | { 103 | string? nullString = null; 104 | var exception = Assert.Throws(() => Guard.Against.NullOrWhiteSpace(nullString, expectedParamName, customMessage)); 105 | Assert.NotNull(exception); 106 | Assert.Equal(expectedParamName, exception.ParamName); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForTimeSpan.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForTimeSpan 4 | { 5 | [Theory] 6 | [InlineData(1, 1, 1)] 7 | [InlineData(1, 1, 3)] 8 | [InlineData(2, 1, 3)] 9 | [InlineData(3, 1, 3)] 10 | public void DoesNothingGivenInRangeValue(int input, int rangeFrom, int rangeTo) 11 | { 12 | var inputTimeSpan = TimeSpan.FromSeconds(input); 13 | var rangeFromTimeSpan = TimeSpan.FromSeconds(rangeFrom); 14 | var rangeToTimeSpan = TimeSpan.FromSeconds(rangeTo); 15 | 16 | Guard.Against.OutOfRange(inputTimeSpan, "index", rangeFromTimeSpan, rangeToTimeSpan); 17 | } 18 | 19 | [Theory] 20 | [InlineData(-1, 1, 3)] 21 | [InlineData(0, 1, 3)] 22 | [InlineData(4, 1, 3)] 23 | public void ThrowsGivenOutOfRangeValue(int input, int rangeFrom, int rangeTo) 24 | { 25 | var inputTimeSpan = TimeSpan.FromSeconds(input); 26 | var rangeFromTimeSpan = TimeSpan.FromSeconds(rangeFrom); 27 | var rangeToTimeSpan = TimeSpan.FromSeconds(rangeTo); 28 | 29 | Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, "index", rangeFromTimeSpan, rangeToTimeSpan)); 30 | } 31 | 32 | [Theory] 33 | [InlineData(-1, 3, 1)] 34 | [InlineData(0, 3, 1)] 35 | [InlineData(4, 3, 1)] 36 | public void ThrowsGivenInvalidArgumentValue(int input, int rangeFrom, int rangeTo) 37 | { 38 | var inputTimeSpan = TimeSpan.FromSeconds(input); 39 | var rangeFromTimeSpan = TimeSpan.FromSeconds(rangeFrom); 40 | var rangeToTimeSpan = TimeSpan.FromSeconds(rangeTo); 41 | 42 | Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, "index", rangeFromTimeSpan, rangeToTimeSpan)); 43 | } 44 | 45 | [Theory] 46 | [InlineData(1, 1, 1, 1)] 47 | [InlineData(1, 1, 3, 1)] 48 | [InlineData(2, 1, 3, 2)] 49 | [InlineData(3, 1, 3, 3)] 50 | public void ReturnsExpectedValueGivenInRangeValue(int input, int rangeFrom, int rangeTo, int expected) 51 | { 52 | var inputTimeSpan = TimeSpan.FromSeconds(input); 53 | var rangeFromTimeSpan = TimeSpan.FromSeconds(rangeFrom); 54 | var rangeToTimeSpan = TimeSpan.FromSeconds(rangeTo); 55 | var expectedTimeSpan = TimeSpan.FromSeconds(expected); 56 | 57 | Assert.Equal(expectedTimeSpan, Guard.Against.OutOfRange(inputTimeSpan, "index", rangeFromTimeSpan, rangeToTimeSpan)); 58 | } 59 | 60 | [Theory] 61 | [InlineData(null, "rangeFrom should be less or equal than rangeTo (Parameter 'parameterName')")] 62 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 63 | public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, string expectedMessage) 64 | { 65 | var inputTimeSpan = TimeSpan.FromSeconds(-1); 66 | var rangeFromTimeSpan = TimeSpan.FromSeconds(3); 67 | var rangeToTimeSpan = TimeSpan.FromSeconds(1); 68 | 69 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, "parameterName", rangeFromTimeSpan, rangeToTimeSpan, customMessage)); 70 | Assert.NotNull(exception); 71 | Assert.NotNull(exception.Message); 72 | Assert.Equal(expectedMessage, exception.Message); 73 | } 74 | 75 | [Theory] 76 | [InlineData(null, null)] 77 | [InlineData(null, "Please provide correct value")] 78 | [InlineData("SomeParameter", null)] 79 | [InlineData("SomeOtherParameter", "Value must be correct")] 80 | public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) 81 | { 82 | var inputTimeSpan = TimeSpan.FromSeconds(-1); 83 | var rangeFromTimeSpan = TimeSpan.FromSeconds(3); 84 | var rangeToTimeSpan = TimeSpan.FromSeconds(1); 85 | 86 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, expectedParamName, rangeFromTimeSpan, rangeToTimeSpan, customMessage)); 87 | Assert.NotNull(exception); 88 | Assert.Equal(expectedParamName, exception.ParamName); 89 | } 90 | 91 | [Theory] 92 | [InlineData(null, "Input parameterName was out of range (Parameter 'parameterName')")] 93 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 94 | public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, string expectedMessage) 95 | { 96 | var inputTimeSpan = TimeSpan.FromSeconds(-1); 97 | var rangeFromTimeSpan = TimeSpan.FromSeconds(0); 98 | var rangeToTimeSpan = TimeSpan.FromSeconds(1); 99 | 100 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, "parameterName", rangeFromTimeSpan, rangeToTimeSpan, customMessage)); 101 | Assert.NotNull(exception); 102 | Assert.NotNull(exception.Message); 103 | Assert.Equal(expectedMessage, exception.Message); 104 | } 105 | 106 | [Theory] 107 | [InlineData(null, null)] 108 | [InlineData(null, "Please provide correct value")] 109 | [InlineData("SomeParameter", null)] 110 | [InlineData("SomeOtherParameter", "Value must be correct")] 111 | public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) 112 | { 113 | var inputTimeSpan = TimeSpan.FromSeconds(-1); 114 | var rangeFromTimeSpan = TimeSpan.FromSeconds(0); 115 | var rangeToTimeSpan = TimeSpan.FromSeconds(1); 116 | 117 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, expectedParamName, rangeFromTimeSpan, rangeToTimeSpan, customMessage)); 118 | Assert.NotNull(exception); 119 | Assert.Equal(expectedParamName, exception.ParamName); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | -------------------------------------------------------------------------------- /media/logotype 1024.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForEnumerableInt.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForEnumerableInt 4 | { 5 | [Theory] 6 | [ClassData(typeof(CorrectClassData))] 7 | public void DoesNothingGivenInRangeValue(IEnumerable input, int rangeFrom, int rangeTo) 8 | { 9 | Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 10 | } 11 | 12 | [Theory] 13 | [ClassData(typeof(IncorrectClassData))] 14 | public void ThrowsGivenOutOfRangeValue(IEnumerable input, int rangeFrom, int rangeTo) 15 | { 16 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 17 | } 18 | 19 | [Theory] 20 | [ClassData(typeof(IncorrectRangeClassData))] 21 | public void ThrowsGivenInvalidArgumentValue(IEnumerable input, int rangeFrom, int rangeTo) 22 | { 23 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 24 | } 25 | 26 | [Theory] 27 | [ClassData(typeof(CorrectClassData))] 28 | public void ReturnsExpectedValueGivenInRangeValue(IEnumerable input, int rangeFrom, int rangeTo) 29 | { 30 | var result = Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 31 | Assert.Equal(input, result); 32 | } 33 | 34 | [Theory] 35 | [InlineData(null, "rangeFrom should be less or equal than rangeTo (Parameter 'parameterName')")] 36 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 37 | public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, string expectedMessage) 38 | { 39 | var input = new[] { 0, 1, 99 }; 40 | int rangeFrom = 2; 41 | int rangeTo = 1; 42 | 43 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 44 | Assert.NotNull(exception); 45 | Assert.NotNull(exception.Message); 46 | Assert.Equal(expectedMessage, exception.Message); 47 | } 48 | 49 | [Theory] 50 | [InlineData(null, null)] 51 | [InlineData(null, "Please provide correct value")] 52 | [InlineData("SomeParameter", null)] 53 | [InlineData("SomeOtherParameter", "Value must be correct")] 54 | public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) 55 | { 56 | var input = new[] { 0, 1, 99 }; 57 | int rangeFrom = 2; 58 | int rangeTo = 1; 59 | 60 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 61 | Assert.NotNull(exception); 62 | Assert.Equal(expectedParamName, exception.ParamName); 63 | } 64 | 65 | [Theory] 66 | [InlineData(null, "Input parameterName had out of range item(s) (Parameter 'parameterName')")] 67 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 68 | public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, string expectedMessage) 69 | { 70 | var input = new[] { 0, 1, 99 }; 71 | int rangeFrom = 0; 72 | int rangeTo = 1; 73 | 74 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 75 | Assert.NotNull(exception); 76 | Assert.NotNull(exception.Message); 77 | Assert.Equal(expectedMessage, exception.Message); 78 | } 79 | 80 | [Theory] 81 | [InlineData(null, null)] 82 | [InlineData(null, "Please provide correct value")] 83 | [InlineData("SomeParameter", null)] 84 | [InlineData("SomeOtherParameter", "Value must be correct")] 85 | public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) 86 | { 87 | var input = new[] { 0, 1, 99 }; 88 | int rangeFrom = 0; 89 | int rangeTo = 1; 90 | 91 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 92 | Assert.NotNull(exception); 93 | Assert.Equal(expectedParamName, exception.ParamName); 94 | } 95 | 96 | public class CorrectClassData : IEnumerable 97 | { 98 | public IEnumerator GetEnumerator() 99 | { 100 | yield return new object[] { new List { 1000, 1200, 1500 }, 1000, 2000 }; 101 | yield return new object[] { new List { 100000, 2000, 120, 180000 }, 100, 200000 }; 102 | yield return new object[] { new List { 18, 128, 108 }, 0, 200 }; 103 | } 104 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 105 | } 106 | 107 | public class IncorrectClassData : IEnumerable 108 | { 109 | public IEnumerator GetEnumerator() 110 | { 111 | yield return new object[] { new List { 10, 12, 1500 }, 10, 1200 }; 112 | yield return new object[] { new List { 1000, 200, 120, 180000 }, 100, 150000 }; 113 | yield return new object[] { new List { 15, 120, 158 }, 10, 110 }; 114 | } 115 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 116 | } 117 | 118 | public class IncorrectRangeClassData : IEnumerable 119 | { 120 | public IEnumerator GetEnumerator() 121 | { 122 | yield return new object[] { new List { 10000, 1200, 15 }, 10000, 10 }; 123 | yield return new object[] { new List { 100010, 200, 120000, 180 }, 2000000, 150 }; 124 | yield return new object[] { new List { 52000, 86, 2500000 }, 20000000, 100 }; 125 | } 126 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForEnumerableShort.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForEnumerableShort 4 | { 5 | [Theory] 6 | [ClassData(typeof(CorrectClassData))] 7 | public void DoesNothingGivenInRangeValue(IEnumerable input, short rangeFrom, short rangeTo) 8 | { 9 | Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 10 | } 11 | 12 | [Theory] 13 | [ClassData(typeof(IncorrectClassData))] 14 | public void ThrowsGivenOutOfRangeValue(IEnumerable input, short rangeFrom, short rangeTo) 15 | { 16 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 17 | } 18 | 19 | [Theory] 20 | [ClassData(typeof(IncorrectRangeClassData))] 21 | public void ThrowsGivenInvalidArgumentValue(IEnumerable input, short rangeFrom, short rangeTo) 22 | { 23 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 24 | } 25 | 26 | [Theory] 27 | [ClassData(typeof(CorrectClassData))] 28 | public void ReturnsExpectedValueGivenInRangeValue(IEnumerable input, short rangeFrom, short rangeTo) 29 | { 30 | var result = Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 31 | Assert.Equal(input, result); 32 | } 33 | 34 | [Theory] 35 | [InlineData(null, "rangeFrom should be less or equal than rangeTo (Parameter 'parameterName')")] 36 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 37 | public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, string expectedMessage) 38 | { 39 | var input = new short[] { 0, 1, 99 }; 40 | short rangeFrom = 2; 41 | short rangeTo = 1; 42 | 43 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 44 | Assert.NotNull(exception); 45 | Assert.NotNull(exception.Message); 46 | Assert.Equal(expectedMessage, exception.Message); 47 | } 48 | 49 | [Theory] 50 | [InlineData(null, null)] 51 | [InlineData(null, "Please provide correct value")] 52 | [InlineData("SomeParameter", null)] 53 | [InlineData("SomeOtherParameter", "Value must be correct")] 54 | public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) 55 | { 56 | var input = new short[] { 0, 1, 99 }; 57 | short rangeFrom = 2; 58 | short rangeTo = 1; 59 | 60 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 61 | Assert.NotNull(exception); 62 | Assert.Equal(expectedParamName, exception.ParamName); 63 | } 64 | 65 | [Theory] 66 | [InlineData(null, "Input parameterName had out of range item(s) (Parameter 'parameterName')")] 67 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 68 | public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, string expectedMessage) 69 | { 70 | var input = new short[] { 0, 1, 99 }; 71 | short rangeFrom = 0; 72 | short rangeTo = 1; 73 | 74 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 75 | Assert.NotNull(exception); 76 | Assert.NotNull(exception.Message); 77 | Assert.Equal(expectedMessage, exception.Message); 78 | } 79 | 80 | [Theory] 81 | [InlineData(null, null)] 82 | [InlineData(null, "Please provide correct value")] 83 | [InlineData("SomeParameter", null)] 84 | [InlineData("SomeOtherParameter", "Value must be correct")] 85 | public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) 86 | { 87 | var input = new short[] { 0, 1, 99 }; 88 | short rangeFrom = 0; 89 | short rangeTo = 1; 90 | 91 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 92 | Assert.NotNull(exception); 93 | Assert.Equal(expectedParamName, exception.ParamName); 94 | } 95 | 96 | public class CorrectClassData : IEnumerable 97 | { 98 | public IEnumerator GetEnumerator() 99 | { 100 | yield return new object[] { new List { 10, 12, 15 }, 10, 20 }; 101 | yield return new object[] { new List { 100, 200, 120, 180 }, 100, 200 }; 102 | yield return new object[] { new List { 18, 128, 108 }, 0, 200 }; 103 | } 104 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 105 | } 106 | 107 | public class IncorrectClassData : IEnumerable 108 | { 109 | public IEnumerator GetEnumerator() 110 | { 111 | yield return new object[] { new List { 10, 12, 15 }, 10, 12 }; 112 | yield return new object[] { new List { 100, 200, 120, 180 }, 100, 150 }; 113 | yield return new object[] { new List { 15, 120, 158 }, 10, 110 }; 114 | } 115 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 116 | } 117 | 118 | public class IncorrectRangeClassData : IEnumerable 119 | { 120 | public IEnumerator GetEnumerator() 121 | { 122 | yield return new object[] { new List { 10, 12, 15 }, 10, 9 }; 123 | yield return new object[] { new List { 100, 200, 120, 180 }, 200, 150 }; 124 | yield return new object[] { new List { 52, 86, 250 }, 200, 100 }; 125 | } 126 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # To learn more about .editorconfig see https://aka.ms/editorconfigdocs 2 | ############################### 3 | # Core EditorConfig Options # 4 | ############################### 5 | # All files 6 | [*] 7 | indent_style = space 8 | # Code files 9 | [*.{cs,csx,vb,vbx}] 10 | indent_size = 4 11 | insert_final_newline = true 12 | charset = utf-8-bom 13 | ############################### 14 | # .NET Coding Conventions # 15 | ############################### 16 | [*.{cs,vb}] 17 | # Organize usings 18 | dotnet_sort_system_directives_first = true 19 | # this. preferences 20 | dotnet_style_qualification_for_field = false:silent 21 | dotnet_style_qualification_for_property = false:silent 22 | dotnet_style_qualification_for_method = false:silent 23 | dotnet_style_qualification_for_event = false:silent 24 | # Language keywords vs BCL types preferences 25 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent 26 | dotnet_style_predefined_type_for_member_access = true:silent 27 | # Parentheses preferences 28 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent 29 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent 30 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent 31 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent 32 | # Modifier preferences 33 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent 34 | dotnet_style_readonly_field = true:suggestion 35 | # Expression-level preferences 36 | dotnet_style_object_initializer = true:suggestion 37 | dotnet_style_collection_initializer = true:suggestion 38 | dotnet_style_explicit_tuple_names = true:suggestion 39 | dotnet_style_null_propagation = true:suggestion 40 | dotnet_style_coalesce_expression = true:suggestion 41 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent 42 | dotnet_style_prefer_inferred_tuple_names = true:suggestion 43 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion 44 | dotnet_style_prefer_auto_properties = true:silent 45 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent 46 | dotnet_style_prefer_conditional_expression_over_return = true:silent 47 | ############################### 48 | # Naming Conventions # 49 | ############################### 50 | # Style Definitions 51 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case 52 | # Use PascalCase for constant fields 53 | dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion 54 | dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields 55 | dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style 56 | dotnet_naming_symbols.constant_fields.applicable_kinds = field 57 | dotnet_naming_symbols.constant_fields.applicable_accessibilities = * 58 | dotnet_naming_symbols.constant_fields.required_modifiers = const 59 | ############################### 60 | # C# Coding Conventions # 61 | ############################### 62 | [*.cs] 63 | # var preferences 64 | csharp_style_var_for_built_in_types = true:silent 65 | csharp_style_var_when_type_is_apparent = true:silent 66 | csharp_style_var_elsewhere = true:silent 67 | # Expression-bodied members 68 | csharp_style_expression_bodied_methods = false:silent 69 | csharp_style_expression_bodied_constructors = false:silent 70 | csharp_style_expression_bodied_operators = false:silent 71 | csharp_style_expression_bodied_properties = true:silent 72 | csharp_style_expression_bodied_indexers = true:silent 73 | csharp_style_expression_bodied_accessors = true:silent 74 | # Pattern matching preferences 75 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 76 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 77 | # Null-checking preferences 78 | csharp_style_throw_expression = true:suggestion 79 | csharp_style_conditional_delegate_call = true:suggestion 80 | # Modifier preferences 81 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion 82 | # Expression-level preferences 83 | csharp_prefer_braces = true:silent 84 | csharp_style_deconstructed_variable_declaration = true:suggestion 85 | csharp_prefer_simple_default_expression = true:suggestion 86 | csharp_style_pattern_local_over_anonymous_function = true:suggestion 87 | csharp_style_inlined_variable_declaration = true:suggestion 88 | ############################### 89 | # C# Formatting Rules # 90 | ############################### 91 | # New line preferences 92 | csharp_new_line_before_open_brace = all 93 | csharp_new_line_before_else = true 94 | csharp_new_line_before_catch = true 95 | csharp_new_line_before_finally = true 96 | csharp_new_line_before_members_in_object_initializers = true 97 | csharp_new_line_before_members_in_anonymous_types = true 98 | csharp_new_line_between_query_expression_clauses = true 99 | # Indentation preferences 100 | csharp_indent_case_contents = true 101 | csharp_indent_switch_labels = true 102 | csharp_indent_labels = flush_left 103 | # Space preferences 104 | csharp_space_after_cast = false 105 | csharp_space_after_keywords_in_control_flow_statements = true 106 | csharp_space_between_method_call_parameter_list_parentheses = false 107 | csharp_space_between_method_declaration_parameter_list_parentheses = false 108 | csharp_space_between_parentheses = false 109 | csharp_space_before_colon_in_inheritance_clause = true 110 | csharp_space_after_colon_in_inheritance_clause = true 111 | csharp_space_around_binary_operators = before_and_after 112 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 113 | csharp_space_between_method_call_name_and_opening_parenthesis = false 114 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 115 | # Wrapping preferences 116 | csharp_preserve_single_line_statements = true 117 | csharp_preserve_single_line_blocks = true 118 | csharp_style_namespace_declarations = file_scoped:warning 119 | ############################### 120 | # VB Coding Conventions # 121 | ############################### 122 | [*.vb] 123 | # Modifier preferences 124 | visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion 125 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForEnumerableLong.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForEnumerableLong 4 | { 5 | [Theory] 6 | [ClassData(typeof(CorrectClassData))] 7 | public void DoesNothingGivenInRangeValue(IEnumerable input, long rangeFrom, long rangeTo) 8 | { 9 | Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 10 | } 11 | 12 | [Theory] 13 | [ClassData(typeof(IncorrectClassData))] 14 | public void ThrowsGivenOutOfRangeValue(IEnumerable input, long rangeFrom, long rangeTo) 15 | { 16 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 17 | } 18 | 19 | [Theory] 20 | [ClassData(typeof(IncorrectRangeClassData))] 21 | public void ThrowsGivenInvalidArgumentValue(IEnumerable input, long rangeFrom, long rangeTo) 22 | { 23 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 24 | } 25 | 26 | [Theory] 27 | [ClassData(typeof(CorrectClassData))] 28 | public void ReturnsExpectedValueGivenInRangeValue(IEnumerable input, long rangeFrom, long rangeTo) 29 | { 30 | var result = Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 31 | Assert.Equal(input, result); 32 | } 33 | 34 | [Theory] 35 | [InlineData(null, "rangeFrom should be less or equal than rangeTo (Parameter 'parameterName')")] 36 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 37 | public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, string expectedMessage) 38 | { 39 | var input = new long[] { 0, 1, 99 }; 40 | long rangeFrom = 2; 41 | long rangeTo = 1; 42 | 43 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 44 | Assert.NotNull(exception); 45 | Assert.NotNull(exception.Message); 46 | Assert.Equal(expectedMessage, exception.Message); 47 | } 48 | 49 | [Theory] 50 | [InlineData(null, null)] 51 | [InlineData(null, "Please provide correct value")] 52 | [InlineData("SomeParameter", null)] 53 | [InlineData("SomeOtherParameter", "Value must be correct")] 54 | public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) 55 | { 56 | var input = new long[] { 0, 1, 99 }; 57 | long rangeFrom = 2; 58 | long rangeTo = 1; 59 | 60 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 61 | Assert.NotNull(exception); 62 | Assert.Equal(expectedParamName, exception.ParamName); 63 | } 64 | 65 | [Theory] 66 | [InlineData(null, "Input parameterName had out of range item(s) (Parameter 'parameterName')")] 67 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 68 | public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, string expectedMessage) 69 | { 70 | var input = new long[] { 0, 1, 99 }; 71 | long rangeFrom = 0; 72 | long rangeTo = 1; 73 | 74 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 75 | Assert.NotNull(exception); 76 | Assert.NotNull(exception.Message); 77 | Assert.Equal(expectedMessage, exception.Message); 78 | } 79 | 80 | [Theory] 81 | [InlineData(null, null)] 82 | [InlineData(null, "Please provide correct value")] 83 | [InlineData("SomeParameter", null)] 84 | [InlineData("SomeOtherParameter", "Value must be correct")] 85 | public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) 86 | { 87 | var input = new long[] { 0, 1, 99 }; 88 | long rangeFrom = 0; 89 | long rangeTo = 1; 90 | 91 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 92 | Assert.NotNull(exception); 93 | Assert.Equal(expectedParamName, exception.ParamName); 94 | } 95 | 96 | public class CorrectClassData : IEnumerable 97 | { 98 | public IEnumerator GetEnumerator() 99 | { 100 | yield return new object[] { new List { long.MaxValue, 1200, long.MinValue}, long.MinValue, long.MaxValue }; 101 | yield return new object[] { new List { 1100000, 2000, 120, 180000 }, 100, 1200000 }; 102 | yield return new object[] { new List { 18, 128, 108 }, 0, 200 }; 103 | } 104 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 105 | } 106 | 107 | public class IncorrectClassData : IEnumerable 108 | { 109 | public IEnumerator GetEnumerator() 110 | { 111 | yield return new object[] { new List { 10, 12, 1500 }, 10, 1200 }; 112 | yield return new object[] { new List { 1000, 200, 120, 180000 }, 100, 150000 }; 113 | yield return new object[] { new List { 15, 120, 158 }, 10, 110 }; 114 | } 115 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 116 | } 117 | 118 | public class IncorrectRangeClassData : IEnumerable 119 | { 120 | public IEnumerator GetEnumerator() 121 | { 122 | yield return new object[] { new List { 10000, 1200, 15 }, 10000, 10 }; 123 | yield return new object[] { new List { 100010, 200, 120000, 180 }, 2000000, 150 }; 124 | yield return new object[] { new List { 52000, 86, 2500000 }, 20000000, 100 }; 125 | } 126 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForEnum.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForEnum 4 | { 5 | [Theory] 6 | [InlineData(0)] 7 | [InlineData(1)] 8 | [InlineData(2)] 9 | [InlineData(3)] 10 | [InlineData(4)] 11 | [InlineData(5)] 12 | public void DoesNothingGivenInRangeValue(int enumValue) 13 | { 14 | Guard.Against.EnumOutOfRange(enumValue, nameof(enumValue)); 15 | } 16 | 17 | 18 | [Theory] 19 | [InlineData(-1)] 20 | [InlineData(6)] 21 | [InlineData(10)] 22 | public void ThrowsGivenOutOfRangeValue(int enumValue) 23 | { 24 | var exception = Assert.Throws(() => Guard.Against.EnumOutOfRange(enumValue, nameof(enumValue))); 25 | Assert.Equal(nameof(enumValue), exception.ParamName); 26 | } 27 | 28 | [Theory] 29 | [InlineData(TestEnum.Budgie)] 30 | [InlineData(TestEnum.Cat)] 31 | [InlineData(TestEnum.Dog)] 32 | [InlineData(TestEnum.Fish)] 33 | [InlineData(TestEnum.Frog)] 34 | [InlineData(TestEnum.Penguin)] 35 | public void DoesNothingGivenInRangeEnum(TestEnum enumValue) 36 | { 37 | Guard.Against.EnumOutOfRange(enumValue, nameof(enumValue)); 38 | } 39 | 40 | 41 | [Theory] 42 | [InlineData((TestEnum)(-1))] 43 | [InlineData((TestEnum)6)] 44 | [InlineData((TestEnum)10)] 45 | public void ThrowsGivenOutOfRangeEnum(TestEnum enumValue) 46 | { 47 | var exception = Assert.Throws(() => Guard.Against.EnumOutOfRange(enumValue, nameof(enumValue))); 48 | Assert.Equal(nameof(enumValue), exception.ParamName); 49 | } 50 | 51 | [Theory] 52 | [InlineData(0)] 53 | [InlineData(1)] 54 | [InlineData(2)] 55 | [InlineData(3)] 56 | [InlineData(4)] 57 | [InlineData(5)] 58 | public void ReturnsExpectedValueGivenInRangeValue(int enumValue) 59 | { 60 | var expected = enumValue; 61 | Assert.Equal(expected, Guard.Against.EnumOutOfRange(enumValue, nameof(enumValue))); 62 | } 63 | 64 | [Theory] 65 | [InlineData(TestEnum.Budgie)] 66 | [InlineData(TestEnum.Cat)] 67 | [InlineData(TestEnum.Dog)] 68 | [InlineData(TestEnum.Fish)] 69 | [InlineData(TestEnum.Frog)] 70 | [InlineData(TestEnum.Penguin)] 71 | public void ReturnsExpectedValueGivenInRangeEnum(TestEnum enumValue) 72 | { 73 | var expected = enumValue; 74 | Assert.Equal(expected, Guard.Against.EnumOutOfRange(enumValue, nameof(enumValue))); 75 | } 76 | 77 | [Theory] 78 | [InlineData(null, "The value of argument 'parameterName' (99) is invalid for Enum type 'TestEnum'. (Parameter 'parameterName')")] 79 | [InlineData("Invalid enum value", "Invalid enum value")] 80 | public void ErrorMessageMatchesExpectedWhenInputIsEnum(string customMessage, string expectedMessage) 81 | { 82 | var exception = Assert.Throws( 83 | () => Guard.Against.EnumOutOfRange((TestEnum)99, "parameterName", customMessage)); 84 | Assert.NotNull(exception); 85 | Assert.NotNull(exception.Message); 86 | Assert.Equal(expectedMessage, exception.Message); 87 | } 88 | 89 | [Theory] 90 | [InlineData(null, "The value of argument 'xyz' (99) is invalid for Enum type 'TestEnum'. (Parameter 'xyz')")] 91 | [InlineData("Invalid enum value", "Invalid enum value")] 92 | public void ErrorMessageMatchesExpectedWhenInputIsEnumAndParamNameNotExplicitlyProvided(string customMessage, string expectedMessage) 93 | { 94 | var xyz = (TestEnum)99; 95 | var exception = Assert.Throws( 96 | () => Guard.Against.EnumOutOfRange(xyz, message: customMessage)); 97 | 98 | Assert.NotNull(exception); 99 | Assert.NotNull(exception.Message); 100 | Assert.Equal(expectedMessage, exception.Message); 101 | } 102 | 103 | [Theory] 104 | [InlineData(null, null)] 105 | [InlineData(null, "Please provide correct value")] 106 | [InlineData("SomeParameter", null)] 107 | [InlineData(null, "Value must be correct")] 108 | public void ExceptionParamNameMatchesExpectedWhenInputIsEnum(string expectedParamName, string customMessage) 109 | { 110 | var exception = Assert.Throws( 111 | () => Guard.Against.EnumOutOfRange((TestEnum)99, expectedParamName, customMessage)); 112 | Assert.NotNull(exception); 113 | Assert.Equal(expectedParamName, exception.ParamName); 114 | } 115 | 116 | [Theory] 117 | [InlineData(null, "The value of argument 'parameterName' (99) is invalid for Enum type 'TestEnum'. (Parameter 'parameterName')")] 118 | [InlineData("Invalid enum value", "Invalid enum value")] 119 | public void ErrorMessageMatchesExpectedWhenInputIsInt(string customMessage, string expectedMessage) 120 | { 121 | var exception = Assert.Throws( 122 | () => Guard.Against.EnumOutOfRange(99, "parameterName", customMessage)); 123 | Assert.NotNull(exception); 124 | Assert.NotNull(exception.Message); 125 | Assert.Equal(expectedMessage, exception.Message); 126 | } 127 | 128 | [Theory] 129 | [InlineData(null, null)] 130 | [InlineData(null, "Please provide correct value")] 131 | [InlineData("SomeParameter", null)] 132 | [InlineData(null, "Value must be correct")] 133 | public void ExceptionParamNameMatchesExpectedWhenInputIsInt(string expectedParamName, string customMessage) 134 | { 135 | var exception = Assert.Throws( 136 | () => Guard.Against.EnumOutOfRange(99, expectedParamName, customMessage)); 137 | Assert.NotNull(exception); 138 | Assert.Equal(expectedParamName, exception.ParamName); 139 | } 140 | } 141 | 142 | 143 | public enum TestEnum 144 | { 145 | Cat = 0, 146 | Dog = 1, 147 | Fish = 2, 148 | Budgie = 3, 149 | Penguin = 4, 150 | Frog = 5 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForEnumerableFloat.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForEnumerableFloat 4 | { 5 | [Theory] 6 | [ClassData(typeof(CorrectClassData))] 7 | public void DoesNothingGivenInRangeValue(IEnumerable input, float rangeFrom, float rangeTo) 8 | { 9 | Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 10 | } 11 | 12 | [Theory] 13 | [ClassData(typeof(IncorrectClassData))] 14 | public void ThrowsGivenOutOfRangeValue(IEnumerable input, float rangeFrom, float rangeTo) 15 | { 16 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 17 | } 18 | 19 | [Theory] 20 | [ClassData(typeof(IncorrectRangeClassData))] 21 | public void ThrowsGivenInvalidArgumentValue(IEnumerable input, float rangeFrom, float rangeTo) 22 | { 23 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 24 | } 25 | 26 | [Theory] 27 | [ClassData(typeof(CorrectClassData))] 28 | public void ReturnsExpectedValueGivenInRangeValue(IEnumerable input, float rangeFrom, float rangeTo) 29 | { 30 | var result = Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 31 | Assert.Equal(input, result); 32 | } 33 | 34 | [Theory] 35 | [InlineData(null, "rangeFrom should be less or equal than rangeTo (Parameter 'parameterName')")] 36 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 37 | public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, string expectedMessage) 38 | { 39 | var input = new[] { 0f, 1f, 99f }; 40 | float rangeFrom = 2f; 41 | float rangeTo = 1f; 42 | 43 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 44 | Assert.NotNull(exception); 45 | Assert.NotNull(exception.Message); 46 | Assert.Equal(expectedMessage, exception.Message); 47 | } 48 | 49 | [Theory] 50 | [InlineData(null, null)] 51 | [InlineData(null, "Please provide correct value")] 52 | [InlineData("SomeParameter", null)] 53 | [InlineData("SomeOtherParameter", "Value must be correct")] 54 | public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) 55 | { 56 | var input = new[] { 0f, 1f, 99f }; 57 | float rangeFrom = 2f; 58 | float rangeTo = 1f; 59 | 60 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 61 | Assert.NotNull(exception); 62 | Assert.Equal(expectedParamName, exception.ParamName); 63 | } 64 | 65 | [Theory] 66 | [InlineData(null, "Input parameterName had out of range item(s) (Parameter 'parameterName')")] 67 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 68 | public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, string expectedMessage) 69 | { 70 | var input = new[] { 0f, 1f, 99f }; 71 | float rangeFrom = 0f; 72 | float rangeTo = 1f; 73 | 74 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 75 | Assert.NotNull(exception); 76 | Assert.NotNull(exception.Message); 77 | Assert.Equal(expectedMessage, exception.Message); 78 | } 79 | 80 | [Theory] 81 | [InlineData(null, null)] 82 | [InlineData(null, "Please provide correct value")] 83 | [InlineData("SomeParameter", null)] 84 | [InlineData("SomeOtherParameter", "Value must be correct")] 85 | public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) 86 | { 87 | var input = new[] { 0f, 1f, 99f }; 88 | float rangeFrom = 0f; 89 | float rangeTo = 1f; 90 | 91 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 92 | Assert.NotNull(exception); 93 | Assert.Equal(expectedParamName, exception.ParamName); 94 | } 95 | 96 | public class CorrectClassData : IEnumerable 97 | { 98 | public IEnumerator GetEnumerator() 99 | { 100 | yield return new object[] {new List {float.MaxValue, 1.0f, float.MinValue}, float.MinValue, float.MaxValue}; 101 | yield return new object[] {new List {1100000.0f, 2000.8f, 120.5f, 180000.0f}, 100.0,1200000.0}; 102 | yield return new object[] {new List {0.1f, 128.0f, 200.5f}, 0.1, 200.5}; 103 | } 104 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 105 | } 106 | 107 | public class IncorrectClassData : IEnumerable 108 | { 109 | public IEnumerator GetEnumerator() 110 | { 111 | yield return new object[] { new List { 10.0f, 12.0f, 1500.0f }, 10.0, 1200.0 }; 112 | yield return new object[] { new List { 1000.0f, 200.0f, 120.0f, 180000.0f }, 100.0, 150000.0 }; 113 | yield return new object[] { new List { 15.0f, 120.0f, 158.0f }, 10.1, 110.0 }; 114 | } 115 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 116 | } 117 | 118 | public class IncorrectRangeClassData : IEnumerable 119 | { 120 | public IEnumerator GetEnumerator() 121 | { 122 | yield return new object[] { new List { 10000.0f, 1200.0f, 15.0f }, 10000.0, 10.0 }; 123 | yield return new object[] { new List { 100010.0f, 200.0f, 120000.0f, 180.0f }, 2000000.0, 150.0 }; 124 | yield return new object[] { new List { 52000.0f, 86.0f, 2500000.0f }, 20000000.0, 100.0 }; 125 | } 126 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForEnumerableDecimal.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForEnumerableDecimal 4 | { 5 | [Theory] 6 | [ClassData(typeof(CorrectClassData))] 7 | public void DoesNothingGivenInRangeValue(IEnumerable input, decimal rangeFrom, decimal rangeTo) 8 | { 9 | Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 10 | } 11 | 12 | [Theory] 13 | [ClassData(typeof(IncorrectClassData))] 14 | public void ThrowsGivenOutOfRangeValue(IEnumerable input, decimal rangeFrom, decimal rangeTo) 15 | { 16 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 17 | } 18 | 19 | [Theory] 20 | [ClassData(typeof(IncorrectRangeClassData))] 21 | public void ThrowsGivenInvalidArgumentValue(IEnumerable input, decimal rangeFrom, decimal rangeTo) 22 | { 23 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 24 | } 25 | 26 | [Theory] 27 | [ClassData(typeof(CorrectClassData))] 28 | public void ReturnsExpectedValueGivenInRangeValue(IEnumerable input, decimal rangeFrom, decimal rangeTo) 29 | { 30 | var result = Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 31 | Assert.Equal(input, result); 32 | } 33 | 34 | [Theory] 35 | [InlineData(null, "rangeFrom should be less or equal than rangeTo (Parameter 'parameterName')")] 36 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 37 | public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, string expectedMessage) 38 | { 39 | var input = new[] { 0m, 1m, 99m }; 40 | decimal rangeFrom = 2m; 41 | decimal rangeTo = 1m; 42 | 43 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 44 | Assert.NotNull(exception); 45 | Assert.NotNull(exception.Message); 46 | Assert.Equal(expectedMessage, exception.Message); 47 | } 48 | 49 | [Theory] 50 | [InlineData(null, null)] 51 | [InlineData(null, "Please provide correct value")] 52 | [InlineData("SomeParameter", null)] 53 | [InlineData("SomeOtherParameter", "Value must be correct")] 54 | public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) 55 | { 56 | var input = new[] { 0m, 1m, 99m }; 57 | decimal rangeFrom = 2m; 58 | decimal rangeTo = 1m; 59 | 60 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 61 | Assert.NotNull(exception); 62 | Assert.Equal(expectedParamName, exception.ParamName); 63 | } 64 | 65 | [Theory] 66 | [InlineData(null, "Input parameterName had out of range item(s) (Parameter 'parameterName')")] 67 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 68 | public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, string expectedMessage) 69 | { 70 | var input = new[] { 0m, 1m, 99m }; 71 | decimal rangeFrom = 0m; 72 | decimal rangeTo = 1m; 73 | 74 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 75 | Assert.NotNull(exception); 76 | Assert.NotNull(exception.Message); 77 | Assert.Equal(expectedMessage, exception.Message); 78 | } 79 | 80 | [Theory] 81 | [InlineData(null, null)] 82 | [InlineData(null, "Please provide correct value")] 83 | [InlineData("SomeParameter", null)] 84 | [InlineData("SomeOtherParameter", "Value must be correct")] 85 | public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) 86 | { 87 | var input = new [] { 0m, 1m, 99m }; 88 | decimal rangeFrom = 0m; 89 | decimal rangeTo = 1m; 90 | 91 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 92 | Assert.NotNull(exception); 93 | Assert.Equal(expectedParamName, exception.ParamName); 94 | } 95 | 96 | public class CorrectClassData : IEnumerable 97 | { 98 | public IEnumerator GetEnumerator() 99 | { 100 | yield return new object[] { new List { decimal.MaxValue, 1.0m, decimal.MinValue }, decimal.MinValue, decimal.MaxValue }; 101 | yield return new object[] { new List { 1100000.0m, 2000.8m, 120.5m, 180000.0m }, 100.0, 1200000.0 }; 102 | yield return new object[] { new List { 0.1m, 128, 200.5m }, 0.1, 200.5 }; 103 | } 104 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 105 | } 106 | 107 | public class IncorrectClassData : IEnumerable 108 | { 109 | public IEnumerator GetEnumerator() 110 | { 111 | yield return new object[] { new List { 10.0m, 12.0m, 1500.0m }, 10.0, 1200.0 }; 112 | yield return new object[] { new List { 1000.0m, 200.0m, 120.0m, 180000.0m }, 100.0, 150000.0 }; 113 | yield return new object[] { new List { 5.0m, 120.0m, 158.0m }, 10.1, 110.0 }; 114 | } 115 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 116 | } 117 | 118 | public class IncorrectRangeClassData : IEnumerable 119 | { 120 | public IEnumerator GetEnumerator() 121 | { 122 | yield return new object[] { new List { 10000.0m, 1200.0m, 15.0m }, 10000.0, 10.0 }; 123 | yield return new object[] { new List { 100010.0m, 200.0m, 120000.0m, 0.2m }, 2000000.0, 150.0 }; 124 | yield return new object[] { new List { 52000.0m, 86.0m, 2500000.0m }, 20000000.0, 100.0 }; 125 | } 126 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForEnumerableDouble.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForEnumerableDouble 4 | { 5 | [Theory] 6 | [ClassData(typeof(CorrectClassData))] 7 | public void DoesNothingGivenInRangeValue(IEnumerable input, double rangeFrom, double rangeTo) 8 | { 9 | Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 10 | } 11 | 12 | [Theory] 13 | [ClassData(typeof(IncorrectClassData))] 14 | public void ThrowsGivenOutOfRangeValue(IEnumerable input, double rangeFrom, double rangeTo) 15 | { 16 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 17 | } 18 | 19 | [Theory] 20 | [ClassData(typeof(IncorrectRangeClassData))] 21 | public void ThrowsGivenInvalidArgumentValue(IEnumerable input, double rangeFrom, double rangeTo) 22 | { 23 | Assert.Throws(() => Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo)); 24 | } 25 | 26 | [Theory] 27 | [ClassData(typeof(CorrectClassData))] 28 | public void ReturnsExpectedValueGivenInRangeValue(IEnumerable input, double rangeFrom, double rangeTo) 29 | { 30 | var result = Guard.Against.OutOfRange(input, nameof(input), rangeFrom, rangeTo); 31 | Assert.Equal(input, result); 32 | } 33 | 34 | [Theory] 35 | [InlineData(null, "rangeFrom should be less or equal than rangeTo (Parameter 'parameterName')")] 36 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 37 | public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, string expectedMessage) 38 | { 39 | var input = new [] { 0d, 1d, 99d }; 40 | double rangeFrom = 2d; 41 | double rangeTo = 1d; 42 | 43 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 44 | Assert.NotNull(exception); 45 | Assert.NotNull(exception.Message); 46 | Assert.Equal(expectedMessage, exception.Message); 47 | } 48 | 49 | [Theory] 50 | [InlineData(null, null)] 51 | [InlineData(null, "Please provide correct value")] 52 | [InlineData("SomeParameter", null)] 53 | [InlineData("SomeOtherParameter", "Value must be correct")] 54 | public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) 55 | { 56 | var input = new[] { 0d, 1d, 99d }; 57 | double rangeFrom = 2d; 58 | double rangeTo = 1d; 59 | 60 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 61 | Assert.NotNull(exception); 62 | Assert.Equal(expectedParamName, exception.ParamName); 63 | } 64 | 65 | [Theory] 66 | [InlineData(null, "Input parameterName had out of range item(s) (Parameter 'parameterName')")] 67 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 68 | public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, string expectedMessage) 69 | { 70 | var input = new[] { 0d, 1d, 99d }; 71 | double rangeFrom = 0d; 72 | double rangeTo = 1d; 73 | 74 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 75 | Assert.NotNull(exception); 76 | Assert.NotNull(exception.Message); 77 | Assert.Equal(expectedMessage, exception.Message); 78 | } 79 | 80 | [Theory] 81 | [InlineData(null, null)] 82 | [InlineData(null, "Please provide correct value")] 83 | [InlineData("SomeParameter", null)] 84 | [InlineData("SomeOtherParameter", "Value must be correct")] 85 | public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) 86 | { 87 | var input = new[] { 0d, 1d, 99d }; 88 | double rangeFrom = 0d; 89 | double rangeTo = 1d; 90 | 91 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 92 | Assert.NotNull(exception); 93 | Assert.Equal(expectedParamName, exception.ParamName); 94 | } 95 | 96 | public class CorrectClassData : IEnumerable 97 | { 98 | public IEnumerator GetEnumerator() 99 | { 100 | yield return new object[] 101 | { 102 | new List {double.MaxValue, 1.0, double.MinValue}, double.MinValue, double.MaxValue 103 | }; 104 | yield return new object[] {new List {1100000.0, 2000.8, 120.5, 180000.0}, 100.0, 1200000.0}; 105 | yield return new object[] {new List {0.1, 128, 200.5}, 0.1, 200.5}; 106 | } 107 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 108 | } 109 | 110 | public class IncorrectClassData : IEnumerable 111 | { 112 | public IEnumerator GetEnumerator() 113 | { 114 | yield return new object[] { new List { 10.0, 12.0, 1500.0 }, 10.0, 1200.0 }; 115 | yield return new object[] { new List { 1000.0, 200.0, 120.0, 180000.0 }, 100.0, 150000.0 }; 116 | yield return new object[] { new List { 15.0, 120.0, 158.0 }, 10.1, 110.0 }; 117 | } 118 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 119 | } 120 | 121 | public class IncorrectRangeClassData : IEnumerable 122 | { 123 | public IEnumerator GetEnumerator() 124 | { 125 | yield return new object[] { new List { 10000.0, 1200.0, 15.0}, 10000.0, 10.0 }; 126 | yield return new object[] { new List { 100010.0, 200.0, 120000.0, 0.2 }, 2000000.0, 150.0 }; 127 | yield return new object[] { new List { 52000.0, 86.0, 2500000.0 }, 20000000.0, 100.0 }; 128 | } 129 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 130 | } 131 | 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstOutOfRangeForEnumerableTimeSpan.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstOutOfRangeForEnumerableTimeSpan 4 | { 5 | [Theory] 6 | [ClassData(typeof(CorrectClassData))] 7 | public void DoesNothingGivenInRangeValue(IEnumerable input, int rangeFrom, int rangeTo) 8 | { 9 | var inputTimeSpan = input.Select(i => TimeSpan.FromSeconds(i)); 10 | var rangeFromTimeSpan = TimeSpan.FromSeconds(rangeFrom); 11 | var rangeToTimeSpan = TimeSpan.FromSeconds(rangeTo); 12 | 13 | Guard.Against.OutOfRange(inputTimeSpan, nameof(inputTimeSpan), rangeFromTimeSpan, rangeToTimeSpan); 14 | } 15 | 16 | [Theory] 17 | [ClassData(typeof(IncorrectClassData))] 18 | public void ThrowsGivenOutOfRangeValue(IEnumerable input, int rangeFrom, int rangeTo) 19 | { 20 | var inputTimeSpan = input.Select(i => TimeSpan.FromSeconds(i)); 21 | var rangeFromTimeSpan = TimeSpan.FromSeconds(rangeFrom); 22 | var rangeToTimeSpan = TimeSpan.FromSeconds(rangeTo); 23 | 24 | Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, nameof(inputTimeSpan), rangeFromTimeSpan, rangeToTimeSpan)); 25 | } 26 | 27 | [Theory] 28 | [ClassData(typeof(IncorrectRangeClassData))] 29 | public void ThrowsGivenInvalidArgumentValue(IEnumerable input, int rangeFrom, int rangeTo) 30 | { 31 | var inputTimeSpan = input.Select(i => TimeSpan.FromSeconds(i)); 32 | var rangeFromTimeSpan = TimeSpan.FromSeconds(rangeFrom); 33 | var rangeToTimeSpan = TimeSpan.FromSeconds(rangeTo); 34 | 35 | Assert.Throws(() => Guard.Against.OutOfRange(inputTimeSpan, nameof(inputTimeSpan), rangeFromTimeSpan, rangeToTimeSpan)); 36 | } 37 | 38 | [Theory] 39 | [ClassData(typeof(CorrectClassData))] 40 | public void ReturnsExpectedValueGivenInRangeValue(IEnumerable input, int rangeFrom, int rangeTo) 41 | { 42 | var inputTimeSpan = input.Select(i => TimeSpan.FromSeconds(i)); 43 | var rangeFromTimeSpan = TimeSpan.FromSeconds(rangeFrom); 44 | var rangeToTimeSpan = TimeSpan.FromSeconds(rangeTo); 45 | 46 | var result = Guard.Against.OutOfRange(inputTimeSpan, nameof(inputTimeSpan), rangeFromTimeSpan, rangeToTimeSpan); 47 | Assert.Equal(inputTimeSpan, result); 48 | } 49 | 50 | [Theory] 51 | [InlineData(null, "rangeFrom should be less or equal than rangeTo (Parameter 'parameterName')")] 52 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 53 | public void ErrorMessageMatchesExpectedWhenRangeIsInvalid(string customMessage, string expectedMessage) 54 | { 55 | var input = Enumerable.Range(0, 3).Select(i => TimeSpan.FromSeconds(i)); 56 | var rangeFrom = TimeSpan.FromSeconds(2); 57 | var rangeTo = TimeSpan.FromSeconds(1); 58 | 59 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 60 | Assert.NotNull(exception); 61 | Assert.NotNull(exception.Message); 62 | Assert.Equal(expectedMessage, exception.Message); 63 | } 64 | 65 | [Theory] 66 | [InlineData(null, null)] 67 | [InlineData(null, "Please provide correct value")] 68 | [InlineData("SomeParameter", null)] 69 | [InlineData("SomeOtherParameter", "Value must be correct")] 70 | public void ExceptionParamNameMatchesExpectedRangeIsInvalid(string expectedParamName, string customMessage) 71 | { 72 | var input = Enumerable.Range(0, 3).Select(i => TimeSpan.FromSeconds(i)); 73 | var rangeFrom = TimeSpan.FromSeconds(2); 74 | var rangeTo = TimeSpan.FromSeconds(1); 75 | 76 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 77 | Assert.NotNull(exception); 78 | Assert.Equal(expectedParamName, exception.ParamName); 79 | } 80 | 81 | [Theory] 82 | [InlineData(null, "Input parameterName had out of range item(s) (Parameter 'parameterName')")] 83 | [InlineData("Timespan range", "Timespan range (Parameter 'parameterName')")] 84 | public void ErrorMessageMatchesExpectedWhenInputIsInvalid(string customMessage, string expectedMessage) 85 | { 86 | var input = Enumerable.Range(0, 3).Select(i => TimeSpan.FromSeconds(i)); 87 | var rangeFrom = TimeSpan.FromSeconds(0); 88 | var rangeTo = TimeSpan.FromSeconds(1); 89 | 90 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, "parameterName", rangeFrom, rangeTo, customMessage)); 91 | Assert.NotNull(exception); 92 | Assert.NotNull(exception.Message); 93 | Assert.Equal(expectedMessage, exception.Message); 94 | } 95 | 96 | [Theory] 97 | [InlineData(null, null)] 98 | [InlineData(null, "Please provide correct value")] 99 | [InlineData("SomeParameter", null)] 100 | [InlineData("SomeOtherParameter", "Value must be correct")] 101 | public void ExceptionParamNameMatchesExpectedInputIsInvalid(string expectedParamName, string customMessage) 102 | { 103 | var input = Enumerable.Range(0, 3).Select(i => TimeSpan.FromSeconds(i)); 104 | var rangeFrom = TimeSpan.FromSeconds(0); 105 | var rangeTo = TimeSpan.FromSeconds(1); 106 | 107 | var exception = Assert.Throws(() => Guard.Against.OutOfRange(input, expectedParamName, rangeFrom, rangeTo, customMessage)); 108 | Assert.NotNull(exception); 109 | Assert.Equal(expectedParamName, exception.ParamName); 110 | } 111 | 112 | public class CorrectClassData : IEnumerable 113 | { 114 | public IEnumerator GetEnumerator() 115 | { 116 | yield return new object[] { new List { 1000, 1200, 1500 }, 1000, 2000 }; 117 | yield return new object[] { new List { 100000, 2000, 120, 180000 }, 100, 200000 }; 118 | yield return new object[] { new List { 18, 128, 108 }, 0, 200 }; 119 | } 120 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 121 | } 122 | 123 | public class IncorrectClassData : IEnumerable 124 | { 125 | public IEnumerator GetEnumerator() 126 | { 127 | yield return new object[] { new List { 10, 12, 1500 }, 10, 1200 }; 128 | yield return new object[] { new List { 1000, 200, 120, 180000 }, 100, 150000 }; 129 | yield return new object[] { new List { 15, 120, 158 }, 10, 110 }; 130 | } 131 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 132 | } 133 | 134 | public class IncorrectRangeClassData : IEnumerable 135 | { 136 | public IEnumerator GetEnumerator() 137 | { 138 | yield return new object[] { new List { 10000, 1200, 15 }, 10000, 10 }; 139 | yield return new object[] { new List { 100010, 200, 120000, 180 }, 2000000, 150 }; 140 | yield return new object[] { new List { 52000, 86, 2500000 }, 20000000, 100 }; 141 | } 142 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/GuardClauses/GuardAgainstZeroExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.CompilerServices; 4 | using JetBrainsInvokerParameterNameAttribute = JetBrains.Annotations.InvokerParameterNameAttribute; 5 | using JetBrainsNotNullAttribute = JetBrains.Annotations.NotNullAttribute; 6 | 7 | namespace Ardalis.GuardClauses 8 | { 9 | public static partial class GuardClauseExtensions 10 | { 11 | /// 12 | /// Throws an if is zero. 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// Optional. Custom error message 18 | /// if the value is not zero. 19 | /// 20 | #if NETSTANDARD || NETFRAMEWORK 21 | public static int Zero([JetBrainsNotNull] this IGuardClause guardClause, 22 | int input, 23 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 24 | string? message = null) 25 | #else 26 | public static int Zero([JetBrainsNotNull] this IGuardClause guardClause, 27 | int input, 28 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null, 29 | string? message = null) 30 | #endif 31 | { 32 | return Zero(guardClause, input, parameterName!, message); 33 | } 34 | 35 | /// 36 | /// Throws an if is zero. 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// Optional. Custom error message 42 | /// if the value is not zero. 43 | /// 44 | #if NETSTANDARD || NETFRAMEWORK 45 | public static long Zero([JetBrainsNotNull] this IGuardClause guardClause, 46 | long input, 47 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 48 | string? message = null) 49 | #else 50 | public static long Zero([JetBrainsNotNull] this IGuardClause guardClause, 51 | long input, 52 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null, 53 | string? message = null) 54 | #endif 55 | { 56 | return Zero(guardClause, input, parameterName!, message); 57 | } 58 | 59 | /// 60 | /// Throws an if is zero. 61 | /// 62 | /// 63 | /// 64 | /// 65 | /// Optional. Custom error message 66 | /// if the value is not zero. 67 | /// 68 | #if NETSTANDARD || NETFRAMEWORK 69 | public static decimal Zero([JetBrainsNotNull] this IGuardClause guardClause, 70 | decimal input, 71 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 72 | string? message = null) 73 | #else 74 | public static decimal Zero([JetBrainsNotNull] this IGuardClause guardClause, 75 | decimal input, 76 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null, 77 | string? message = null) 78 | #endif 79 | { 80 | return Zero(guardClause, input, parameterName!, message); 81 | } 82 | 83 | /// 84 | /// Throws an if is zero. 85 | /// 86 | /// 87 | /// 88 | /// 89 | /// Optional. Custom error message 90 | /// if the value is not zero. 91 | /// 92 | #if NETSTANDARD || NETFRAMEWORK 93 | public static float Zero([JetBrainsNotNull] this IGuardClause guardClause, 94 | float input, 95 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 96 | string? message = null) 97 | #else 98 | public static float Zero([JetBrainsNotNull] this IGuardClause guardClause, 99 | float input, 100 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null, 101 | string? message = null) 102 | #endif 103 | { 104 | return Zero(guardClause, input, parameterName!, message); 105 | } 106 | 107 | /// 108 | /// Throws an if is zero. 109 | /// 110 | /// 111 | /// 112 | /// 113 | /// Optional. Custom error message 114 | /// if the value is not zero. 115 | /// 116 | #if NETSTANDARD || NETFRAMEWORK 117 | public static double Zero([JetBrainsNotNull] this IGuardClause guardClause, 118 | double input, 119 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 120 | string? message = null) 121 | #else 122 | public static double Zero([JetBrainsNotNull] this IGuardClause guardClause, 123 | double input, 124 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null, 125 | string? message = null) 126 | #endif 127 | { 128 | return Zero(guardClause, input, parameterName!, message); 129 | } 130 | 131 | /// 132 | /// Throws an if is zero. 133 | /// 134 | /// 135 | /// 136 | /// 137 | /// if the value is not zero. 138 | /// 139 | #if NETSTANDARD || NETFRAMEWORK 140 | public static TimeSpan Zero([JetBrainsNotNull] this IGuardClause guardClause, 141 | TimeSpan input, 142 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName) 143 | #else 144 | public static TimeSpan Zero([JetBrainsNotNull] this IGuardClause guardClause, 145 | TimeSpan input, 146 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null) 147 | #endif 148 | { 149 | return Zero(guardClause, input, parameterName!); 150 | } 151 | 152 | /// 153 | /// Throws an if is zero. 154 | /// 155 | /// 156 | /// 157 | /// 158 | /// Optional. Custom error message 159 | /// if the value is not zero. 160 | /// 161 | private static T Zero([JetBrainsNotNull] this IGuardClause guardClause, T input, [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, string? message = null) where T : struct 162 | { 163 | if (EqualityComparer.Default.Equals(input, default(T))) 164 | { 165 | throw new ArgumentException(message ?? $"Required input {parameterName} cannot be zero.", parameterName); 166 | } 167 | 168 | return input; 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/GuardClauses/GuardAgainstOutOfRangeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Runtime.CompilerServices; 6 | using JetBrainsInvokerParameterNameAttribute = JetBrains.Annotations.InvokerParameterNameAttribute; 7 | using JetBrainsNotNullAttribute = JetBrains.Annotations.NotNullAttribute; 8 | 9 | namespace Ardalis.GuardClauses 10 | { 11 | public static partial class GuardClauseExtensions 12 | { 13 | /// 14 | /// Throws an if is not a valid enum value. 15 | /// 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// Optional. Custom error message 21 | /// if the value is not out of range. 22 | /// 23 | #if NETSTANDARD || NETFRAMEWORK 24 | public static int EnumOutOfRange([JetBrainsNotNull] this IGuardClause guardClause, 25 | int input, 26 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 27 | string? message = null) where T : struct, Enum 28 | #else 29 | public static int EnumOutOfRange([JetBrainsNotNull] this IGuardClause guardClause, 30 | int input, 31 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null, 32 | string? message = null) where T : struct, Enum 33 | #endif 34 | { 35 | if (!Enum.IsDefined(typeof(T), input)) 36 | { 37 | if (string.IsNullOrEmpty(message)) 38 | { 39 | throw new InvalidEnumArgumentException(parameterName, input, typeof(T)); 40 | } 41 | throw new InvalidEnumArgumentException(message); 42 | } 43 | 44 | return input; 45 | } 46 | 47 | /// 48 | /// Throws an if is not a valid enum value. 49 | /// 50 | /// 51 | /// 52 | /// 53 | /// 54 | /// /// Optional. Custom error message 55 | /// if the value is not out of range. 56 | /// 57 | #if NETSTANDARD || NETFRAMEWORK 58 | public static T EnumOutOfRange([JetBrainsNotNull] this IGuardClause guardClause, 59 | T input, 60 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 61 | string? message = null) where T : struct, Enum 62 | #else 63 | public static T EnumOutOfRange([JetBrainsNotNull] this IGuardClause guardClause, 64 | T input, 65 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null, 66 | string? message = null) where T : struct, Enum 67 | #endif 68 | { 69 | if (!Enum.IsDefined(typeof(T), input)) 70 | { 71 | if (string.IsNullOrEmpty(message)) 72 | { 73 | throw new InvalidEnumArgumentException(parameterName, Convert.ToInt32(input), typeof(T)); 74 | } 75 | throw new InvalidEnumArgumentException(message); 76 | } 77 | 78 | return input; 79 | } 80 | 81 | /// 82 | /// Throws an if any 's item is less than or greater than . 83 | /// 84 | /// 85 | /// 86 | /// 87 | /// 88 | /// 89 | /// Optional. Custom error message 90 | /// if any item is not out of range. 91 | /// 92 | /// 93 | public static IEnumerable OutOfRange(this IGuardClause guardClause, IEnumerable input, string parameterName, T rangeFrom, T rangeTo, string? message = null) where T : IComparable, IComparable 94 | { 95 | if (rangeFrom.CompareTo(rangeTo) > 0) 96 | { 97 | throw new ArgumentException(message ?? $"{nameof(rangeFrom)} should be less or equal than {nameof(rangeTo)}", parameterName); 98 | } 99 | 100 | if (input.Any(x => x.CompareTo(rangeFrom) < 0 || x.CompareTo(rangeTo) > 0)) 101 | { 102 | if (string.IsNullOrEmpty(message)) 103 | { 104 | throw new ArgumentOutOfRangeException(parameterName, message ?? $"Input {parameterName} had out of range item(s)"); 105 | } 106 | throw new ArgumentOutOfRangeException(parameterName, message); 107 | } 108 | 109 | return input; 110 | } 111 | /// 112 | /// Throws an if is not in the range of valid SqlDateTime values. 113 | /// 114 | /// 115 | /// 116 | /// 117 | /// Optional. Custom error message 118 | /// if the value is in the range of valid SqlDateTime values. 119 | /// 120 | #if NETSTANDARD || NETFRAMEWORK 121 | public static DateTime OutOfSQLDateRange([JetBrainsNotNull] this IGuardClause guardClause, 122 | DateTime input, 123 | [JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName, 124 | string? message = null) 125 | #else 126 | public static DateTime OutOfSQLDateRange([JetBrainsNotNull] this IGuardClause guardClause, 127 | DateTime input, 128 | [JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null, 129 | string? message = null) 130 | #endif 131 | { 132 | // System.Data is unavailable in .NET Standard so we can't use SqlDateTime. 133 | const long sqlMinDateTicks = 552877920000000000; 134 | const long sqlMaxDateTicks = 3155378975999970000; 135 | 136 | return OutOfRange(guardClause, input, parameterName!, new DateTime(sqlMinDateTicks), new DateTime(sqlMaxDateTicks), message); 137 | } 138 | 139 | /// 140 | /// Throws an if is less than or greater than . 141 | /// 142 | /// 143 | /// 144 | /// 145 | /// 146 | /// 147 | /// Optional. Custom error message 148 | /// if the value is not out of range. 149 | /// 150 | public static T OutOfRange(this IGuardClause guardClause, T input, 151 | [JetBrainsInvokerParameterName] string parameterName, 152 | T rangeFrom, 153 | T rangeTo, 154 | string? message = null) where T : IComparable, IComparable 155 | { 156 | if (rangeFrom.CompareTo(rangeTo) > 0) 157 | { 158 | throw new ArgumentException(message ?? $"{nameof(rangeFrom)} should be less or equal than {nameof(rangeTo)}", parameterName); 159 | } 160 | 161 | if (input.CompareTo(rangeFrom) < 0 || input.CompareTo(rangeTo) > 0) 162 | { 163 | if (string.IsNullOrEmpty(message)) 164 | { 165 | throw new ArgumentOutOfRangeException(parameterName, $"Input {parameterName} was out of range"); 166 | } 167 | throw new ArgumentOutOfRangeException(parameterName, message); 168 | } 169 | 170 | return input; 171 | } 172 | 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /test/GuardClauses.UnitTests/GuardAgainstNullOrEmpty.cs: -------------------------------------------------------------------------------- 1 | namespace GuardClauses.UnitTests 2 | { 3 | public class GuardAgainstNullOrEmpty 4 | { 5 | [Fact] 6 | public void DoesNothingGivenNonEmptyStringValue() 7 | { 8 | Guard.Against.NullOrEmpty("a", "string"); 9 | Guard.Against.NullOrEmpty("1", "aNumericString"); 10 | } 11 | 12 | [Fact] 13 | public void DoesNothingGivenNonEmptyGuidValue() 14 | { 15 | Guard.Against.NullOrEmpty(Guid.NewGuid(), "guid"); 16 | } 17 | 18 | [Fact] 19 | public void DoesNothingGivenNonEmptyEnumerable() 20 | { 21 | Guard.Against.NullOrEmpty(new[] { "foo", "bar" }, "stringArray"); 22 | Guard.Against.NullOrEmpty(new[] { 1, 2 }, "intArray"); 23 | } 24 | 25 | [Fact] 26 | public void ThrowsGivenNullString() 27 | { 28 | string? nullString = null; 29 | Assert.Throws(() => Guard.Against.NullOrEmpty(nullString, "nullString")); 30 | } 31 | 32 | [Fact] 33 | public void ThrowsGivenEmptyString() 34 | { 35 | Assert.Throws(() => Guard.Against.NullOrEmpty("", "emptyString")); 36 | } 37 | 38 | [Fact] 39 | public void ThrowsGivenNullGuid() 40 | { 41 | Guid? nullGuid = null; 42 | Assert.Throws(() => Guard.Against.NullOrEmpty(nullGuid, "nullGuid")); 43 | } 44 | 45 | [Fact] 46 | public void ThrowsGivenEmptyGuid() 47 | { 48 | Assert.Throws(() => Guard.Against.NullOrEmpty(Guid.Empty, "emptyGuid")); 49 | } 50 | 51 | [Fact] 52 | public void ThrowsGivenEmptyEnumerable() 53 | { 54 | Assert.Throws(() => Guard.Against.NullOrEmpty(Enumerable.Empty(), "emptyStringEnumerable")); 55 | } 56 | 57 | [Fact] 58 | public void ReturnsExpectedValueWhenGivenValidValue() 59 | { 60 | Assert.Equal("a", Guard.Against.NullOrEmpty("a", "string")); 61 | Assert.Equal("1", Guard.Against.NullOrEmpty("1", "aNumericString")); 62 | 63 | var collection1 = new[] { "foo", "bar" }; 64 | Assert.Equal(collection1, Guard.Against.NullOrEmpty(collection1, "stringArray")); 65 | 66 | var collection2 = new[] { 1, 2 }; 67 | Assert.Equal(collection2, Guard.Against.NullOrEmpty(collection2, "intArray")); 68 | } 69 | 70 | [Theory] 71 | [InlineData(null, "Required input xyz was empty. (Parameter 'xyz')")] 72 | [InlineData("Value is empty", "Value is empty (Parameter 'xyz')")] 73 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvidedGivenStringValue(string customMessage, string expectedMessage) 74 | { 75 | string xyz = string.Empty; 76 | 77 | var exception = Assert.Throws(() => Guard.Against.NullOrEmpty(xyz, message: customMessage)); 78 | 79 | Assert.NotNull(exception); 80 | Assert.NotNull(exception.Message); 81 | Assert.Contains(expectedMessage, exception.Message); 82 | } 83 | 84 | [Theory] 85 | [InlineData(null, "Required input xyz was empty. (Parameter 'xyz')")] 86 | [InlineData("Value is empty", "Value is empty (Parameter 'xyz')")] 87 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvidedGivenGuidValue(string customMessage, string expectedMessage) 88 | { 89 | Guid xyz = Guid.Empty; 90 | 91 | var exception = Assert.Throws(() => Guard.Against.NullOrEmpty(xyz, message: customMessage)); 92 | 93 | Assert.NotNull(exception); 94 | Assert.NotNull(exception.Message); 95 | Assert.Contains(expectedMessage, exception.Message); 96 | } 97 | 98 | [Theory] 99 | [InlineData(null, "Required input xyz was empty. (Parameter 'xyz')")] 100 | [InlineData("Value is empty", "Value is empty (Parameter 'xyz')")] 101 | public void ErrorMessageMatchesExpectedWhenNameNotExplicitlyProvidedGivenIEnumerableValue(string customMessage, string expectedMessage) 102 | { 103 | IEnumerable xyz = Enumerable.Empty(); 104 | 105 | var exception = Assert.Throws(() => Guard.Against.NullOrEmpty(xyz, message: customMessage)); 106 | 107 | Assert.NotNull(exception); 108 | Assert.NotNull(exception.Message); 109 | Assert.Contains(expectedMessage, exception.Message); 110 | } 111 | 112 | [Theory] 113 | [InlineData(null, "Required input parameterName was empty. (Parameter 'parameterName')")] 114 | [InlineData("Value is empty", "Value is empty (Parameter 'parameterName')")] 115 | public void ErrorMessageMatchesExpectedWhenInputIsEmpty(string customMessage, string expectedMessage) 116 | { 117 | string emptyString = string.Empty; 118 | Guid emptyGuid = Guid.Empty; 119 | IEnumerable emptyEnumerable = Enumerable.Empty(); 120 | 121 | var clausesToEvaluate = new List 122 | { 123 | () => Guard.Against.NullOrEmpty(emptyString, "parameterName", customMessage), 124 | () => Guard.Against.NullOrEmpty(emptyGuid, "parameterName", customMessage), 125 | () => Guard.Against.NullOrEmpty(emptyEnumerable, "parameterName", customMessage) 126 | }; 127 | 128 | foreach (var clauseToEvaluate in clausesToEvaluate) 129 | { 130 | var exception = Assert.Throws(clauseToEvaluate); 131 | Assert.NotNull(exception); 132 | Assert.NotNull(exception.Message); 133 | Assert.Equal(expectedMessage, exception.Message); 134 | } 135 | } 136 | 137 | [Theory] 138 | [InlineData(null, "Value cannot be null. (Parameter 'parameterName')")] 139 | [InlineData("Value must be correct", "Value must be correct (Parameter 'parameterName')")] 140 | public void ErrorMessageMatchesExpectedWhenInputIsNull(string customMessage, string expectedMessage) 141 | { 142 | string? nullString = null; 143 | Guid? nullGuid = null; 144 | IEnumerable? nullEnumerable = null; 145 | 146 | var clausesToEvaluate = new List 147 | { 148 | () => Guard.Against.NullOrEmpty(nullString, "parameterName", customMessage), 149 | () => Guard.Against.NullOrEmpty(nullGuid, "parameterName", customMessage), 150 | () => Guard.Against.NullOrEmpty(nullEnumerable, "parameterName", customMessage) 151 | }; 152 | 153 | foreach (var clauseToEvaluate in clausesToEvaluate) 154 | { 155 | var exception = Assert.Throws(clauseToEvaluate); 156 | Assert.NotNull(exception); 157 | Assert.NotNull(exception.Message); 158 | Assert.Equal(expectedMessage, exception.Message); 159 | } 160 | } 161 | 162 | [Theory] 163 | [InlineData(null, null)] 164 | [InlineData(null, "Please provide correct value")] 165 | [InlineData("SomeParameter", null)] 166 | [InlineData("SomeOtherParameter", "Value must be correct")] 167 | public void ExceptionParamNameMatchesExpectedWhenInputIsEmpty(string expectedParamName, string customMessage) 168 | { 169 | string emptyString = string.Empty; 170 | Guid emptyGuid = Guid.Empty; 171 | IEnumerable emptyEnumerable = Enumerable.Empty(); 172 | 173 | var clausesToEvaluate = new List 174 | { 175 | () => Guard.Against.NullOrEmpty(emptyString, expectedParamName, customMessage), 176 | () => Guard.Against.NullOrEmpty(emptyGuid, expectedParamName, customMessage), 177 | () => Guard.Against.NullOrEmpty(emptyEnumerable, expectedParamName, customMessage) 178 | }; 179 | 180 | foreach (var clauseToEvaluate in clausesToEvaluate) 181 | { 182 | var exception = Assert.Throws(clauseToEvaluate); 183 | Assert.NotNull(exception); 184 | Assert.Equal(expectedParamName, exception.ParamName); 185 | } 186 | } 187 | 188 | [Theory] 189 | [InlineData(null, null)] 190 | [InlineData(null, "Please provide correct value")] 191 | [InlineData("SomeParameter", null)] 192 | [InlineData("SomeOtherParameter", "Value must be correct")] 193 | public void ExceptionParamNameMatchesExpectedWhenInputIsNull(string expectedParamName, string customMessage) 194 | { 195 | string? nullString = null; 196 | Guid? nullGuid = null; 197 | IEnumerable? nullEnumerable = null; 198 | 199 | var clausesToEvaluate = new List 200 | { 201 | () => Guard.Against.NullOrEmpty(nullString, expectedParamName, customMessage), 202 | () => Guard.Against.NullOrEmpty(nullGuid, expectedParamName, customMessage), 203 | () => Guard.Against.NullOrEmpty(nullEnumerable, expectedParamName, customMessage) 204 | }; 205 | 206 | foreach (var clauseToEvaluate in clausesToEvaluate) 207 | { 208 | var exception = Assert.Throws(clauseToEvaluate); 209 | Assert.NotNull(exception); 210 | Assert.Equal(expectedParamName, exception.ParamName); 211 | } 212 | } 213 | } 214 | } 215 | --------------------------------------------------------------------------------