├── .gitignore
├── nuget.config
├── Argument
├── Internal
│ ├── ValidatedNotNullAttribute.cs
│ ├── NotNullAtribute.cs
│ └── JetBrains.Annotations.cs
├── Argument.csproj
└── Argument.cs
├── Argument.Tests
├── GlobalSuppressions.cs
├── Argument.Tests.csproj
├── CodeAnalysisTests.cs
├── NullableFlowTests.cs
└── ArgumentTests.cs
├── Directory.Build.props
├── License.txt
├── .github
└── workflows
│ └── build-and-publish.yml
├── .editorconfig
├── Readme.md
└── Argument.sln
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .vs/
3 | *.user
4 | artifacts/
5 | project.lock.json
6 | bin/
7 | obj/
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Argument/Internal/ValidatedNotNullAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ArgumentInternal {
4 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
5 | internal sealed class ValidatedNotNullAttribute : Attribute
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Argument/Internal/NotNullAtribute.cs:
--------------------------------------------------------------------------------
1 | namespace System.Diagnostics.CodeAnalysis {
2 | // https://github.com/dotnet/roslyn/issues/37544#issuecomment-533639747
3 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
4 | internal sealed class NotNullAttribute : Attribute {}
5 | }
--------------------------------------------------------------------------------
/Argument.Tests/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project.
3 | // Project-level suppressions either have no target or are given
4 | // a specific target and scoped to a namespace, type, member, etc.
5 |
6 | using System.Diagnostics.CodeAnalysis;
7 |
8 | [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores")]
9 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 9.0
4 | enable
5 | true
6 |
7 |
8 |
9 |
10 | all
11 | runtime; build; native; contentfiles; analyzers; buildtransitive
12 |
13 |
14 |
--------------------------------------------------------------------------------
/License.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013, Andrey Shchekin
2 |
3 | Permission to use, copy, modify, and/or distribute this software for any purpose
4 | with or without fee is hereby granted, provided that the above copyright notice
5 | and this permission notice appear in all copies.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
8 | TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
9 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
10 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
11 | PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
12 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--------------------------------------------------------------------------------
/.github/workflows/build-and-publish.yml:
--------------------------------------------------------------------------------
1 | name: 'Build and Publish'
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | build-and-publish:
6 | name: 'Build and Publish'
7 | runs-on: windows-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: actions/setup-dotnet@v1
11 | with:
12 | dotnet-version: 5.0.x
13 |
14 | - run: dotnet build --configuration Release
15 | - run: dotnet test --no-build --configuration Release
16 | - run: dotnet pack --no-build --output . --configuration Release
17 |
18 | - run: dotnet nuget push Argument.*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{secrets.NUGET_API_KEY}} --skip-duplicate
19 | if: github.ref == 'refs/heads/main'
20 |
21 | - uses: actions/upload-artifact@v2
22 | with:
23 | name: Package
24 | path: Argument.*.nupkg
--------------------------------------------------------------------------------
/Argument.Tests/Argument.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net5.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers; buildtransitive
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | trim_trailing_whitespace = true
8 | insert_final_newline = false
9 |
10 | [*.csproj]
11 | indent_size = 2
12 |
13 | [*.cs]
14 | csharp_new_line_before_open_brace = none
15 | csharp_style_var_for_built_in_types = true:warning
16 | csharp_style_var_when_type_is_apparent = true:warning
17 | csharp_style_var_elsewhere = true:warning
18 |
19 | # CA1822: Mark members as static
20 | dotnet_diagnostic.CA1822.severity = none
21 |
22 | # CA1062: Validate arguments of public methods
23 | dotnet_diagnostic.CA1062.severity = error
24 |
25 | # IDE rules should not need explicit levels in the future,
26 | # but for now Microsoft.CodeAnalysis.CSharp.CodeStyle requires
27 | # this during the build. Also warnings-as-errors do not work
28 | # on those, so we set them to error.
29 |
30 | # IDE0007: Use 'var' instead of explicit type
31 | dotnet_diagnostic.IDE0007.severity = error
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | ## Overview
2 |
3 | This project includes a single class, `Argument`, useful for argument validation/guard methods.
4 | You can get the NuGet package at: https://nuget.org/packages/Argument.
5 |
6 | [](https://ci.appveyor.com/project/ashmind/argument)
7 |
8 | ## Example
9 |
10 | public MyService(OtherService other) {
11 | _other = Argument.NotNull("other", other);
12 | }
13 |
14 | ## Features
15 |
16 | 1. ReSharper annotations (Argument.ExternalAnnotations.xml).
17 | Note that there is `[NotNull]` annotation on values that are being tested — that is so you do not forget to add `[NotNull]` to your arguments.
18 | 2. For .NET 4.5 Code Contracts: `[ContractArgumentValidator]`.
19 | I did not have time to test if it actually works in Visual Studio though.
20 | 3. `Argument.Ex` is an extensibility point. Example:
21 |
22 | public static T Magic(this Argument.Extensible _, string name, T value) {
23 | //..
24 | }
25 |
26 | Argument.Ex.Magic("name", value);
27 |
--------------------------------------------------------------------------------
/Argument.Tests/CodeAnalysisTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | // nothing here should generate warnings (which are set to produce errors anyways)
4 | public class CodeAnalysisTests {
5 | public int CA1062_ArgumentCheck_NotRequired_NotNull(string argument) {
6 | Argument.NotNull(nameof(argument), argument);
7 | return argument.Length;
8 | }
9 |
10 | public int CA1062_ArgumentCheck_NotRequired_NotNullOrEmpty_String(string argument) {
11 | Argument.NotNullOrEmpty(nameof(argument), argument);
12 | return argument.Length;
13 | }
14 |
15 | public int CA1062_ArgumentCheck_NotRequired_NotNullOrEmpty_Array(int[] argument) {
16 | Argument.NotNullOrEmpty(nameof(argument), argument);
17 | return argument.Length;
18 | }
19 |
20 | public int CA1062_ArgumentCheck_NotRequired_NotNullOrEmpty_List(IReadOnlyList argument) {
21 | Argument.NotNullOrEmpty(nameof(argument), argument);
22 | return argument.Count;
23 | }
24 |
25 | public int CA1062_ArgumentCheck_NotRequired_NotNullOrWhiteSpace_String(string argument) {
26 | Argument.NotNullOrWhiteSpace(nameof(argument), argument);
27 | return argument.Length;
28 | }
29 |
30 | public int CA1062_ArgumentCheck_NotRequired_NotNullAndCast(string argument) {
31 | Argument.NotNullAndCast(nameof(argument), argument);
32 | return argument.Length;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Argument.Tests/NullableFlowTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | // nothing here should generate warnings (which are set to produce errors anyways)
4 | public class NullableFlowTests {
5 | public int CS8602_ValueIsNotNullable_After_NotNull(string? argument) {
6 | Argument.NotNull(nameof(argument), argument!);
7 | return argument.Length;
8 | }
9 |
10 | public int CS8602_ValueIsNotNullable_After_NotNullOrEmpty_String(string? argument) {
11 | Argument.NotNullOrEmpty(nameof(argument), argument!);
12 | return argument.Length;
13 | }
14 |
15 | public int CS8602_ValueIsNotNullable_After_NotNullOrEmpty_Array(int[]? argument) {
16 | Argument.NotNullOrEmpty(nameof(argument), argument!);
17 | return argument.Length;
18 | }
19 |
20 | public int CS8602_ValueIsNotNullable_After_NotNullOrEmpty_List(IReadOnlyList? argument) {
21 | Argument.NotNullOrEmpty(nameof(argument), argument!);
22 | return argument.Count;
23 | }
24 |
25 | public int CS8602_ValueIsNotNullable_After_NotNullOrWhiteSpace_String(string? argument) {
26 | Argument.NotNullOrWhiteSpace(nameof(argument), argument!);
27 | return argument.Length;
28 | }
29 |
30 | public int CS8602_ValueIsNotNullable_After_NotNullAndCast(string? argument) {
31 | Argument.NotNullAndCast(nameof(argument), argument!);
32 | return argument.Length;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Argument/Argument.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
5 |
6 |
7 | Argument validation methods, for example:
8 | this.user = Argument.NotNull("user", user).
9 |
10 | Less fancy than approaches based on lambdas/anonymous classes, but less scary performance-wise (given that argument checks are often all over the place).
11 |
12 | Annotations: C# 8 nullable reference types, ReSharper, Microsoft.CodeQuality.Analyzers, Code Contracts (.NET 4.5 only).
13 | Copyright (c) 2013–2020 Andrey Shchekin
14 | 1.4.0
15 | Andrey Shchekin
16 | net45;netstandard11
17 | Argument
18 | Argument
19 | contracts;validation;argument
20 | https://github.com/ashmind/argument
21 | ISC
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Argument.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27428.2015
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{48B9BF9A-498F-4238-9F1E-CE9FAB616B09}"
7 | ProjectSection(SolutionItems) = preProject
8 | Argument.cs = Argument.cs
9 | Argument.ExternalAnnotations.xml = Argument.ExternalAnnotations.xml
10 | License.txt = License.txt
11 | EndProjectSection
12 | EndProject
13 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Properties", "Properties", "{E40A2F3C-917C-47F5-A3F7-C89DF7C5939A}"
14 | ProjectSection(SolutionItems) = preProject
15 | Properties\AssemblyInfo.cs = Properties\AssemblyInfo.cs
16 | EndProjectSection
17 | EndProject
18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Argument", "Argument\Argument.csproj", "{8C077462-1F3C-493A-924D-F1DA430E1E1C}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Argument.Tests", "Argument.Tests\Argument.Tests.csproj", "{0F628144-FFB1-4095-BFC6-FFD4295D869D}"
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|Any CPU = Debug|Any CPU
25 | Debug|Mixed Platforms = Debug|Mixed Platforms
26 | Debug|x86 = Debug|x86
27 | Release|Any CPU = Release|Any CPU
28 | Release|Mixed Platforms = Release|Mixed Platforms
29 | Release|x86 = Release|x86
30 | EndGlobalSection
31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
32 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
35 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
36 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Debug|x86.ActiveCfg = Debug|Any CPU
37 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Debug|x86.Build.0 = Debug|Any CPU
38 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
41 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
42 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Release|x86.ActiveCfg = Release|Any CPU
43 | {8C077462-1F3C-493A-924D-F1DA430E1E1C}.Release|x86.Build.0 = Release|Any CPU
44 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
47 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
48 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Debug|x86.ActiveCfg = Debug|Any CPU
49 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Debug|x86.Build.0 = Debug|Any CPU
50 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
53 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Release|Mixed Platforms.Build.0 = Release|Any CPU
54 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Release|x86.ActiveCfg = Release|Any CPU
55 | {0F628144-FFB1-4095-BFC6-FFD4295D869D}.Release|x86.Build.0 = Release|Any CPU
56 | EndGlobalSection
57 | GlobalSection(SolutionProperties) = preSolution
58 | HideSolutionNode = FALSE
59 | EndGlobalSection
60 | GlobalSection(NestedProjects) = preSolution
61 | {E40A2F3C-917C-47F5-A3F7-C89DF7C5939A} = {48B9BF9A-498F-4238-9F1E-CE9FAB616B09}
62 | EndGlobalSection
63 | GlobalSection(ExtensibilityGlobals) = postSolution
64 | SolutionGuid = {D1B12DA8-F185-4BA1-B149-B87D3554872D}
65 | EndGlobalSection
66 | EndGlobal
67 |
--------------------------------------------------------------------------------
/Argument/Internal/JetBrains.Annotations.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 |
5 | #pragma warning disable 1591
6 | // ReSharper disable UnusedMember.Global
7 | // ReSharper disable MemberCanBePrivate.Global
8 | // ReSharper disable UnusedAutoPropertyAccessor.Global
9 | // ReSharper disable IntroduceOptionalParameters.Global
10 | // ReSharper disable MemberCanBeProtected.Global
11 | // ReSharper disable InconsistentNaming
12 |
13 | // ReSharper disable once CheckNamespace
14 | namespace JetBrains.Annotations {
15 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event)]
16 | internal sealed class CanBeNullAttribute : Attribute { }
17 |
18 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event)]
19 | internal sealed class NotNullAttribute : Attribute { }
20 |
21 | [AttributeUsage(AttributeTargets.Parameter)]
22 | internal sealed class InvokerParameterNameAttribute : Attribute { }
23 |
24 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
25 | internal sealed class ContractAnnotationAttribute : Attribute {
26 | public ContractAnnotationAttribute([NotNull] string contract)
27 | : this(contract, false) { }
28 |
29 | public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) {
30 | Contract = contract;
31 | ForceFullStates = forceFullStates;
32 | }
33 |
34 | public string Contract { get; private set; }
35 | public bool ForceFullStates { get; private set; }
36 | }
37 |
38 | [AttributeUsage(AttributeTargets.All)]
39 | [Conditional("JETBRAINS_ANNOTATIONS")]
40 | internal sealed class UsedImplicitlyAttribute : Attribute {
41 | public UsedImplicitlyAttribute()
42 | : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
43 |
44 | public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
45 | : this(useKindFlags, ImplicitUseTargetFlags.Default) { }
46 |
47 | public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
48 | : this(ImplicitUseKindFlags.Default, targetFlags) { }
49 |
50 | public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) {
51 | UseKindFlags = useKindFlags;
52 | TargetFlags = targetFlags;
53 | }
54 |
55 | public ImplicitUseKindFlags UseKindFlags { get; private set; }
56 | public ImplicitUseTargetFlags TargetFlags { get; private set; }
57 | }
58 |
59 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.GenericParameter)]
60 | [Conditional("JETBRAINS_ANNOTATIONS")]
61 | internal sealed class MeansImplicitUseAttribute : Attribute {
62 | public MeansImplicitUseAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
63 |
64 | public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags)
65 | : this(useKindFlags, ImplicitUseTargetFlags.Default) { }
66 |
67 | public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags)
68 | : this(ImplicitUseKindFlags.Default, targetFlags) { }
69 |
70 | public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) {
71 | UseKindFlags = useKindFlags;
72 | TargetFlags = targetFlags;
73 | }
74 |
75 | [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; }
76 | [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; }
77 | }
78 |
79 | [Flags]
80 | internal enum ImplicitUseKindFlags {
81 | Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
82 | Access = 1,
83 | Assign = 2,
84 | InstantiatedWithFixedConstructorSignature = 4,
85 | InstantiatedNoFixedConstructorSignature = 8,
86 | }
87 |
88 | [Flags]
89 | internal enum ImplicitUseTargetFlags {
90 | Default = Itself,
91 | Itself = 1,
92 | Members = 2,
93 | WithMembers = Itself | Members
94 | }
95 |
96 | [MeansImplicitUse]
97 | [Conditional("JETBRAINS_ANNOTATIONS")]
98 | internal sealed class PublicAPIAttribute : Attribute {
99 | public PublicAPIAttribute() { }
100 | public PublicAPIAttribute([NotNull] string comment) {
101 | Comment = comment;
102 | }
103 |
104 | public string? Comment { get; private set; }
105 | }
106 |
107 | [AttributeUsage(AttributeTargets.Parameter)]
108 | internal sealed class InstantHandleAttribute : Attribute { }
109 |
110 | [AttributeUsage(AttributeTargets.Method)]
111 | internal sealed class AssertionMethodAttribute : Attribute { }
112 |
113 | [AttributeUsage(AttributeTargets.Parameter)]
114 | internal sealed class AssertionConditionAttribute : Attribute {
115 | public AssertionConditionAttribute(AssertionConditionType conditionType) {
116 | ConditionType = conditionType;
117 | }
118 |
119 | public AssertionConditionType ConditionType { get; private set; }
120 | }
121 |
122 | internal enum AssertionConditionType {
123 | IS_TRUE = 0,
124 | IS_FALSE = 1,
125 | IS_NULL = 2,
126 | IS_NOT_NULL = 3,
127 | }
128 |
129 | [AttributeUsage(AttributeTargets.Parameter)]
130 | internal sealed class NoEnumerationAttribute : Attribute { }
131 | }
--------------------------------------------------------------------------------
/Argument.Tests/ArgumentTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.Immutable;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Linq.Expressions;
6 | using System.Reflection;
7 | using Xunit;
8 |
9 | // Broken by nullable reference types
10 | #pragma warning disable xUnit1019 // MemberData must reference a member providing a valid data type
11 |
12 | // ReSharper disable CheckNamespace
13 | [SuppressMessage("Design", "CA1062:Validate arguments of public methods")]
14 | public class ArgumentTests {
15 | [Theory]
16 | [MemberData(nameof(NullVariants))]
17 | public void NotNullVariant_ThrowsArgumentNullException_WithCorrectMessage_WhenValueIsNull(Expression> validateExpression) {
18 | var validate = validateExpression.Compile();
19 | var exception = Assert.Throws(() => validate("x"));
20 | Assert.Equal(new ArgumentNullException("x").Message, exception.Message);
21 | }
22 |
23 | [Theory]
24 | [MemberData(nameof(NullVariants))]
25 | public void NotNullVariant_ThrowsArgumentNullException_WithCorrectParamName_WhenValueIsNull(Expression> validateExpression) {
26 | var validate = validateExpression.Compile();
27 | var exception = Assert.Throws(() => validate("x"));
28 | Assert.Equal("x", exception.ParamName);
29 | }
30 |
31 | [Theory]
32 | [MemberData(nameof(EmptyVariants))]
33 | public void NotNullOrEmptyVariant_ThrowsArgumentException_WithCorrectParamName_WhenValueIsEmpty(Expression> validateExpression) {
34 | var validate = validateExpression.Compile();
35 | var exception = Assert.Throws(() => validate("x"));
36 | Assert.Equal("x", exception.ParamName);
37 | }
38 |
39 | [Theory]
40 | [MemberData(nameof(WhiteSpaceVariants))]
41 | public void NotNullOrWhiteSpaceVariant_ThrowsArgumentException_WithCorrectParamName_WhenValueIsWhiteSpace(Expression> validateExpression) {
42 | var validate = validateExpression.Compile();
43 | var exception = Assert.Throws(() => validate("x"));
44 | Assert.Equal("x", exception.ParamName);
45 | }
46 |
47 | [Theory]
48 | [MemberData(nameof(IncorrectTypeVariants))]
49 | public void CastVariant_ThrowsArgumentException_WithCorrectParamName_WhenValueHasIncorrectType(Expression> validateExpression) {
50 | var validate = validateExpression.Compile();
51 | var exception = Assert.Throws(() => validate("x"));
52 | Assert.Equal("x", exception.ParamName);
53 | }
54 |
55 | [Theory]
56 | [MemberData(nameof(OutOfRangeVariants))]
57 | public void RangeVariant_ThrowsArgumentOutOfRangeException_WithCorrectParamName_WhenValueIsOutOfRange(Expression> validateExpression) {
58 | var validate = validateExpression.Compile();
59 | var exception = Assert.Throws(() => validate("x"));
60 | Assert.Equal("x", exception.ParamName);
61 | }
62 |
63 | [Theory]
64 | [MemberData(nameof(SuccessVariants))]
65 | public void AnyVariant_ReturnsArgumentValue_WhenSuccessful(T argument, Expression> validateExpression) {
66 | var validate = validateExpression.Compile();
67 | var result = validate(argument);
68 |
69 | if (typeof(T).GetTypeInfo().IsValueType) {
70 | Assert.Equal(argument, result);
71 | }
72 | else {
73 | #pragma warning disable xUnit2005 // Do not use identity check on value type
74 | Assert.Same(argument, result);
75 | #pragma warning restore xUnit2005 // Do not use identity check on value type
76 | }
77 | }
78 |
79 | public static IEnumerable