From 76518ba2e432854bc976e4afbaf693c5a01d9004 Mon Sep 17 00:00:00 2001 From: pepelev Date: Mon, 29 Sep 2025 19:04:45 +0500 Subject: [PATCH 1/6] Add NullableEquality and other fixes --- .../workflows/build-test-publish-nuget.yml | 42 ++++++--- .github/workflows/build-test.yml | 8 +- .../Comparation.Tests.csproj | 4 +- src/Comparation.Tests/Core/EqualitySuite.cs | 80 +++++++++++++++++ ...tyShouldGiveSameHashCodeForEqualObjects.cs | 6 +- src/Comparation.Tests/Equality/Cases.cs | 41 ++++++++- src/Comparation.Tests/TestsEntryPoint.cs | 3 + src/Comparation/Box.cs | 16 ++-- src/Comparation/CollectionEquality.cs | 32 +++++-- src/Comparation/Comparation.csproj | 3 +- src/Comparation/Equality.cs | 4 +- src/Comparation/HashCode.cs | 13 +++ src/Comparation/NullableEquality.cs | 36 ++++++++ src/Comparation/ProjectingEquality.cs | 12 ++- src/Comparation/SetEquality.cs | 87 +++++++++++++++++++ 15 files changed, 343 insertions(+), 44 deletions(-) create mode 100644 src/Comparation.Tests/Core/EqualitySuite.cs create mode 100644 src/Comparation/HashCode.cs create mode 100644 src/Comparation/NullableEquality.cs create mode 100644 src/Comparation/SetEquality.cs diff --git a/.github/workflows/build-test-publish-nuget.yml b/.github/workflows/build-test-publish-nuget.yml index e69e747..fd233e4 100644 --- a/.github/workflows/build-test-publish-nuget.yml +++ b/.github/workflows/build-test-publish-nuget.yml @@ -16,12 +16,12 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 with: - dotnet-version: 5.0.103 + dotnet-version: 8.0.* - name: Install dependencies run: dotnet restore @@ -33,13 +33,27 @@ jobs: run: dotnet test --no-restore --verbosity normal - name: Publish on version change - id: publish_nuget - uses: rohith/publish-nuget@v2 - with: - PROJECT_FILE_PATH: ./src/Comparation/Comparation.csproj - VERSION_REGEX: ^\s*(.*)<\/Version>\s*$ - TAG_COMMIT: true - TAG_FORMAT: v* - NUGET_KEY: ${{secrets.NUGETKEY}} - NUGET_SOURCE: https://api.nuget.org - INCLUDE_SYMBOLS: true \ No newline at end of file + shell: bash + env: + NUGETKEY: ${{ secrets.NUGETKEY }} + run: | + function publish_project() { + ProjectName="$1" + Version=$(grep --only-matching --perl-regex '[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+)?' "$ProjectName/$ProjectName.csproj" | grep --only-matching --perl-regex '[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+)?') + echo "Version=$Version" + if test -z "$Version"; then + echo "Could not get version from $ProjectName.csproj" + exit 1 + fi + git fetch --tags + if test -n "$(git tag --list "$ProjectName-$Version" | tr -d '[:space:]')"; then + echo "Version $Version already exists for $ProjectName" + else + rm -rf nuget + dotnet pack "$ProjectName" --configuration Release --no-build --include-symbols --nologo --output nuget &&\ + dotnet nuget push nuget/*.nupkg --source 'https://api.nuget.org/v3/index.json' --api-key "$NUGETKEY" --skip-duplicate &&\ + git tag "$ProjectName-$Version" && git push origin "$ProjectName-$Version" || { echo "Error occurred"; exit 1; } + fi + } + + publish_project Comparation \ No newline at end of file diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 9cc0ccc..2a44265 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -16,12 +16,12 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 + - name: Setup .NET 8 + uses: actions/setup-dotnet@v4 with: - dotnet-version: 5.0.103 + dotnet-version: 8.0.* - name: Install dependencies run: dotnet restore diff --git a/src/Comparation.Tests/Comparation.Tests.csproj b/src/Comparation.Tests/Comparation.Tests.csproj index f0b479a..f2a476f 100644 --- a/src/Comparation.Tests/Comparation.Tests.csproj +++ b/src/Comparation.Tests/Comparation.Tests.csproj @@ -1,7 +1,7 @@  - net48;net5.0 + net48;net8 ..\..\bin\Comparation.Tests true 9 @@ -13,7 +13,7 @@ annotations - + enable diff --git a/src/Comparation.Tests/Core/EqualitySuite.cs b/src/Comparation.Tests/Core/EqualitySuite.cs new file mode 100644 index 0000000..2f50c86 --- /dev/null +++ b/src/Comparation.Tests/Core/EqualitySuite.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Comparation.Tests.Equality.Aspects; + +namespace Comparation.Tests.Core +{ + public sealed class EqualitySuite : IEnumerable> + { + private readonly string name; + private readonly IEqualityComparer sut; + private readonly Named[][] equalGroups; + + public EqualitySuite(string name, IEqualityComparer sut, Named[][] equalGroups) + { + this.name = name; + this.sut = sut; + this.equalGroups = equalGroups; + } + + private IEnumerable> Yield() + { + var allItems = equalGroups.SelectMany(group => group).ToList(); + var uniqueNames = allItems.Select(item => item.Name).Distinct().ToList(); + if (uniqueNames.Count != allItems.Count) + { + throw new Exception("Duplicate items"); + } + + return Cases(); + + IEnumerable> Cases() + { + for (var i = 0; i < equalGroups.Length; i++) + { + for (var j = 0; j < equalGroups.Length; j++) + { + for (var k = 0; k < equalGroups[i].Length; k++) + { + for (var m = 0; m < equalGroups[j].Length; m++) + { + var a = equalGroups[i][k]; + var b = equalGroups[j][m]; + var expectation = i == j; + var sign = expectation + ? "==" + : "!="; + yield return ( + $"{name}: {a.Name} {sign} {b.Name}", + new EqualityShouldWorkAsExpected( + sut, + a.Value, + b.Value, + expectation: expectation + ) + ); + + if (expectation) + { + yield return ( + $"{name}: HashCode({a.Name}) {sign} HashCode({b.Name})", + new EqualityShouldGiveSameHashCodeForEqualObjects( + sut, + a.Value, + b.Value + ) + ); + } + } + } + } + } + } + } + + public IEnumerator> GetEnumerator() => Yield().GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} \ No newline at end of file diff --git a/src/Comparation.Tests/Equality/Aspects/EqualityShouldGiveSameHashCodeForEqualObjects.cs b/src/Comparation.Tests/Equality/Aspects/EqualityShouldGiveSameHashCodeForEqualObjects.cs index 3cfee5b..6014dc4 100644 --- a/src/Comparation.Tests/Equality/Aspects/EqualityShouldGiveSameHashCodeForEqualObjects.cs +++ b/src/Comparation.Tests/Equality/Aspects/EqualityShouldGiveSameHashCodeForEqualObjects.cs @@ -7,10 +7,10 @@ namespace Comparation.Tests.Equality.Aspects public sealed class EqualityShouldGiveSameHashCodeForEqualObjects : Test { private readonly IEqualityComparer equality; - private readonly T a; - private readonly T b; + private readonly T? a; + private readonly T? b; - public EqualityShouldGiveSameHashCodeForEqualObjects(IEqualityComparer equality, T a, T b) + public EqualityShouldGiveSameHashCodeForEqualObjects(IEqualityComparer equality, T? a, T? b) { this.equality = equality; this.a = a; diff --git a/src/Comparation.Tests/Equality/Cases.cs b/src/Comparation.Tests/Equality/Cases.cs index 5f7587a..ffd78a3 100644 --- a/src/Comparation.Tests/Equality/Cases.cs +++ b/src/Comparation.Tests/Equality/Cases.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using Comparation.Tests.Core; @@ -11,6 +12,41 @@ public sealed class Cases : IEnumerable { private const string Category = "Equality"; + private static EqualitySuite> StringSetSuite() + { + // ReSharper disable InconsistentNaming + Named?> nullSet = (nameof(nullSet), null); + Named?> emptySet = (nameof(emptySet), Array.Empty()); + Named?> singleNull = (nameof(singleNull), new string?[] { null }); + Named?> singleA = (nameof(singleA), new[] { "a" }); + Named?> singleBigA = (nameof(singleBigA), new[] { "A" }); + Named?> twoAs = (nameof(twoAs), new[] { "a", "A" }); + Named?> ab = (nameof(ab), new[] { "a", "b" }); + Named?> ba = (nameof(ba), new[] { "b", "a" }); + Named?> abc = (nameof(abc), new[] { "a", "b", "c" }); + Named?> ab2c = (nameof(ab2c), new[] { "a", "b", "c", "b" }); + Named?> abnull = (nameof(abnull), new[] { "a", "b", null }); + Named?> nullba = (nameof(nullba), new[] { null, "b", "a" }); + // ReSharper restore InconsistentNaming + + return new EqualitySuite>( + nameof(SetEquality), + new SetEquality( + Comparation.Equality.Of().By(@string => @string.ToLowerInvariant()) + ), + new[] + { + new[] { nullSet }, + new[] { emptySet }, + new[] { singleNull }, + new[] { singleA, singleBigA, twoAs }, + new[] { ab, ba }, + new[] { abc, ab2c }, + new[] { abnull, nullba } + } + ); + } + public IEnumerator GetEnumerator() => Sequence.Concat( new WorkAsExpected(), new Examples(), @@ -19,7 +55,8 @@ public IEnumerator GetEnumerator() => Sequence.Concat( new GiveSameHashCodeForEqualObjects(), new TreatTreatsNullNotEqualToObject(), new Transitive(), - new Equal() + new Equal(), + StringSetSuite() ) .Select(@case => new NamePrefixing(Category, @case)) .Select(@case => new TestCaseData(@case.Value).SetName(@case.Name).SetCategory(Category)) diff --git a/src/Comparation.Tests/TestsEntryPoint.cs b/src/Comparation.Tests/TestsEntryPoint.cs index 3e68c3d..b47c5ff 100644 --- a/src/Comparation.Tests/TestsEntryPoint.cs +++ b/src/Comparation.Tests/TestsEntryPoint.cs @@ -1,8 +1,11 @@ using Comparation.Tests.Core; using NUnit.Framework; +[assembly: LevelOfParallelism(8)] + namespace Comparation.Tests { + [Parallelizable(ParallelScope.All)] public sealed class TestsEntryPoint { [Test] diff --git a/src/Comparation/Box.cs b/src/Comparation/Box.cs index fd5b84f..ce4af49 100644 --- a/src/Comparation/Box.cs +++ b/src/Comparation/Box.cs @@ -24,16 +24,20 @@ public Equality(IEqualityComparer equality) this.equality = equality; } - public bool Equals(Box x, Box y) => (x.value, y.value) switch - { - ({ } a, { } b) => equality.Equals(a, b), - (null, null) => true, - _ => false - }; +#if NETSTANDARD2_0 || NETSTANDARD2_1 + public bool Equals(Box x, Box y) => equality.Equals(x.value!, y.value!); +#else + public bool Equals(Box x, Box y) => equality.Equals(x.value, y.value); +#endif public int GetHashCode(Box obj) => obj.value is { } value ? equality.GetHashCode(value) : 0; } } + + internal static class Box + { + public static Box Wrap(T item) => new(item); + } } \ No newline at end of file diff --git a/src/Comparation/CollectionEquality.cs b/src/Comparation/CollectionEquality.cs index 2a32ba0..63a92a8 100644 --- a/src/Comparation/CollectionEquality.cs +++ b/src/Comparation/CollectionEquality.cs @@ -1,5 +1,9 @@ using System; using System.Collections.Generic; +#if NET6_0_OR_GREATER +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +#endif namespace Comparation { @@ -77,10 +81,14 @@ public int GetHashCode(IReadOnlyCollection collection) foreach (var item in x) { var box = new Box(item); +#if NET6_0_OR_GREATER + CollectionsMarshal.GetValueRefOrAddDefault(counts, box, out _)++; +#else var newCount = counts.TryGetValue(box, out var count) ? count + 1 : 1; counts[box] = newCount; +#endif } return counts; @@ -91,21 +99,33 @@ private static bool Equals(IEnumerable y, Dictionary, int> counts) foreach (var item in y) { var box = new Box(item); +#if NET6_0_OR_GREATER + ref var count = ref CollectionsMarshal.GetValueRefOrNullRef(counts, box); + if (Unsafe.IsNullRef(ref count)) + { + return false; + } + + count--; + if (count < 0) + { + return false; + } +#else if (counts.TryGetValue(box, out var count)) { - if (count == 1) + if (count <= 0) { - counts.Remove(box); - } - else - { - counts[box] = count - 1; + return false; } + + counts[box] = count - 1; } else { return false; } +#endif } return true; diff --git a/src/Comparation/Comparation.csproj b/src/Comparation/Comparation.csproj index 23cb5a9..3d6495b 100644 --- a/src/Comparation/Comparation.csproj +++ b/src/Comparation/Comparation.csproj @@ -3,12 +3,12 @@ ..\..\bin\Comparation true + netstandard2.0;netstandard2.1;net6 9 enable - netstandard2.0;netstandard2.1;net5.0 true full false @@ -16,7 +16,6 @@ - netstandard2.0;netstandard2.1 pdbonly true diff --git a/src/Comparation/Equality.cs b/src/Comparation/Equality.cs index 14b8d6f..bf27f73 100644 --- a/src/Comparation/Equality.cs +++ b/src/Comparation/Equality.cs @@ -56,11 +56,11 @@ public sealed class Equality public IEqualityComparer Default => EqualityComparer.Default; - public IEqualityComparer By(Func projection) => + public IEqualityComparer By(Func projection) => By(projection, EqualityComparer.Default); public IEqualityComparer By( - Func projection, + Func projection, IEqualityComparer equality) => new ProjectingEquality(projection, equality); diff --git a/src/Comparation/HashCode.cs b/src/Comparation/HashCode.cs new file mode 100644 index 0000000..0a88da2 --- /dev/null +++ b/src/Comparation/HashCode.cs @@ -0,0 +1,13 @@ +#if NETSTANDARD2_0 +namespace Comparation +{ + internal struct HashCode + { + private int value; + + public void Add(int hashCode) => value = unchecked(value * 397) ^ hashCode; + + public int ToHashCode() => value; + } +} +#endif \ No newline at end of file diff --git a/src/Comparation/NullableEquality.cs b/src/Comparation/NullableEquality.cs new file mode 100644 index 0000000..a2056e0 --- /dev/null +++ b/src/Comparation/NullableEquality.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; + +namespace Comparation +{ + public sealed class NullableEquality : IEqualityComparer where TSubject : struct + { + private readonly IEqualityComparer equality; + + public NullableEquality(IEqualityComparer equality) + { + this.equality = equality; + } + + public bool Equals(TSubject? x, TSubject? y) + { + if (x == null && y == null) + { + return true; + } + + if (x == null || y == null) + { + return false; + } + + return equality.Equals(x.Value, y.Value); + } + + public int GetHashCode(TSubject? obj) + { + return obj == null + ? 0 + : equality.GetHashCode(obj.Value); + } + } +} \ No newline at end of file diff --git a/src/Comparation/ProjectingEquality.cs b/src/Comparation/ProjectingEquality.cs index 45a696c..8ecf64f 100644 --- a/src/Comparation/ProjectingEquality.cs +++ b/src/Comparation/ProjectingEquality.cs @@ -3,13 +3,12 @@ namespace Comparation { - // todo make interface generic parameter nullable public sealed class ProjectingEquality : IEqualityComparer { - private readonly Func projection; + private readonly Func projection; private readonly IEqualityComparer equality; - public ProjectingEquality(Func projection, IEqualityComparer equality) + public ProjectingEquality(Func projection, IEqualityComparer equality) { this.projection = projection; this.equality = equality; @@ -32,10 +31,17 @@ public bool Equals(TSubject? x, TSubject? y) return false; } +#if NETSTANDARD2_0 || NETSTANDARD2_1 + return equality.Equals( + projection(x)!, + projection(y)! + ); +#else return equality.Equals( projection(x), projection(y) ); +#endif } public int GetHashCode(TSubject obj) => projection(obj) is { } value diff --git a/src/Comparation/SetEquality.cs b/src/Comparation/SetEquality.cs new file mode 100644 index 0000000..4492f9c --- /dev/null +++ b/src/Comparation/SetEquality.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Comparation +{ + public sealed class SetEquality : IEqualityComparer> + { + private readonly Box.Equality itemEquality; + + public SetEquality(IEqualityComparer itemEquality) + { + this.itemEquality = new Box.Equality(itemEquality); + } + + public bool Equals(IReadOnlyCollection? x, IReadOnlyCollection? y) + { + if (ReferenceEquals(x, y)) + { + return true; + } + + if (ReferenceEquals(x, null)) + { + return false; + } + + if (ReferenceEquals(y, null)) + { + return false; + } + + var xEmpty = x.Count == 0; + var yEmpty = y.Count == 0; + if (xEmpty != yEmpty) + { + return false; + } + + var setX = new HashSet>( + x.Select(Box.Wrap), + itemEquality + ); + + var itemsY = y.Select(Box.Wrap); + return setX.SetEquals(itemsY); + } + + public int GetHashCode(IReadOnlyCollection collection) + { + var count = collection.Count; +#if NETCOREAPP2_1_OR_GREATER + var hashCodes = count <= 1024 / sizeof(int) + ? stackalloc int[count] + : new int[count]; +#else + var hashCodes = new int[count]; +#endif + var i = 0; + foreach (var item in collection) + { + hashCodes[i++] = itemEquality.GetHashCode(Box.Wrap(item)); + } + +#if NETCOREAPP2_1_OR_GREATER + hashCodes.Sort(); +#else + Array.Sort(hashCodes); +#endif + + var result = new HashCode(); + var lastHashCode = 0; + foreach (var hashCode in hashCodes) + { + if (lastHashCode == hashCode) + { + continue; + } + + result.Add(hashCode); + lastHashCode = hashCode; + } + + return result.ToHashCode(); + } + } +} \ No newline at end of file From e332684a89dc35d17d792dc3e5a65a69366df85d Mon Sep 17 00:00:00 2001 From: pepelev Date: Mon, 29 Sep 2025 19:21:07 +0500 Subject: [PATCH 2/6] Disable net4.8 tests --- .github/workflows/build-test-publish-nuget.yml | 2 +- .github/workflows/build-test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test-publish-nuget.yml b/.github/workflows/build-test-publish-nuget.yml index fd233e4..481cdaf 100644 --- a/.github/workflows/build-test-publish-nuget.yml +++ b/.github/workflows/build-test-publish-nuget.yml @@ -30,7 +30,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Test - run: dotnet test --no-restore --verbosity normal + run: dotnet test --no-restore --verbosity normal --framework net8.0 - name: Publish on version change shell: bash diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 2a44265..9b77521 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -30,4 +30,4 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Test - run: dotnet test --no-restore --verbosity normal \ No newline at end of file + run: dotnet test --no-restore --verbosity normal --framework net8.0 \ No newline at end of file From eafb5bb940000aeab5ca3ef4676b5e108ee5463b Mon Sep 17 00:00:00 2001 From: pepelev Date: Mon, 29 Sep 2025 19:22:53 +0500 Subject: [PATCH 3/6] fit string --- .github/workflows/build-test-publish-nuget.yml | 2 +- .github/workflows/build-test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test-publish-nuget.yml b/.github/workflows/build-test-publish-nuget.yml index 481cdaf..cf27505 100644 --- a/.github/workflows/build-test-publish-nuget.yml +++ b/.github/workflows/build-test-publish-nuget.yml @@ -30,7 +30,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Test - run: dotnet test --no-restore --verbosity normal --framework net8.0 + run: dotnet test --no-restore --verbosity normal --framework net8 - name: Publish on version change shell: bash diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 9b77521..ad82a26 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -30,4 +30,4 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Test - run: dotnet test --no-restore --verbosity normal --framework net8.0 \ No newline at end of file + run: dotnet test --no-restore --verbosity normal --framework net8 \ No newline at end of file From 72ba4d43ac8beefd8d945be11ea7eb116e8ccbec Mon Sep 17 00:00:00 2001 From: pepelev Date: Tue, 30 Sep 2025 13:32:52 +0500 Subject: [PATCH 4/6] Try keep only single test --- src/Comparation.Tests/EqualityShould.cs | 466 +++++++++++------------ src/Comparation.Tests/TestsEntryPoint.cs | 14 +- 2 files changed, 243 insertions(+), 237 deletions(-) diff --git a/src/Comparation.Tests/EqualityShould.cs b/src/Comparation.Tests/EqualityShould.cs index 280f4d0..97b709e 100644 --- a/src/Comparation.Tests/EqualityShould.cs +++ b/src/Comparation.Tests/EqualityShould.cs @@ -1,233 +1,233 @@ -using System.Collections.Generic; -using FluentAssertions; -using NUnit.Framework; - -namespace Comparation.Tests -{ - public sealed class EqualityShould - { - public static TestCaseData[] EqualityCases => new[] - { - new TestCaseData(StringByLength, "Hello", "world").Returns(true).SetName("positive single by"), - new TestCaseData(StringByLength, "Quick", "fox").Returns(false).SetName("negative single by"), - - new TestCaseData(StringByReference, "Hello", "Hello").Returns(true).SetName("positive by reference (interning)"), - new TestCaseData(StringByReference, "Quick", string.Concat("Qui", "ck")).Returns(false).SetName("negative by reference"), - - new TestCaseData( - StringByFirstLetterCaseInsensitively, - "Firmware", - "fox" - ).Returns(true).SetName("positive single by with equality"), - new TestCaseData( - StringByFirstLetterCaseInsensitively, - "Yeti", - "Bigfoot" - ).Returns(false).SetName("negative single by with equality"), - - new TestCaseData( - StringByLengthAndFirstLetter, - "Brown", - "Beast" - ).Returns(true).SetName("positive and-by"), - new TestCaseData( - StringByLengthAndFirstLetter, - "Apple", - "Alpine" - ).Returns(false).SetName("negative and-by on first field"), - new TestCaseData( - StringByLengthAndFirstLetter, - "Fear", - "Calm" - ).Returns(false).SetName("negative and-by on second field"), - - new TestCaseData( - StringByLengthAndFirstLetterCaseInsensitively, - "Brown", - "blast" - ).Returns(true).SetName("positive and-by with equality"), - new TestCaseData( - StringByLengthAndFirstLetterCaseInsensitively, - "Apple", - "Alpine" - ).Returns(false).SetName("negative and-by with equality on first field"), - new TestCaseData( - StringByLengthAndFirstLetterCaseInsensitively, - "Fear", - "Calm" - ).Returns(false).SetName("negative and-by with equality on second field"), - - new TestCaseData( - StringByLengthAndUsingFirstLetterCaseInsensitively, - "Brown", - "blast" - ).Returns(true).SetName("positive and-by with equality"), - new TestCaseData( - StringByLengthAndUsingFirstLetterCaseInsensitively, - "Apple", - "Alpine" - ).Returns(false).SetName("negative and-by with equality on first field"), - new TestCaseData( - StringByLengthAndUsingFirstLetterCaseInsensitively, - "Fear", - "Calm" - ).Returns(false).SetName("negative and-by with equality on second field"), - - new TestCaseData( - StringCompositeByLengthFirstLetterCaseInsensitively, - "Brown", - "blast" - ).Returns(true).SetName("positive and-by with equality"), - new TestCaseData( - StringCompositeByLengthFirstLetterCaseInsensitively, - "Apple", - "Alpine" - ).Returns(false).SetName("negative and-by with equality on first field"), - new TestCaseData( - StringCompositeByLengthFirstLetterCaseInsensitively, - "Fear", - "Calm" - ).Returns(false).SetName("negative and-by with equality on second field"), - - new TestCaseData( - StringCompositeCollectionByLengthFirstLetterCaseInsensitively, - "Brown", - "blast" - ).Returns(true).SetName("positive and-by with equality"), - new TestCaseData( - StringCompositeCollectionByLengthFirstLetterCaseInsensitively, - "Apple", - "Alpine" - ).Returns(false).SetName("negative and-by with equality on first field"), - new TestCaseData( - StringCompositeCollectionByLengthFirstLetterCaseInsensitively, - "Fear", - "Calm" - ).Returns(false).SetName("negative and-by with equality on second field") - }; - - private static IEqualityComparer StringByLength => Comparation.Equality.Of().By(@string => @string.Length); - private static IEqualityComparer StringByReference => Comparation.Equality.ByReference(); - - private static IEqualityComparer StringByFirstLetterCaseInsensitively => Comparation.Equality.Of().By( - @string => @string[0], - CharCaseInsensitively - ); - - private static IEqualityComparer CharCaseInsensitively => Comparation.Equality.Of().By(char.ToLowerInvariant); - - private static IEqualityComparer StringByLengthAndFirstLetter => - StringByLength.AndBy(@string => @string[0]); - - private static IEqualityComparer StringByLengthAndFirstLetterCaseInsensitively => - StringByLength.AndBy(@string => @string[0], CharCaseInsensitively); - - private static IEqualityComparer StringByLengthAndUsingFirstLetterCaseInsensitively => - StringByLength.AndUsing(StringByFirstLetterCaseInsensitively); - - private static IEqualityComparer StringCompositeByLengthFirstLetterCaseInsensitively => - Comparation.Equality.Of().Composite( - StringByLength, - StringByFirstLetterCaseInsensitively - ); - - private static IEqualityComparer StringCompositeCollectionByLengthFirstLetterCaseInsensitively => - Comparation.Equality.Of().Composite( - new List> - { - StringByLength, - StringByFirstLetterCaseInsensitively - } - ); - - private static IEqualityComparer> StringCollection => - Comparation.Equality.Of().Collection(); - - private static IEqualityComparer> StringSequence => - Comparation.Equality.Of().Sequence(); - - public static TestCaseData[] Equalities => new[] - { - new TestCaseData(StringByLength).SetName(nameof(StringByLength)), - new TestCaseData(StringByReference).SetName(nameof(StringByReference)), - new TestCaseData(StringByFirstLetterCaseInsensitively) - .SetName(nameof(StringByFirstLetterCaseInsensitively)), - new TestCaseData(StringByLengthAndFirstLetter).SetName(nameof(StringByLengthAndFirstLetter)), - new TestCaseData(StringByLengthAndFirstLetterCaseInsensitively) - .SetName(nameof(StringByLengthAndFirstLetterCaseInsensitively)), - new TestCaseData(StringByLengthAndUsingFirstLetterCaseInsensitively) - .SetName(nameof(StringByLengthAndUsingFirstLetterCaseInsensitively)), - new TestCaseData(StringCompositeByLengthFirstLetterCaseInsensitively) - .SetName(nameof(StringCompositeByLengthFirstLetterCaseInsensitively)), - new TestCaseData(StringCompositeCollectionByLengthFirstLetterCaseInsensitively) - .SetName(nameof(StringCompositeCollectionByLengthFirstLetterCaseInsensitively)) - }; - - public static TestCaseData[] EqualitiesWithArgument => new[] - { - new TestCaseData(StringByLength, "Dog").SetName(nameof(StringByLength)), - new TestCaseData(StringByReference, "And").SetName(nameof(StringByReference)), - new TestCaseData(StringByFirstLetterCaseInsensitively, "Cat") - .SetName(nameof(StringByFirstLetterCaseInsensitively)), - new TestCaseData(StringByLengthAndFirstLetter, "Are").SetName(nameof(StringByLengthAndFirstLetter)), - new TestCaseData(StringByLengthAndFirstLetterCaseInsensitively, "Friends") - .SetName(nameof(StringByLengthAndFirstLetterCaseInsensitively)), - new TestCaseData(StringByLengthAndUsingFirstLetterCaseInsensitively, "Believe") - .SetName(nameof(StringByLengthAndUsingFirstLetterCaseInsensitively)), - new TestCaseData(StringCompositeByLengthFirstLetterCaseInsensitively, "Me") - .SetName(nameof(StringCompositeByLengthFirstLetterCaseInsensitively)), - new TestCaseData(StringCompositeCollectionByLengthFirstLetterCaseInsensitively, "Pal") - .SetName(nameof(StringCompositeCollectionByLengthFirstLetterCaseInsensitively)) - }; - - [Test] - [TestCaseSource(nameof(EqualityCases))] - public bool DefineEquality(IEqualityComparer equality, T a, T b) => equality.Equals(a, b); - - [Test] - [TestCase(new string[0], new string[0], ExpectedResult = true)] - [TestCase(new[] {"Dog"}, new string[0], ExpectedResult = false)] - [TestCase(new[] {"Dog"}, new[] {"Dog"}, ExpectedResult = true)] - [TestCase(new[] {"Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] - [TestCase(new[] {"Dog"}, new[] {"Cat"}, ExpectedResult = false)] - [TestCase(new[] {"Dog", "Cat"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] - [TestCase(new[] {"Cat", "Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] - [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Cat"}, ExpectedResult = false)] - [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = true)] - public bool DefineEqualityOnCollections(string[] a, string[] b) => StringCollection.Equals(a, b); - - [Test] - [TestCase(new string[0], new string[0], ExpectedResult = true)] - [TestCase(new[] {"Dog"}, new string[0], ExpectedResult = false)] - [TestCase(new[] {"Dog"}, new[] {"Dog"}, ExpectedResult = true)] - [TestCase(new[] {"Dog"}, new[] {"Cat"}, ExpectedResult = false)] - [TestCase(new[] {"Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] - [TestCase(new[] {"Dog", "Cat"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] - [TestCase(new[] {"Cat", "Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] - [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Cat"}, ExpectedResult = false)] - [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = false)] - [TestCase(new[] {"Dog", "Cat", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = true)] - public bool DefineEqualityOnSequences(string[] a, string[] b) => StringSequence.Equals(a, b); - - [Test] - [TestCaseSource(nameof(EqualitiesWithArgument))] - public void WorkWithFirstArgumentNull(IEqualityComparer equality, T b) where T : class - { - equality.Equals(null, b).Should().BeFalse(); - } - - [Test] - [TestCaseSource(nameof(EqualitiesWithArgument))] - public void WorkWithSecondArgumentNull(IEqualityComparer equality, T a) where T : class - { - equality.Equals(a, null).Should().BeFalse(); - } - - [Test] - [TestCaseSource(nameof(Equalities))] - public void TreatBothNullsAsEqual(IEqualityComparer equality) - { - equality.Equals(null, null).Should().BeTrue(); - } - } -} \ No newline at end of file +// using System.Collections.Generic; +// using FluentAssertions; +// using NUnit.Framework; +// +// namespace Comparation.Tests +// { +// public sealed class EqualityShould +// { +// public static TestCaseData[] EqualityCases => new[] +// { +// new TestCaseData(StringByLength, "Hello", "world").Returns(true).SetName("positive single by"), +// new TestCaseData(StringByLength, "Quick", "fox").Returns(false).SetName("negative single by"), +// +// new TestCaseData(StringByReference, "Hello", "Hello").Returns(true).SetName("positive by reference (interning)"), +// new TestCaseData(StringByReference, "Quick", string.Concat("Qui", "ck")).Returns(false).SetName("negative by reference"), +// +// new TestCaseData( +// StringByFirstLetterCaseInsensitively, +// "Firmware", +// "fox" +// ).Returns(true).SetName("positive single by with equality"), +// new TestCaseData( +// StringByFirstLetterCaseInsensitively, +// "Yeti", +// "Bigfoot" +// ).Returns(false).SetName("negative single by with equality"), +// +// new TestCaseData( +// StringByLengthAndFirstLetter, +// "Brown", +// "Beast" +// ).Returns(true).SetName("positive and-by"), +// new TestCaseData( +// StringByLengthAndFirstLetter, +// "Apple", +// "Alpine" +// ).Returns(false).SetName("negative and-by on first field"), +// new TestCaseData( +// StringByLengthAndFirstLetter, +// "Fear", +// "Calm" +// ).Returns(false).SetName("negative and-by on second field"), +// +// new TestCaseData( +// StringByLengthAndFirstLetterCaseInsensitively, +// "Brown", +// "blast" +// ).Returns(true).SetName("positive and-by with equality"), +// new TestCaseData( +// StringByLengthAndFirstLetterCaseInsensitively, +// "Apple", +// "Alpine" +// ).Returns(false).SetName("negative and-by with equality on first field"), +// new TestCaseData( +// StringByLengthAndFirstLetterCaseInsensitively, +// "Fear", +// "Calm" +// ).Returns(false).SetName("negative and-by with equality on second field"), +// +// new TestCaseData( +// StringByLengthAndUsingFirstLetterCaseInsensitively, +// "Brown", +// "blast" +// ).Returns(true).SetName("positive and-by with equality"), +// new TestCaseData( +// StringByLengthAndUsingFirstLetterCaseInsensitively, +// "Apple", +// "Alpine" +// ).Returns(false).SetName("negative and-by with equality on first field"), +// new TestCaseData( +// StringByLengthAndUsingFirstLetterCaseInsensitively, +// "Fear", +// "Calm" +// ).Returns(false).SetName("negative and-by with equality on second field"), +// +// new TestCaseData( +// StringCompositeByLengthFirstLetterCaseInsensitively, +// "Brown", +// "blast" +// ).Returns(true).SetName("positive and-by with equality"), +// new TestCaseData( +// StringCompositeByLengthFirstLetterCaseInsensitively, +// "Apple", +// "Alpine" +// ).Returns(false).SetName("negative and-by with equality on first field"), +// new TestCaseData( +// StringCompositeByLengthFirstLetterCaseInsensitively, +// "Fear", +// "Calm" +// ).Returns(false).SetName("negative and-by with equality on second field"), +// +// new TestCaseData( +// StringCompositeCollectionByLengthFirstLetterCaseInsensitively, +// "Brown", +// "blast" +// ).Returns(true).SetName("positive and-by with equality"), +// new TestCaseData( +// StringCompositeCollectionByLengthFirstLetterCaseInsensitively, +// "Apple", +// "Alpine" +// ).Returns(false).SetName("negative and-by with equality on first field"), +// new TestCaseData( +// StringCompositeCollectionByLengthFirstLetterCaseInsensitively, +// "Fear", +// "Calm" +// ).Returns(false).SetName("negative and-by with equality on second field") +// }; +// +// private static IEqualityComparer StringByLength => Comparation.Equality.Of().By(@string => @string.Length); +// private static IEqualityComparer StringByReference => Comparation.Equality.ByReference(); +// +// private static IEqualityComparer StringByFirstLetterCaseInsensitively => Comparation.Equality.Of().By( +// @string => @string[0], +// CharCaseInsensitively +// ); +// +// private static IEqualityComparer CharCaseInsensitively => Comparation.Equality.Of().By(char.ToLowerInvariant); +// +// private static IEqualityComparer StringByLengthAndFirstLetter => +// StringByLength.AndBy(@string => @string[0]); +// +// private static IEqualityComparer StringByLengthAndFirstLetterCaseInsensitively => +// StringByLength.AndBy(@string => @string[0], CharCaseInsensitively); +// +// private static IEqualityComparer StringByLengthAndUsingFirstLetterCaseInsensitively => +// StringByLength.AndUsing(StringByFirstLetterCaseInsensitively); +// +// private static IEqualityComparer StringCompositeByLengthFirstLetterCaseInsensitively => +// Comparation.Equality.Of().Composite( +// StringByLength, +// StringByFirstLetterCaseInsensitively +// ); +// +// private static IEqualityComparer StringCompositeCollectionByLengthFirstLetterCaseInsensitively => +// Comparation.Equality.Of().Composite( +// new List> +// { +// StringByLength, +// StringByFirstLetterCaseInsensitively +// } +// ); +// +// private static IEqualityComparer> StringCollection => +// Comparation.Equality.Of().Collection(); +// +// private static IEqualityComparer> StringSequence => +// Comparation.Equality.Of().Sequence(); +// +// public static TestCaseData[] Equalities => new[] +// { +// new TestCaseData(StringByLength).SetName(nameof(StringByLength)), +// new TestCaseData(StringByReference).SetName(nameof(StringByReference)), +// new TestCaseData(StringByFirstLetterCaseInsensitively) +// .SetName(nameof(StringByFirstLetterCaseInsensitively)), +// new TestCaseData(StringByLengthAndFirstLetter).SetName(nameof(StringByLengthAndFirstLetter)), +// new TestCaseData(StringByLengthAndFirstLetterCaseInsensitively) +// .SetName(nameof(StringByLengthAndFirstLetterCaseInsensitively)), +// new TestCaseData(StringByLengthAndUsingFirstLetterCaseInsensitively) +// .SetName(nameof(StringByLengthAndUsingFirstLetterCaseInsensitively)), +// new TestCaseData(StringCompositeByLengthFirstLetterCaseInsensitively) +// .SetName(nameof(StringCompositeByLengthFirstLetterCaseInsensitively)), +// new TestCaseData(StringCompositeCollectionByLengthFirstLetterCaseInsensitively) +// .SetName(nameof(StringCompositeCollectionByLengthFirstLetterCaseInsensitively)) +// }; +// +// public static TestCaseData[] EqualitiesWithArgument => new[] +// { +// new TestCaseData(StringByLength, "Dog").SetName(nameof(StringByLength)), +// new TestCaseData(StringByReference, "And").SetName(nameof(StringByReference)), +// new TestCaseData(StringByFirstLetterCaseInsensitively, "Cat") +// .SetName(nameof(StringByFirstLetterCaseInsensitively)), +// new TestCaseData(StringByLengthAndFirstLetter, "Are").SetName(nameof(StringByLengthAndFirstLetter)), +// new TestCaseData(StringByLengthAndFirstLetterCaseInsensitively, "Friends") +// .SetName(nameof(StringByLengthAndFirstLetterCaseInsensitively)), +// new TestCaseData(StringByLengthAndUsingFirstLetterCaseInsensitively, "Believe") +// .SetName(nameof(StringByLengthAndUsingFirstLetterCaseInsensitively)), +// new TestCaseData(StringCompositeByLengthFirstLetterCaseInsensitively, "Me") +// .SetName(nameof(StringCompositeByLengthFirstLetterCaseInsensitively)), +// new TestCaseData(StringCompositeCollectionByLengthFirstLetterCaseInsensitively, "Pal") +// .SetName(nameof(StringCompositeCollectionByLengthFirstLetterCaseInsensitively)) +// }; +// +// [Test] +// [TestCaseSource(nameof(EqualityCases))] +// public bool DefineEquality(IEqualityComparer equality, T a, T b) => equality.Equals(a, b); +// +// [Test] +// [TestCase(new string[0], new string[0], ExpectedResult = true)] +// [TestCase(new[] {"Dog"}, new string[0], ExpectedResult = false)] +// [TestCase(new[] {"Dog"}, new[] {"Dog"}, ExpectedResult = true)] +// [TestCase(new[] {"Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] +// [TestCase(new[] {"Dog"}, new[] {"Cat"}, ExpectedResult = false)] +// [TestCase(new[] {"Dog", "Cat"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] +// [TestCase(new[] {"Cat", "Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] +// [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Cat"}, ExpectedResult = false)] +// [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = true)] +// public bool DefineEqualityOnCollections(string[] a, string[] b) => StringCollection.Equals(a, b); +// +// [Test] +// [TestCase(new string[0], new string[0], ExpectedResult = true)] +// [TestCase(new[] {"Dog"}, new string[0], ExpectedResult = false)] +// [TestCase(new[] {"Dog"}, new[] {"Dog"}, ExpectedResult = true)] +// [TestCase(new[] {"Dog"}, new[] {"Cat"}, ExpectedResult = false)] +// [TestCase(new[] {"Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] +// [TestCase(new[] {"Dog", "Cat"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] +// [TestCase(new[] {"Cat", "Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] +// [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Cat"}, ExpectedResult = false)] +// [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = false)] +// [TestCase(new[] {"Dog", "Cat", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = true)] +// public bool DefineEqualityOnSequences(string[] a, string[] b) => StringSequence.Equals(a, b); +// +// [Test] +// [TestCaseSource(nameof(EqualitiesWithArgument))] +// public void WorkWithFirstArgumentNull(IEqualityComparer equality, T b) where T : class +// { +// equality.Equals(null, b).Should().BeFalse(); +// } +// +// [Test] +// [TestCaseSource(nameof(EqualitiesWithArgument))] +// public void WorkWithSecondArgumentNull(IEqualityComparer equality, T a) where T : class +// { +// equality.Equals(a, null).Should().BeFalse(); +// } +// +// [Test] +// [TestCaseSource(nameof(Equalities))] +// public void TreatBothNullsAsEqual(IEqualityComparer equality) +// { +// equality.Equals(null, null).Should().BeTrue(); +// } +// } +// } \ No newline at end of file diff --git a/src/Comparation.Tests/TestsEntryPoint.cs b/src/Comparation.Tests/TestsEntryPoint.cs index b47c5ff..8159b9f 100644 --- a/src/Comparation.Tests/TestsEntryPoint.cs +++ b/src/Comparation.Tests/TestsEntryPoint.cs @@ -8,12 +8,18 @@ namespace Comparation.Tests [Parallelizable(ParallelScope.All)] public sealed class TestsEntryPoint { + // [Test] + // [TestCaseSource(typeof(Equality.Cases))] + // [TestCaseSource(typeof(Order.Cases))] + // public void Run(Test test) + // { + // test.Run(); + // } + [Test] - [TestCaseSource(typeof(Equality.Cases))] - [TestCaseSource(typeof(Order.Cases))] - public void Run(Test test) + public void FakeTest() { - test.Run(); + Assert.Pass(); } } } \ No newline at end of file From 9e0c7b12f491c5fedc3c0c3833f2b458af774856 Mon Sep 17 00:00:00 2001 From: pepelev Date: Tue, 30 Sep 2025 14:51:05 +0500 Subject: [PATCH 5/6] uncomment some tests --- src/Comparation.Tests/EqualityShould.cs | 466 ++++++++++++------------ 1 file changed, 233 insertions(+), 233 deletions(-) diff --git a/src/Comparation.Tests/EqualityShould.cs b/src/Comparation.Tests/EqualityShould.cs index 97b709e..280f4d0 100644 --- a/src/Comparation.Tests/EqualityShould.cs +++ b/src/Comparation.Tests/EqualityShould.cs @@ -1,233 +1,233 @@ -// using System.Collections.Generic; -// using FluentAssertions; -// using NUnit.Framework; -// -// namespace Comparation.Tests -// { -// public sealed class EqualityShould -// { -// public static TestCaseData[] EqualityCases => new[] -// { -// new TestCaseData(StringByLength, "Hello", "world").Returns(true).SetName("positive single by"), -// new TestCaseData(StringByLength, "Quick", "fox").Returns(false).SetName("negative single by"), -// -// new TestCaseData(StringByReference, "Hello", "Hello").Returns(true).SetName("positive by reference (interning)"), -// new TestCaseData(StringByReference, "Quick", string.Concat("Qui", "ck")).Returns(false).SetName("negative by reference"), -// -// new TestCaseData( -// StringByFirstLetterCaseInsensitively, -// "Firmware", -// "fox" -// ).Returns(true).SetName("positive single by with equality"), -// new TestCaseData( -// StringByFirstLetterCaseInsensitively, -// "Yeti", -// "Bigfoot" -// ).Returns(false).SetName("negative single by with equality"), -// -// new TestCaseData( -// StringByLengthAndFirstLetter, -// "Brown", -// "Beast" -// ).Returns(true).SetName("positive and-by"), -// new TestCaseData( -// StringByLengthAndFirstLetter, -// "Apple", -// "Alpine" -// ).Returns(false).SetName("negative and-by on first field"), -// new TestCaseData( -// StringByLengthAndFirstLetter, -// "Fear", -// "Calm" -// ).Returns(false).SetName("negative and-by on second field"), -// -// new TestCaseData( -// StringByLengthAndFirstLetterCaseInsensitively, -// "Brown", -// "blast" -// ).Returns(true).SetName("positive and-by with equality"), -// new TestCaseData( -// StringByLengthAndFirstLetterCaseInsensitively, -// "Apple", -// "Alpine" -// ).Returns(false).SetName("negative and-by with equality on first field"), -// new TestCaseData( -// StringByLengthAndFirstLetterCaseInsensitively, -// "Fear", -// "Calm" -// ).Returns(false).SetName("negative and-by with equality on second field"), -// -// new TestCaseData( -// StringByLengthAndUsingFirstLetterCaseInsensitively, -// "Brown", -// "blast" -// ).Returns(true).SetName("positive and-by with equality"), -// new TestCaseData( -// StringByLengthAndUsingFirstLetterCaseInsensitively, -// "Apple", -// "Alpine" -// ).Returns(false).SetName("negative and-by with equality on first field"), -// new TestCaseData( -// StringByLengthAndUsingFirstLetterCaseInsensitively, -// "Fear", -// "Calm" -// ).Returns(false).SetName("negative and-by with equality on second field"), -// -// new TestCaseData( -// StringCompositeByLengthFirstLetterCaseInsensitively, -// "Brown", -// "blast" -// ).Returns(true).SetName("positive and-by with equality"), -// new TestCaseData( -// StringCompositeByLengthFirstLetterCaseInsensitively, -// "Apple", -// "Alpine" -// ).Returns(false).SetName("negative and-by with equality on first field"), -// new TestCaseData( -// StringCompositeByLengthFirstLetterCaseInsensitively, -// "Fear", -// "Calm" -// ).Returns(false).SetName("negative and-by with equality on second field"), -// -// new TestCaseData( -// StringCompositeCollectionByLengthFirstLetterCaseInsensitively, -// "Brown", -// "blast" -// ).Returns(true).SetName("positive and-by with equality"), -// new TestCaseData( -// StringCompositeCollectionByLengthFirstLetterCaseInsensitively, -// "Apple", -// "Alpine" -// ).Returns(false).SetName("negative and-by with equality on first field"), -// new TestCaseData( -// StringCompositeCollectionByLengthFirstLetterCaseInsensitively, -// "Fear", -// "Calm" -// ).Returns(false).SetName("negative and-by with equality on second field") -// }; -// -// private static IEqualityComparer StringByLength => Comparation.Equality.Of().By(@string => @string.Length); -// private static IEqualityComparer StringByReference => Comparation.Equality.ByReference(); -// -// private static IEqualityComparer StringByFirstLetterCaseInsensitively => Comparation.Equality.Of().By( -// @string => @string[0], -// CharCaseInsensitively -// ); -// -// private static IEqualityComparer CharCaseInsensitively => Comparation.Equality.Of().By(char.ToLowerInvariant); -// -// private static IEqualityComparer StringByLengthAndFirstLetter => -// StringByLength.AndBy(@string => @string[0]); -// -// private static IEqualityComparer StringByLengthAndFirstLetterCaseInsensitively => -// StringByLength.AndBy(@string => @string[0], CharCaseInsensitively); -// -// private static IEqualityComparer StringByLengthAndUsingFirstLetterCaseInsensitively => -// StringByLength.AndUsing(StringByFirstLetterCaseInsensitively); -// -// private static IEqualityComparer StringCompositeByLengthFirstLetterCaseInsensitively => -// Comparation.Equality.Of().Composite( -// StringByLength, -// StringByFirstLetterCaseInsensitively -// ); -// -// private static IEqualityComparer StringCompositeCollectionByLengthFirstLetterCaseInsensitively => -// Comparation.Equality.Of().Composite( -// new List> -// { -// StringByLength, -// StringByFirstLetterCaseInsensitively -// } -// ); -// -// private static IEqualityComparer> StringCollection => -// Comparation.Equality.Of().Collection(); -// -// private static IEqualityComparer> StringSequence => -// Comparation.Equality.Of().Sequence(); -// -// public static TestCaseData[] Equalities => new[] -// { -// new TestCaseData(StringByLength).SetName(nameof(StringByLength)), -// new TestCaseData(StringByReference).SetName(nameof(StringByReference)), -// new TestCaseData(StringByFirstLetterCaseInsensitively) -// .SetName(nameof(StringByFirstLetterCaseInsensitively)), -// new TestCaseData(StringByLengthAndFirstLetter).SetName(nameof(StringByLengthAndFirstLetter)), -// new TestCaseData(StringByLengthAndFirstLetterCaseInsensitively) -// .SetName(nameof(StringByLengthAndFirstLetterCaseInsensitively)), -// new TestCaseData(StringByLengthAndUsingFirstLetterCaseInsensitively) -// .SetName(nameof(StringByLengthAndUsingFirstLetterCaseInsensitively)), -// new TestCaseData(StringCompositeByLengthFirstLetterCaseInsensitively) -// .SetName(nameof(StringCompositeByLengthFirstLetterCaseInsensitively)), -// new TestCaseData(StringCompositeCollectionByLengthFirstLetterCaseInsensitively) -// .SetName(nameof(StringCompositeCollectionByLengthFirstLetterCaseInsensitively)) -// }; -// -// public static TestCaseData[] EqualitiesWithArgument => new[] -// { -// new TestCaseData(StringByLength, "Dog").SetName(nameof(StringByLength)), -// new TestCaseData(StringByReference, "And").SetName(nameof(StringByReference)), -// new TestCaseData(StringByFirstLetterCaseInsensitively, "Cat") -// .SetName(nameof(StringByFirstLetterCaseInsensitively)), -// new TestCaseData(StringByLengthAndFirstLetter, "Are").SetName(nameof(StringByLengthAndFirstLetter)), -// new TestCaseData(StringByLengthAndFirstLetterCaseInsensitively, "Friends") -// .SetName(nameof(StringByLengthAndFirstLetterCaseInsensitively)), -// new TestCaseData(StringByLengthAndUsingFirstLetterCaseInsensitively, "Believe") -// .SetName(nameof(StringByLengthAndUsingFirstLetterCaseInsensitively)), -// new TestCaseData(StringCompositeByLengthFirstLetterCaseInsensitively, "Me") -// .SetName(nameof(StringCompositeByLengthFirstLetterCaseInsensitively)), -// new TestCaseData(StringCompositeCollectionByLengthFirstLetterCaseInsensitively, "Pal") -// .SetName(nameof(StringCompositeCollectionByLengthFirstLetterCaseInsensitively)) -// }; -// -// [Test] -// [TestCaseSource(nameof(EqualityCases))] -// public bool DefineEquality(IEqualityComparer equality, T a, T b) => equality.Equals(a, b); -// -// [Test] -// [TestCase(new string[0], new string[0], ExpectedResult = true)] -// [TestCase(new[] {"Dog"}, new string[0], ExpectedResult = false)] -// [TestCase(new[] {"Dog"}, new[] {"Dog"}, ExpectedResult = true)] -// [TestCase(new[] {"Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] -// [TestCase(new[] {"Dog"}, new[] {"Cat"}, ExpectedResult = false)] -// [TestCase(new[] {"Dog", "Cat"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] -// [TestCase(new[] {"Cat", "Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] -// [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Cat"}, ExpectedResult = false)] -// [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = true)] -// public bool DefineEqualityOnCollections(string[] a, string[] b) => StringCollection.Equals(a, b); -// -// [Test] -// [TestCase(new string[0], new string[0], ExpectedResult = true)] -// [TestCase(new[] {"Dog"}, new string[0], ExpectedResult = false)] -// [TestCase(new[] {"Dog"}, new[] {"Dog"}, ExpectedResult = true)] -// [TestCase(new[] {"Dog"}, new[] {"Cat"}, ExpectedResult = false)] -// [TestCase(new[] {"Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] -// [TestCase(new[] {"Dog", "Cat"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] -// [TestCase(new[] {"Cat", "Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] -// [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Cat"}, ExpectedResult = false)] -// [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = false)] -// [TestCase(new[] {"Dog", "Cat", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = true)] -// public bool DefineEqualityOnSequences(string[] a, string[] b) => StringSequence.Equals(a, b); -// -// [Test] -// [TestCaseSource(nameof(EqualitiesWithArgument))] -// public void WorkWithFirstArgumentNull(IEqualityComparer equality, T b) where T : class -// { -// equality.Equals(null, b).Should().BeFalse(); -// } -// -// [Test] -// [TestCaseSource(nameof(EqualitiesWithArgument))] -// public void WorkWithSecondArgumentNull(IEqualityComparer equality, T a) where T : class -// { -// equality.Equals(a, null).Should().BeFalse(); -// } -// -// [Test] -// [TestCaseSource(nameof(Equalities))] -// public void TreatBothNullsAsEqual(IEqualityComparer equality) -// { -// equality.Equals(null, null).Should().BeTrue(); -// } -// } -// } \ No newline at end of file +using System.Collections.Generic; +using FluentAssertions; +using NUnit.Framework; + +namespace Comparation.Tests +{ + public sealed class EqualityShould + { + public static TestCaseData[] EqualityCases => new[] + { + new TestCaseData(StringByLength, "Hello", "world").Returns(true).SetName("positive single by"), + new TestCaseData(StringByLength, "Quick", "fox").Returns(false).SetName("negative single by"), + + new TestCaseData(StringByReference, "Hello", "Hello").Returns(true).SetName("positive by reference (interning)"), + new TestCaseData(StringByReference, "Quick", string.Concat("Qui", "ck")).Returns(false).SetName("negative by reference"), + + new TestCaseData( + StringByFirstLetterCaseInsensitively, + "Firmware", + "fox" + ).Returns(true).SetName("positive single by with equality"), + new TestCaseData( + StringByFirstLetterCaseInsensitively, + "Yeti", + "Bigfoot" + ).Returns(false).SetName("negative single by with equality"), + + new TestCaseData( + StringByLengthAndFirstLetter, + "Brown", + "Beast" + ).Returns(true).SetName("positive and-by"), + new TestCaseData( + StringByLengthAndFirstLetter, + "Apple", + "Alpine" + ).Returns(false).SetName("negative and-by on first field"), + new TestCaseData( + StringByLengthAndFirstLetter, + "Fear", + "Calm" + ).Returns(false).SetName("negative and-by on second field"), + + new TestCaseData( + StringByLengthAndFirstLetterCaseInsensitively, + "Brown", + "blast" + ).Returns(true).SetName("positive and-by with equality"), + new TestCaseData( + StringByLengthAndFirstLetterCaseInsensitively, + "Apple", + "Alpine" + ).Returns(false).SetName("negative and-by with equality on first field"), + new TestCaseData( + StringByLengthAndFirstLetterCaseInsensitively, + "Fear", + "Calm" + ).Returns(false).SetName("negative and-by with equality on second field"), + + new TestCaseData( + StringByLengthAndUsingFirstLetterCaseInsensitively, + "Brown", + "blast" + ).Returns(true).SetName("positive and-by with equality"), + new TestCaseData( + StringByLengthAndUsingFirstLetterCaseInsensitively, + "Apple", + "Alpine" + ).Returns(false).SetName("negative and-by with equality on first field"), + new TestCaseData( + StringByLengthAndUsingFirstLetterCaseInsensitively, + "Fear", + "Calm" + ).Returns(false).SetName("negative and-by with equality on second field"), + + new TestCaseData( + StringCompositeByLengthFirstLetterCaseInsensitively, + "Brown", + "blast" + ).Returns(true).SetName("positive and-by with equality"), + new TestCaseData( + StringCompositeByLengthFirstLetterCaseInsensitively, + "Apple", + "Alpine" + ).Returns(false).SetName("negative and-by with equality on first field"), + new TestCaseData( + StringCompositeByLengthFirstLetterCaseInsensitively, + "Fear", + "Calm" + ).Returns(false).SetName("negative and-by with equality on second field"), + + new TestCaseData( + StringCompositeCollectionByLengthFirstLetterCaseInsensitively, + "Brown", + "blast" + ).Returns(true).SetName("positive and-by with equality"), + new TestCaseData( + StringCompositeCollectionByLengthFirstLetterCaseInsensitively, + "Apple", + "Alpine" + ).Returns(false).SetName("negative and-by with equality on first field"), + new TestCaseData( + StringCompositeCollectionByLengthFirstLetterCaseInsensitively, + "Fear", + "Calm" + ).Returns(false).SetName("negative and-by with equality on second field") + }; + + private static IEqualityComparer StringByLength => Comparation.Equality.Of().By(@string => @string.Length); + private static IEqualityComparer StringByReference => Comparation.Equality.ByReference(); + + private static IEqualityComparer StringByFirstLetterCaseInsensitively => Comparation.Equality.Of().By( + @string => @string[0], + CharCaseInsensitively + ); + + private static IEqualityComparer CharCaseInsensitively => Comparation.Equality.Of().By(char.ToLowerInvariant); + + private static IEqualityComparer StringByLengthAndFirstLetter => + StringByLength.AndBy(@string => @string[0]); + + private static IEqualityComparer StringByLengthAndFirstLetterCaseInsensitively => + StringByLength.AndBy(@string => @string[0], CharCaseInsensitively); + + private static IEqualityComparer StringByLengthAndUsingFirstLetterCaseInsensitively => + StringByLength.AndUsing(StringByFirstLetterCaseInsensitively); + + private static IEqualityComparer StringCompositeByLengthFirstLetterCaseInsensitively => + Comparation.Equality.Of().Composite( + StringByLength, + StringByFirstLetterCaseInsensitively + ); + + private static IEqualityComparer StringCompositeCollectionByLengthFirstLetterCaseInsensitively => + Comparation.Equality.Of().Composite( + new List> + { + StringByLength, + StringByFirstLetterCaseInsensitively + } + ); + + private static IEqualityComparer> StringCollection => + Comparation.Equality.Of().Collection(); + + private static IEqualityComparer> StringSequence => + Comparation.Equality.Of().Sequence(); + + public static TestCaseData[] Equalities => new[] + { + new TestCaseData(StringByLength).SetName(nameof(StringByLength)), + new TestCaseData(StringByReference).SetName(nameof(StringByReference)), + new TestCaseData(StringByFirstLetterCaseInsensitively) + .SetName(nameof(StringByFirstLetterCaseInsensitively)), + new TestCaseData(StringByLengthAndFirstLetter).SetName(nameof(StringByLengthAndFirstLetter)), + new TestCaseData(StringByLengthAndFirstLetterCaseInsensitively) + .SetName(nameof(StringByLengthAndFirstLetterCaseInsensitively)), + new TestCaseData(StringByLengthAndUsingFirstLetterCaseInsensitively) + .SetName(nameof(StringByLengthAndUsingFirstLetterCaseInsensitively)), + new TestCaseData(StringCompositeByLengthFirstLetterCaseInsensitively) + .SetName(nameof(StringCompositeByLengthFirstLetterCaseInsensitively)), + new TestCaseData(StringCompositeCollectionByLengthFirstLetterCaseInsensitively) + .SetName(nameof(StringCompositeCollectionByLengthFirstLetterCaseInsensitively)) + }; + + public static TestCaseData[] EqualitiesWithArgument => new[] + { + new TestCaseData(StringByLength, "Dog").SetName(nameof(StringByLength)), + new TestCaseData(StringByReference, "And").SetName(nameof(StringByReference)), + new TestCaseData(StringByFirstLetterCaseInsensitively, "Cat") + .SetName(nameof(StringByFirstLetterCaseInsensitively)), + new TestCaseData(StringByLengthAndFirstLetter, "Are").SetName(nameof(StringByLengthAndFirstLetter)), + new TestCaseData(StringByLengthAndFirstLetterCaseInsensitively, "Friends") + .SetName(nameof(StringByLengthAndFirstLetterCaseInsensitively)), + new TestCaseData(StringByLengthAndUsingFirstLetterCaseInsensitively, "Believe") + .SetName(nameof(StringByLengthAndUsingFirstLetterCaseInsensitively)), + new TestCaseData(StringCompositeByLengthFirstLetterCaseInsensitively, "Me") + .SetName(nameof(StringCompositeByLengthFirstLetterCaseInsensitively)), + new TestCaseData(StringCompositeCollectionByLengthFirstLetterCaseInsensitively, "Pal") + .SetName(nameof(StringCompositeCollectionByLengthFirstLetterCaseInsensitively)) + }; + + [Test] + [TestCaseSource(nameof(EqualityCases))] + public bool DefineEquality(IEqualityComparer equality, T a, T b) => equality.Equals(a, b); + + [Test] + [TestCase(new string[0], new string[0], ExpectedResult = true)] + [TestCase(new[] {"Dog"}, new string[0], ExpectedResult = false)] + [TestCase(new[] {"Dog"}, new[] {"Dog"}, ExpectedResult = true)] + [TestCase(new[] {"Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] + [TestCase(new[] {"Dog"}, new[] {"Cat"}, ExpectedResult = false)] + [TestCase(new[] {"Dog", "Cat"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] + [TestCase(new[] {"Cat", "Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] + [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Cat"}, ExpectedResult = false)] + [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = true)] + public bool DefineEqualityOnCollections(string[] a, string[] b) => StringCollection.Equals(a, b); + + [Test] + [TestCase(new string[0], new string[0], ExpectedResult = true)] + [TestCase(new[] {"Dog"}, new string[0], ExpectedResult = false)] + [TestCase(new[] {"Dog"}, new[] {"Dog"}, ExpectedResult = true)] + [TestCase(new[] {"Dog"}, new[] {"Cat"}, ExpectedResult = false)] + [TestCase(new[] {"Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] + [TestCase(new[] {"Dog", "Cat"}, new[] {"Dog", "Cat"}, ExpectedResult = true)] + [TestCase(new[] {"Cat", "Dog"}, new[] {"Dog", "Cat"}, ExpectedResult = false)] + [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Cat"}, ExpectedResult = false)] + [TestCase(new[] {"Cat", "Dog", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = false)] + [TestCase(new[] {"Dog", "Cat", "Dog"}, new[] {"Dog", "Cat", "Dog"}, ExpectedResult = true)] + public bool DefineEqualityOnSequences(string[] a, string[] b) => StringSequence.Equals(a, b); + + [Test] + [TestCaseSource(nameof(EqualitiesWithArgument))] + public void WorkWithFirstArgumentNull(IEqualityComparer equality, T b) where T : class + { + equality.Equals(null, b).Should().BeFalse(); + } + + [Test] + [TestCaseSource(nameof(EqualitiesWithArgument))] + public void WorkWithSecondArgumentNull(IEqualityComparer equality, T a) where T : class + { + equality.Equals(a, null).Should().BeFalse(); + } + + [Test] + [TestCaseSource(nameof(Equalities))] + public void TreatBothNullsAsEqual(IEqualityComparer equality) + { + equality.Equals(null, null).Should().BeTrue(); + } + } +} \ No newline at end of file From 8ece06bda86466514fe02b62e38115bbe9ab5536 Mon Sep 17 00:00:00 2001 From: pepelev Date: Tue, 30 Sep 2025 16:27:05 +0500 Subject: [PATCH 6/6] Uncomment all tests --- src/Comparation.Tests/TestsEntryPoint.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Comparation.Tests/TestsEntryPoint.cs b/src/Comparation.Tests/TestsEntryPoint.cs index 8159b9f..5d6e5f3 100644 --- a/src/Comparation.Tests/TestsEntryPoint.cs +++ b/src/Comparation.Tests/TestsEntryPoint.cs @@ -8,13 +8,13 @@ namespace Comparation.Tests [Parallelizable(ParallelScope.All)] public sealed class TestsEntryPoint { - // [Test] - // [TestCaseSource(typeof(Equality.Cases))] - // [TestCaseSource(typeof(Order.Cases))] - // public void Run(Test test) - // { - // test.Run(); - // } + [Test] + [TestCaseSource(typeof(Equality.Cases))] + [TestCaseSource(typeof(Order.Cases))] + public void Run(Test test) + { + test.Run(); + } [Test] public void FakeTest()