Skip to content

Commit

Permalink
Add IsNotEmpty checks for collection (#30)
Browse files Browse the repository at this point in the history
(MINOR)
  • Loading branch information
mgrosperrin authored Feb 23, 2024
1 parent 6091505 commit f64c994
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 11 deletions.
18 changes: 10 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ env:
DOTNET_VERSION: '8.0.x'

permissions:
checks: write
contents: read

jobs:
Expand Down Expand Up @@ -45,19 +46,20 @@ jobs:
run: dotnet build -c Release -p:Version=${{ steps.version.outputs.version}}

- name: Run tests
run: dotnet test tests/MGR.Guard.UnitTests/MGR.Guard.UnitTests.csproj -c Release --no-build --collect:"XPlat Code Coverage" --settings coverlet.runsettings
run: dotnet test tests/MGR.Guard.UnitTests/MGR.Guard.UnitTests.csproj -c Release --no-build

- name: Upload dotnet test results
uses: actions/upload-artifact@v4
uses: dorny/[email protected]
if: always()
with:
name: dotnet-results
path: '**/coverage.cobertura.xml'
if-no-files-found: warn
# Use always() to always run this step to publish test results when there are test failures
if: ${{ always() }}

name: .NET Tests
path: '**/MGR.Guard.UnitTests.trx'
reporter: dotnet-trx
fail-on-error: true

- name: Push to MyGet
env:
NUGET_URL: https://www.myget.org/F/mgrosperrin/api/v3/index.json
NUGET_API_KEY: ${{ secrets.MYGET_CI_API_KEY }}
run: dotnet nuget push '**/*.nupkg' --source "$($env:NUGET_URL)" --api-key "$($env:NUGET_API_KEY)"
if: github.event_name == 'push'
6 changes: 6 additions & 0 deletions docs/guard.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ Checks if a value is greater than zero.
#### Exception thrown
`System.ArgumentOutOfRangeException` if the specified value is lower than zero.

## IsNotEmpty
Checks if a collection is not empty.

#### Execption thrown
`System.ArgumentException` if the specified value is empty.

## IsLowerThan
Checks if a value is lower than a maximal limit.

Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ The entry point of the library is the static propery `MGR.Guard.Guardian.ChecksT
The methods allow you to guard against null value, lower or upper bound, file existence.
If the check fails, an exception is thrown.

You can find all [built-in methods here](guard.md), or [browse the API](/api).

All built-in methods exists in two flavors:

1. The first takes the value to check and the name of the value (to provide to the thrown exection),
2. The second takes [an expression](guard-expression.md) from which the value and its name are extracted.

*The first form is much more performant (~600x), but the second one is more maintenable.**

You can find all [built-in methods here](guard.md), or [browse the API](/api).
*The first form is much more performant (~600x), but the second one is more maintenable.*

## What if the provided methods are not enough?

Expand Down
48 changes: 48 additions & 0 deletions src/MGR.Guard.Sources/GuardianExtensions.IsNotEmpty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections;
using System.IO;
using System.Linq.Expressions;
using JetBrains.Annotations;

namespace MGR.Guard
{
#if MGR_GUARD_PUBLIC
public
#else
internal
#endif
static partial class GuardianExtensions
{
/// <summary>
/// Checks that the specified <see cref="IEnumerable " /> <paramref name="expression" /> is empty.
/// </summary>
/// <param name="source">The <see cref="Guardian"/> to extends.</param>
/// <param name="expression">The collection as an Expression.</param>
[PublicAPI]
public static void IsNotEmpty([NotNull] this Guardian source, [NotNull] Expression<Func<IEnumerable>> expression)
{
source.IsNotNull(expression, nameof(expression));

var (collection, parameterName) = ((IGuardian)source).ExtractValueAndParameterNameFromExpression(expression);
IsNotEmpty(source, collection, parameterName);
}
/// <summary>
/// Checks if the specified <see cref="FileSystemInfo " /> <paramref name="collection" /> exists.
/// </summary>
/// <param name="source">The <see cref="Guardian"/> to extends.</param>
/// <param name="collection">The file.</param>
/// <param name="parameterName">The name of the file parameter.</param>
[PublicAPI]
public static void IsNotEmpty([NotNull] this Guardian source, [NotNull] IEnumerable collection, string parameterName)
{
source.IsNotNull(collection, nameof(collection));

var enumerator = collection.GetEnumerator();
var hasItems = enumerator.MoveNext();
if (!hasItems)
{
throw new ArgumentException(Messages.IsNotEmptyMessage, parameterName);
}
}
}
}
1 change: 1 addition & 0 deletions src/MGR.Guard.Sources/GuardianExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ private static class Messages
internal const string IsLowerThanOrEqualToZeroMessage = "The argument must be lower than or equal to 0.";
internal const string IsDefinedType = "TEnum must be an enumerated type.";
internal static Func<TEnum, Type, string> IsDefinedFormat<TEnum>() => (value, enumType) => string.Format(CultureInfo.CurrentCulture, "The value '{0}' is not defined in the enum type '{1}'.", value, enumType);
internal const string IsNotEmptyMessage = "The collection cannot be empty.";
}
}
}
3 changes: 3 additions & 0 deletions src/MGR.Guard.Sources/MGR.Guard.Sources.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<Pack>true</Pack>
<PackagePath>$(ContentTargetFolders)\cs\$(TargetFramework)\$(PackageId)\%(RecursiveDir)</PackagePath>
</Compile>
<Compile Update="GuardianExtensions.IsNotEmpty.cs">
<PackagePath>$(ContentTargetFolders)\cs\$(TargetFramework)\$(PackageId)\%(RecursiveDir)</PackagePath>
</Compile>
</ItemGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
Expand Down
45 changes: 45 additions & 0 deletions tests/MGR.Guard.UnitTests/GuardianExtensionsTests.IsNotEmpty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections;
using System.Linq;
using Xunit;

namespace MGR.Guard
{
public partial class GuardianExtensionsTests
{
public class IsNotEmpty
{
[Fact]
public void Collection_Should_Not_Be_Null()
{
// Arrange
IEnumerable collection = null;

// Act & Assert
var actualException = Assert.Throws<ArgumentNullException>(() => Guardian.ChecksThat.IsNotEmpty(collection, nameof(collection)));
Assert.Equal("collection", actualException.ParamName);
}

[Fact]
public void Collection_Should_Not_Be_Empty()
{
// Arrange
IEnumerable collection = Enumerable.Empty<object>();

// Act & Assert
var actualException = Assert.Throws<ArgumentException>(() => Guardian.ChecksThat.IsNotEmpty(collection, nameof(collection)));
Assert.Equal("collection", actualException.ParamName);
}

[Fact]
public void Non_Empty_Collection()
{
// Arrange
IEnumerable collection = new []{new object()};

// Act & Assert
Guardian.ChecksThat.IsNotEmpty(collection, nameof(collection));
}
}
}
}
2 changes: 2 additions & 0 deletions tests/MGR.Guard.UnitTests/MGR.Guard.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<DocumentationFile />
<IsPackable>false</IsPackable>
<RootNamespace>MGR.Guard</RootNamespace>
<VSTestLogger>trx%3bLogFileName=$(MSBuildProjectName).trx</VSTestLogger>
<VSTestResultsDirectory>$(MSBuildThisFileDirectory)/TestResults/$(TargetFramework)</VSTestResultsDirectory>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit f64c994

Please sign in to comment.