Skip to content

Commit

Permalink
Add an option to allow false boolean values, bump version to 1.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
kasthack committed Jan 6, 2022
1 parent 0000000 commit 0000000
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<PublishDocumentationFile>true</PublishDocumentationFile>
<PublishDocumentationFiles>true</PublishDocumentationFiles>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>1.1.0</PackageVersion>
<PackageVersion>1.1.1</PackageVersion>
<PackageDescription>.NotEmpty&lt;T&gt;() test extension</PackageDescription>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageTags>kasthack nunit xunit mstest test empty null notempty emptinness nullability</PackageTags>
Expand Down
14 changes: 7 additions & 7 deletions src/kasthack.NotEmpty.Core/AssertContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,25 @@ internal class AssertContext

public string Path => "(value)" + string.Concat(this.pathSegments.Reverse());

public bool IsArrayElement { get; set; } = false;
public ElementKind ElementKind { get; set; } = Core.ElementKind.Root;

public AssertContext(AssertOptions options) => this.Options = options;

public IDisposable EnterPath(string segment, bool isArray) => new PathContext(this, segment, isArray);
public IDisposable EnterPath(string segment, ElementKind elementKind) => new PathContext(this, segment, elementKind);

private struct PathContext : IDisposable
{
private readonly AssertContext context;
private readonly bool originalIsArrayElement;
private readonly ElementKind originalElementKind;
private bool disposed = false;

public PathContext(AssertContext context, string segment, bool isArray)
public PathContext(AssertContext context, string segment, ElementKind elementKind)
{
this.context = context ?? throw new ArgumentNullException(nameof(context));
this.originalIsArrayElement = this.context.IsArrayElement;
this.originalElementKind = this.context.ElementKind;

this.context.pathSegments.Push(segment);
this.context.IsArrayElement = isArray;
this.context.ElementKind = elementKind;
}

public void Dispose()
Expand All @@ -44,7 +44,7 @@ public void Dispose()
{
this.disposed = true;
this.context.pathSegments.Pop();
this.context.IsArrayElement = this.originalIsArrayElement;
this.context.ElementKind = this.originalElementKind;
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/kasthack.NotEmpty.Core/AssertOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,10 @@ public class AssertOptions
/// Allows empty strings but not nulls.
/// </summary>
public bool AllowEmptyCollections { get; set; } = false;

/// <summary>
/// Allows bool properties to be false.
/// </summary>
public bool AllowFalseBooleanProperties { get; set; } = false;
}
}
11 changes: 11 additions & 0 deletions src/kasthack.NotEmpty.Core/ElementKind.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace kasthack.NotEmpty.Core
{
internal enum ElementKind
{
Unknown,
Root,
Property,
ArrayElement,
DictionaryElement,
}
}
21 changes: 13 additions & 8 deletions src/kasthack.NotEmpty.Core/NotEmptyExtensionsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@ internal void NotEmptyInternal<T>(T? value, AssertContext context)
var path = context.Path;
string message = GetEmptyMessage(path);
this.Assert(value is not null, message, path); // fast lane
if (
!(context.Options.AllowZerosInNumberArrays &&
context.IsArrayElement &&
value is byte or sbyte or short or ushort or char or int or uint or long or ulong or float or double or decimal or BigInteger
var skipDueToBeingNumberInArrayWhenAllowedByOptions = context.ElementKind == ElementKind.ArrayElement
&& context.Options.AllowZerosInNumberArrays
&& value is byte or sbyte or short or ushort or char or int or uint or long or ulong or float or double or decimal or BigInteger
#if NET5_0_OR_GREATER
or Half or nint or nuint
#endif
))
;
var skipDueToBeingBooleanPropertyWhenAllowedByOptions = context.ElementKind == ElementKind.Property && value is bool;
if (!(
skipDueToBeingBooleanPropertyWhenAllowedByOptions
||
skipDueToBeingNumberInArrayWhenAllowedByOptions
))
{
this.Assert(!EqualityComparer<T>.Default.Equals(default!, value!), message, path);
}
Expand Down Expand Up @@ -68,7 +73,7 @@ or TimeOnly _
foreach (var key in d.Keys)
{
cnt++;
using (context.EnterPath($"[{key}]", false))
using (context.EnterPath($"[{key}]", ElementKind.DictionaryElement))
{
this.NotEmptyBoxed(d[key], context);
}
Expand All @@ -84,7 +89,7 @@ or TimeOnly _
var index = 0;
foreach (var item in e)
{
using (context.EnterPath($"[{index++}]", true))
using (context.EnterPath($"[{index++}]", ElementKind.ArrayElement))
{
this.NotEmptyBoxed(item, context);
}
Expand All @@ -99,7 +104,7 @@ or TimeOnly _
default:
foreach (var pathValue in CachedPropertyExtractor<T>.GetProperties(value))
{
using (context.EnterPath($".{pathValue.Path}", false))
using (context.EnterPath($".{pathValue.Path}", ElementKind.Property))
{
this.NotEmptyBoxed(pathValue.Value, context);
}
Expand Down
22 changes: 22 additions & 0 deletions src/kasthack.NotEmpty.Tests/NotEmptyTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public abstract class NotEmptyTestBase

#region Numbers


[Fact]
public void NotDefaultPrimitiveWorks() => this.Action(new { Value = 1 });

Expand All @@ -50,6 +51,9 @@ public abstract class NotEmptyTestBase
[Fact]
public void BoxedDefaultPrimitiveThrows() => Assert.ThrowsAny<Exception>(() => this.Action(new { Value = (object)0 }));

[Fact]
public void BoxedDefaultPrimitiveThrowsAsRoot() => Assert.ThrowsAny<Exception>(() => this.Action(0));

[Fact]
public void NullNullableThrows() => Assert.ThrowsAny<Exception>(() => this.Action(new { Value = new Nullable<int>(), }));

Expand Down Expand Up @@ -158,6 +162,24 @@ public struct InfiniteNestedStruct
}
#endregion

#region Booleans

[Fact]
public void FalseThrows() => Assert.ThrowsAny<Exception>(() => this.Action(false));

[Fact]
public void TrueWorks() => this.Action(true);

[Fact]
public void FalseDoesntThrowWhenAllowed() => this.Action(new { Value = true }, new AssertOptions { AllowFalseBooleanProperties = true });

[Fact]
public void FalseThrowsWhenAllowedForDifferentKind() => Assert.ThrowsAny<Exception>(() => this.Action(false, new AssertOptions { AllowFalseBooleanProperties = true }));

[Fact]
public void FalseThrowsWhenAllowedForDifferentKindV2() => Assert.ThrowsAny<Exception>(() => this.Action(new[] { false }, new AssertOptions { AllowFalseBooleanProperties = true }));
#endregion

protected void Action(object? value, AssertOptions? options = null) => this.action(value, options);
}
}

0 comments on commit 0000000

Please sign in to comment.